/// <summary>
 /// ヘルムホルツの方程式 剛性行列 残差ベクトルの追加
 /// </summary>
 /// <param name="ls"></param>
 /// <param name="waveLength"></param>
 /// <param name="world"></param>
 /// <param name="fieldValId"></param>
 /// <returns></returns>
 public static bool AddLinSysHelmholtz(CZLinearSystem ls, double waveLength, CFieldWorld world, uint fieldValId)
 {
     if (!world.IsIdField(fieldValId))
     {
         return false;
     }
     CField valField = world.GetField(fieldValId);
     if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
     {
         return false;
     }
     IList<uint> aIdEA = valField.GetAryIdEA();
     foreach (uint eaId in aIdEA)
     {
         if (valField.GetInterpolationType(eaId, world) == INTERPOLATION_TYPE.TRI11)
         {
             uint ntmp = ls.GetTmpBufferSize();
             int[] tmpBuffer = new int[ntmp];
             for (int i = 0; i < ntmp; i++)
             {
                 tmpBuffer[i] = -1;
             }
             bool res = AddLinSysHelmholtz_EachElementAry(ls, waveLength, world, fieldValId, eaId, tmpBuffer);
             if (!res)
             {
                 return false;
             }
         }
     }
     return true;
 }
Beispiel #2
0
 /// <summary>
 /// 境界上の節点番号と座標の取得
 /// </summary>
 /// <param name="world">ワールド座標系</param>
 /// <param name="fieldValId">フィールド値ID</param>
 /// <param name="no_c_all">全体節点番号配列</param>
 /// <param name="to_no_boundary">全体節点番号→境界上の節点番号のマップ</param>
 /// <param name="coord_c_all">座標リスト</param>
 /// <returns></returns>
 public static bool GetBoundaryCoordList(
     CFieldWorld world, uint fieldValId,
     out uint[] no_c_all, out Dictionary <uint, uint> to_no_boundary, out double[][] coord_c_all)
 {
     return(GetBoundaryCoordList(
                world, fieldValId,
                0.0, null,
                out no_c_all, out to_no_boundary, out coord_c_all));
 }
Beispiel #3
0
 /// <summary>
 /// ループ内の節点番号と座標の取得
 /// </summary>
 /// <param name="world">ワールド座標系</param>
 /// <param name="fieldValId">フィールド値ID</param>
 /// <param name="no_c_all">全体節点番号配列</param>
 /// <param name="to_no_boundary">全体節点番号→境界上の節点番号のマップ</param>
 /// <param name="coord_c_all">座標リスト</param>
 /// <returns></returns>
 public static bool GetLoopCoordList(
     CFieldWorld world, uint fieldValId,
     out uint[] no_c_all, out Dictionary <uint, uint> to_no_loop, out double[][] coord_c_all, out uint[][] elem_no_c, out uint[] elem_loopId)
 {
     return(GetLoopCoordList(
                world, fieldValId,
                0.0, null,
                out no_c_all, out to_no_loop, out coord_c_all, out elem_no_c, out elem_loopId));
 }
Beispiel #4
0
        /// <summary>
        /// 境界上の節点番号と座標の取得
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">フィールド値ID</param>
        /// <param name="no_c_all">全体節点番号配列</param>
        /// <param name="to_no_boundary">全体節点番号→境界上の節点番号のマップ</param>
        /// <param name="coord_c_all">座標リスト</param>
        /// <returns></returns>
        public static bool GetBoundaryCoordList(
            CFieldWorld world, uint fieldValId,
            double rotAngle, double[] rotOrigin,
            out uint[] no_c_all, out Dictionary <uint, uint> to_no_boundary, out double[][] coord_c_all)
        {
            no_c_all       = null;
            to_no_boundary = null;
            coord_c_all    = null;

            // フィールドを取得
            CField valField = world.GetField(fieldValId);

            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return(false);
            }
            IList <uint> aIdEA = valField.GetAryIdEA();

            // 全体節点番号→境界節点番号変換テーブル(to_no_boundary)作成
            to_no_boundary = new Dictionary <uint, uint>();
            IList <double[]> coord_c_list = new List <double[]>();

            foreach (uint eaId in aIdEA)
            {
                bool res = getBoundaryCoordList_EachElementAry(
                    world, fieldValId, eaId,
                    rotAngle, rotOrigin,
                    ref to_no_boundary, ref coord_c_list);
                if (!res)
                {
                    return(false);
                }
            }
            //境界節点番号→全体節点番号変換テーブル(no_c_all)作成
            no_c_all = new uint[to_no_boundary.Count];
            foreach (KeyValuePair <uint, uint> kvp in to_no_boundary)
            {
                uint ino_boundary = kvp.Value;
                uint ino          = kvp.Key;
                no_c_all[ino_boundary] = ino;
            }
            coord_c_all = coord_c_list.ToArray();

            return(true);
        }
Beispiel #5
0
        /// <summary>
        ///  欠陥部セルのメッシュ取得
        /// </summary>
        /// <param name="ndivForOneLattice">格子1辺の分割数</param>
        /// <param name="ptsInCell">セル内節点の座標リスト</param>
        /// <param name="nodeBInCell">セル境界節点の節点番号リスト</param>
        /// <param name="elemNodeInCell">要素内節点の節点番号リスト</param>
        public static void GetCellMesh_Defect_TriFirstOrder(
            int ndivForOneLattice,
            out double[,] ptsInCell,
            out uint[,] nodeBInCell,
            out uint[,] elemNodeInCell
            )
        {
            uint[] dummy_elemLoopIdInCell = null;
            uint   dummy_RodLoopId        = 0;
            double dummy_rodRadiusRatio   = 0.0;
            int    dummy_rodCircleDiv     = 0;
            int    dummy_rodRadiusDiv     = 0;

            uint         FieldValId     = 0;
            uint         FieldLoopId    = 0;
            uint         FieldForceBcId = 0;
            IList <uint> FieldPortBcIds = new List <uint>();
            CFieldWorld  World          = new CFieldWorld();

            mkMeshCell_Rod_Tri_FirstOrder(
                false, /* isRodCell : fase 欠陥部 true ロッド部 */
                ndivForOneLattice,
                dummy_rodRadiusRatio,
                dummy_rodCircleDiv,
                dummy_rodRadiusDiv,
                ref World,
                ref FieldValId,
                ref FieldLoopId,
                ref FieldForceBcId,
                ref FieldPortBcIds,
                out dummy_RodLoopId);
            getCoordListFromMeshCell_Tri_FirstOrder(
                World,
                FieldLoopId,
                FieldForceBcId,
                FieldPortBcIds,
                out ptsInCell,
                out nodeBInCell,
                out dummy_elemLoopIdInCell,
                out elemNodeInCell
                );

            World.Dispose();
            World = null;
        }
Beispiel #6
0
        /// <summary>
        ///  欠陥部セルのメッシュ取得
        /// </summary>
        /// <param name="ndivForOneLattice">格子1辺の分割数</param>
        /// <param name="ptsInCell">セル内節点の座標リスト</param>
        /// <param name="nodeBInCell">セル境界節点の節点番号リスト</param>
        /// <param name="elemNodeInCell">要素内節点の節点番号リスト</param>
        public static void GetCellMesh_Defect_TriFirstOrder(
            int ndivForOneLattice,
            out double[,] ptsInCell,
            out uint[,] nodeBInCell,
            out uint[,] elemNodeInCell
            )
        {
            uint[] dummy_elemLoopIdInCell = null;
            uint dummy_RodLoopId = 0;
            double dummy_rodRadiusRatio = 0.0;
            int dummy_rodCircleDiv = 0;
            int dummy_rodRadiusDiv = 0;

            uint FieldValId = 0;
            uint FieldLoopId = 0;
            uint FieldForceBcId = 0;
            IList<uint> FieldPortBcIds = new List<uint>();
            CFieldWorld World = new CFieldWorld();
            mkMeshCell_Rod_Tri_FirstOrder(
                false, /* isRodCell : fase 欠陥部 true ロッド部 */
                ndivForOneLattice,
                dummy_rodRadiusRatio,
                dummy_rodCircleDiv,
                dummy_rodRadiusDiv,
                ref World,
                ref FieldValId,
                ref FieldLoopId,
                ref FieldForceBcId,
                ref FieldPortBcIds,
                out dummy_RodLoopId);
            getCoordListFromMeshCell_Tri_FirstOrder(
                World,
                FieldLoopId,
                FieldForceBcId,
                FieldPortBcIds,
                out ptsInCell,
                out nodeBInCell,
                out dummy_elemLoopIdInCell,
                out elemNodeInCell
                );

            World.Dispose();
            World = null;
        }
Beispiel #7
0
        /// <summary>
        /// ロッド部セルメッシュの取得
        /// </summary>
        /// <param name="ndivForOneLattice">格子1辺の分割数</param>
        /// <param name="rodRadiusRatio">ロッドの半径割合</param>
        /// <param name="rodCircleDiv">ロッドの円周方向分割数</param>
        /// <param name="rodRadiusDiv">ロッドの半径方向分割数(1でもメッシュサイズが小さければ複数に分割される)</param>
        /// <param name="ptsInCell">セル内節点の座標リスト</param>
        /// <param name="nodeBInCell">セル境界節点の節点番号リスト</param>
        /// <param name="elemLoopIdInCell">セル内要素のワールド座標系ループIDリスト</param>
        /// <param name="RodLoopId">ロッドのワールド座標系ループID</param>
        /// <param name="elemNodeInCell">要素内節点の節点番号リスト</param>
        public static void GetCellMesh_Rod_TriFirstOrder(
            int ndivForOneLattice,
            double rodRadiusRatio,
            int rodCircleDiv,
            int rodRadiusDiv,
            out double[,] ptsInCell,
            out uint[,] nodeBInCell,
            out uint[] elemLoopIdInCell,
            out uint RodLoopId,
            out uint[,] elemNodeInCell
            )
        {
            uint         FieldValId     = 0;
            uint         FieldLoopId    = 0;
            uint         FieldForceBcId = 0;
            IList <uint> FieldPortBcIds = new List <uint>();
            CFieldWorld  World          = new CFieldWorld();

            mkMeshCell_Rod_Tri_FirstOrder(
                true, /* isRodCell */
                ndivForOneLattice,
                rodRadiusRatio,
                rodCircleDiv,
                rodRadiusDiv,
                ref World,
                ref FieldValId,
                ref FieldLoopId,
                ref FieldForceBcId,
                ref FieldPortBcIds,
                out RodLoopId);
            getCoordListFromMeshCell_Tri_FirstOrder(
                World,
                FieldLoopId,
                FieldForceBcId,
                FieldPortBcIds,
                out ptsInCell,
                out nodeBInCell,
                out elemLoopIdInCell,
                out elemNodeInCell
                );

            World.Dispose();
            World = null;
        }
Beispiel #8
0
        /// <summary>
        /// 境界上の節点番号の取得(要素アレイ単位)
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">フィールド値ID</param>
        /// <param name="eaId">要素アレイID</param>
        /// <param name="to_no_boundary">全体節点番号→境界上節点番号マップ</param>
        /// <returns></returns>
        private static bool getBoundaryNodeList_EachElementAry(CFieldWorld world, uint fieldValId, uint eaId, Dictionary <uint, uint> to_no_boundary)
        {
            // 要素アレイを取得する
            CElemAry ea = world.GetEA(eaId);

            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.LINE);
            if (ea.ElemType() != ELEM_TYPE.LINE)
            {
                return(false);
            }

            // フィールドを取得
            CField valField = world.GetField(fieldValId);

            // 座標セグメントを取得
            CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, world);

            //境界節点番号→全体節点番号変換テーブル(no_c_all)作成
            // 全体節点番号→境界節点番号変換テーブル(to_no_boundary)作成
            uint node_cnt = ea.Size() + 1;  // 全節点数

            // 線要素の節点数
            uint nno = 2;

            uint[] no_c = new uint[nno]; // 要素節点の全体節点番号

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);

                for (uint ino = 0; ino < nno; ino++)
                {
                    if (!to_no_boundary.ContainsKey(no_c[ino]))
                    {
                        uint ino_boundary_tmp = (uint)to_no_boundary.Count;
                        to_no_boundary[no_c[ino]] = ino_boundary_tmp;
                    }
                }
            }
            return(true);
        }
Beispiel #9
0
        public const double eps0 = 8.85418782e-12;//1.0 / (mu0 * c0 * c0);

        /// <summary>
        /// 境界上の節点番号の取得
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">フィールド値ID</param>
        /// <param name="no_c_all">全体節点番号配列</param>
        /// <param name="to_no_boundary">全体節点番号→境界上の節点番号のマップ</param>
        /// <returns></returns>
        public static bool GetBoundaryNodeList(CFieldWorld world, uint fieldValId, out uint[] no_c_all, out Dictionary <uint, uint> to_no_boundary)
        {
            no_c_all       = null;
            to_no_boundary = null;

            // フィールドを取得
            CField valField = world.GetField(fieldValId);

            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return(false);
            }
            IList <uint> aIdEA = valField.GetAryIdEA();

            // 全体節点番号→境界節点番号変換テーブル(to_no_boundary)作成
            to_no_boundary = new Dictionary <uint, uint>();

            foreach (uint eaId in aIdEA)
            {
                bool res = getBoundaryNodeList_EachElementAry(world, fieldValId, eaId, to_no_boundary);
                if (!res)
                {
                    return(false);
                }
            }
            //境界節点番号→全体節点番号変換テーブル(no_c_all)作成
            no_c_all = new uint[to_no_boundary.Count];
            foreach (KeyValuePair <uint, uint> kvp in to_no_boundary)
            {
                uint ino_boundary = kvp.Value;
                uint ino          = kvp.Key;
                no_c_all[ino_boundary] = ino;
            }

            return(true);
        }
Beispiel #10
0
        /// <summary>
        /// ループ内の節点番号と座標の取得
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">フィールド値ID</param>
        /// <param name="no_c_all">全体節点番号配列</param>
        /// <param name="to_no_boundary">全体節点番号→境界上の節点番号のマップ</param>
        /// <param name="coord_c_all">座標リスト</param>
        /// <returns></returns>
        public static bool GetLoopCoordList(CFieldWorld world, uint fieldValId,
                                            double rotAngle, double[] rotOrigin,
                                            out uint[] no_c_all, out Dictionary <uint, uint> to_no_loop, out double[][] coord_c_all, out uint[][] elem_no_c, out uint[] elem_loopId)
        {
            no_c_all    = null;
            to_no_loop  = null;
            coord_c_all = null;
            elem_no_c   = null;
            elem_loopId = null;

            // フィールドを取得
            CField valField = world.GetField(fieldValId);

            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return(false);
            }
            IList <uint> aIdEA = valField.GetAryIdEA();

            // 全体節点番号→ループ内節点番号変換テーブル作成
            to_no_loop = new Dictionary <uint, uint>();
            IList <double[]> coord_c_list = new List <double[]>();

            // 要素の節点番号リスト
            IList <uint[]> elem_no_c_list = new List <uint[]>();
            // 要素のループIDリスト
            IList <uint> elem_loopId_list = new List <uint>();

            foreach (uint eaId in aIdEA)
            {
                bool res = getLoopCoordList_EachElementAry(
                    world, fieldValId, eaId,
                    rotAngle, rotOrigin,
                    ref to_no_loop, ref coord_c_list, ref elem_no_c_list, ref elem_loopId_list);
                if (!res)
                {
                    return(false);
                }
            }
            //境界節点番号→全体節点番号変換テーブル(no_c_all)作成
            no_c_all = new uint[to_no_loop.Count];
            foreach (KeyValuePair <uint, uint> kvp in to_no_loop)
            {
                uint ino_boundary = kvp.Value;
                uint ino          = kvp.Key;
                no_c_all[ino_boundary] = ino;
            }
            coord_c_all = coord_c_list.ToArray();

            int elemCnt = elem_no_c_list.Count;

            elem_no_c   = new uint[elemCnt][];
            elem_loopId = new uint[elemCnt];
            for (int ie = 0; ie < elemCnt; ie++)
            {
                elem_no_c[ie] = new uint[3];
                for (int i = 0; i < 3; i++)
                {
                    elem_no_c[ie][i] = elem_no_c_list[ie][i];
                    elem_loopId[ie]  = elem_loopId_list[ie];
                }
            }

            return(true);
        }
Beispiel #11
0
        /// <summary>
        /// 直線導波管
        /// </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
            )
        {
            // 直線導波管
            // 導波管不連続領域の長さ
            double disconLength = WaveguideWidth * 0.05;
            // 周期構造距離
            periodicDistance = disconLength;
            // 格子定数(互換性の為設定)
            latticeA = 2.0 * WaveguideWidth;
            // 境界分割数
            const int ndiv = 20 * 3;
            // メッシュの長さ
            double meshL = 1.1 * WaveguideWidth / ndiv;
            // 波のモード
            WaveModeDv = WgUtil.WaveModeDV.TE;

            Beta1 = 0.0;
            Beta2 = 6.0;
            BetaDelta = 0.1;
            GraphBetaInterval = 2.0;

            MinNormalizedFreq = 0.0;
            MaxNormalizedFreq = 2.0;
            GraphFreqInterval = 0.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 baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                // ToDo: 周期境界1, 2上の分割が同じになるように設定する必要がある
                //
                IList<CVector2D> pts = new List<CVector2D>();
                pts.Add(new CVector2D(0, WaveguideWidth));
                pts.Add(new CVector2D(0.0, 0));
                pts.Add(new CVector2D(disconLength, 0.0));
                pts.Add(new CVector2D(disconLength, WaveguideWidth));
                cad2d.AddPolygon(pts);
                // 入出力導波路の周期構造境界上の頂点を追加
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // 入力導波路
                {
                    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);
                }
                // 図面表示
                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 = { 1 };
                int[] mediaIndex_list = { Medias.IndexOf(mediaVacumn) };
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                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(mediaVacumn);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndiv - 1) - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaVacumn);
                }
                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(mediaVacumn);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndiv - 1) * 2 - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaVacumn);
                }
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId2,
                    ref EdgeDic);
            }
            return true;
        }
        /// <summary>
        /// ヘルムホルツの方程式 剛性行列 残差ベクトルの追加(要素アレイ単位)
        /// </summary>
        /// <param name="ls"></param>
        /// <param name="waveLength"></param>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="eaId"></param>
        /// <param name="tmpBuffer"></param>
        /// <returns></returns>
        private static bool AddLinSysHelmholtz_EachElementAry(CZLinearSystem ls, double waveLength, CFieldWorld world, uint fieldValId, uint eaId, int[] tmpBuffer)
        {
            System.Diagnostics.Debug.Assert(world.IsIdEA(eaId));
            CElemAry ea = world.GetEA(eaId);
            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.TRI);
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            CField valField = world.GetField(fieldValId);
            CElemAry.CElemSeg es_c_va = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, true, world);
            CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, world);

            // 三角形要素の節点数
            uint nno = 3;
            // 座標の次元
            uint ndim = 2;
            // 要素節点の全体節点番号
            uint[] no_c = new uint[nno];
            // 要素節点の値
            Complex[] value_c = new Complex[nno];
            // 要素節点の座標
            double[][] coord_c = new double[nno][];
            for (int inoes = 0; inoes < nno; inoes++)
            {
                coord_c[inoes] = new double[ndim];
            }
            // 要素剛性行列のバッファ (i, j) --> (i * rowSize + j)
            Complex[] ematBuffer = new Complex[nno * nno];
            // 要素節点等価内力、外力、残差ベクトル
            Complex[] eres_c = new Complex[nno];
            // 要素剛性行列(コーナ-コーナー)
            CZMatDia_BlkCrs_Ptr mat_cc = ls.GetMatrixPtr(fieldValId, ELSEG_TYPE.CORNER, world);
            // 要素残差ベクトル(コーナー)
            CZVector_Blk_Ptr res_c = ls.GetResidualPtr(fieldValId, ELSEG_TYPE.CORNER, world);

            CNodeAry.CNodeSeg ns_c_val = valField.GetNodeSeg(ELSEG_TYPE.CORNER, true, world);
            CNodeAry.CNodeSeg ns_c_co = valField.GetNodeSeg(ELSEG_TYPE.CORNER, false, world);

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);
                // 座標を取得
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    double[] tmpval = null;
                    ns_c_co.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == ndim);

                    for (int i = 0; i < tmpval.Length; i++)
                    {
                        coord_c[inoes][i] = tmpval[i];
                    }
                    //Console.WriteLine("coord_c [" + no_c[inoes] + " ] = " + coord_c[inoes, 0] + " " +  coord_c[inoes, 1]);
                }
                // 節点の値を取って来る
                es_c_va.GetNodes(ielem, no_c);
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    Complex[] tmpval = null;
                    ns_c_val.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == 1);
                    value_c[inoes] = tmpval[0];
                    //Console.WriteLine("value_c [" + no_c[inoes] + " ] = " + tmpval[0].Real + " " +  tmpval[0].Imag);
                }

                // 節点座標
                double[] p1 = coord_c[0];
                double[] p2 = coord_c[1];
                double[] p3 = coord_c[2];
                // 面積を求める
                double area = CKerEMatTri.TriArea(p1, p2, p3);

                // 形状関数の微分を求める
                double[,] dldx = null;
                double[] const_term = null;
                CKerEMatTri.TriDlDx(out dldx, out const_term, p1, p2, p3);

                // 要素剛性行列を作る
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        //emat[ino, jno]
                        ematBuffer[ino * nno + jno] = area * (dldx[ino, 0] * dldx[jno, 0] + dldx[ino, 1] * dldx[jno, 1]);
                    }
                }
                double k0 = 2 * pi / waveLength;
                double tmp_val = k0 * k0 * area / 12.0;
                for (int ino = 0; ino < nno; ino++)
                {
                    //emat[ino, ino]
                    ematBuffer[ino * nno + ino] -= new Complex(tmp_val);
                    for (int jno = 0; jno < nno; jno++)
                    {
                        //emat[ino, jno]
                        ematBuffer[ino * nno + jno] -= new Complex(tmp_val);
                    }
                }
                // 要素節点等価内力ベクトルを求める
                for (int ino = 0; ino < nno; ino++)
                {
                    eres_c[ino] = new Complex(0.0);
                    for (int jno = 0; jno < nno; jno++)
                    {
                        eres_c[ino] -= ematBuffer[ino * nno + jno] * value_c[jno];
                    }
                }
                // 要素剛性行列にマージする
                mat_cc.Mearge(nno, no_c, nno, no_c, 1, ematBuffer, ref tmpBuffer);

                // 残差ベクトルにマージする
                for (int inoes = 0; inoes < nno; inoes++)
                {
                    res_c.AddValue(no_c[inoes], 0, eres_c[inoes]);
                }
            }

            return true;
        }
Beispiel #13
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;
        }
Beispiel #14
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;
        }
Beispiel #15
0
        /// <summary>
        /// FEM行列の作成
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="WaveguideWidth"></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="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="KMat"></param>
        /// <param name="MMat"></param>
        /// <param name="QbMatList"></param>
        /// <param name="betaXSrcList"></param>
        /// <param name="profileSrcList"></param>
        /// <returns></returns>
        private static bool mkFEMMat(
            int probNo,
            double newmarkBeta,
            double timeDelta,
            double NormalizedFreqSrc,
            double WaveguideWidth,
            WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            uint FieldValId,
            uint FieldLoopId,
            uint FieldForceBcId,
            IList<uint> FieldPortBcIdList,
            IList<uint> VIdRefList,
            IList<MediaInfo> Medias,
            Dictionary<uint, wg2d.World.Loop> LoopDic,
            Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref int node_cnt,
            ref IList<uint> sortedNodes,
            ref Dictionary<uint, uint> toSorted,
            ref IList<IList<uint>> sortedNodes_Port_List,
            ref IList<Dictionary<uint, uint>> toSorted_Port_List,
            ref double[] KMat,
            ref double[] MMat,
            ref IList<double[]> QbMatList,
            ref IList<double[]> RbMatList,
            ref IList<double[]> TbMatList,
            ref IList<double> betaXSrcList,
            ref IList<double[]> profileSrcList,
            ref IList<double[]> velo_List,
            ref IList<double> b0_abc_List,
            ref IList<double[]> a_abc_List,
            ref IList<double[]> b_abc_List,
            ref double[] AMat,
            ref double[] Ez_Pz,
            ref double[] Ez_Pz_Prev,
            ref double[] Ez_Pz_Prev2,
            ref IList<double> EzTimeAryPort1,
            ref IList<double> EzTimeAryPort2
            )
        {
            System.Diagnostics.Debug.WriteLine("mkFEMMat");
            bool success = false;
            node_cnt = 0;
            sortedNodes = null;
            toSorted = null;
            sortedNodes_Port_List = null;
            toSorted_Port_List = null;
            KMat = null;
            MMat = null;
            QbMatList.Clear();
            RbMatList.Clear();
            TbMatList.Clear();
            betaXSrcList.Clear();
            profileSrcList.Clear();
            AMat = null;
            Ez_Pz = null;
            Ez_Pz_Prev = null;
            Ez_Pz_Prev2 = null;
            if (EzTimeAryPort1 != null)
            {
                EzTimeAryPort1.Clear();
            }
            if (EzTimeAryPort2 != null)
            {
                EzTimeAryPort2.Clear();
            }

            try
            {
                // 全節点数を取得する
                //uint node_cnt = 0;
                node_cnt = 0;
                //node_cnt = WgUtilForPeriodicEigen.GetNodeCnt(World, FieldLoopId);
                double[][] coord_c_all = null;
                {
                    uint[] no_c_all_tmp = null;
                    Dictionary<uint, uint> to_no_all_tmp = null;
                    double[][] coord_c_all_tmp = null;
                    WgUtilForTD.GetLoopCoordList(World, FieldLoopId, out no_c_all_tmp, out to_no_all_tmp, out coord_c_all_tmp);
                    node_cnt = no_c_all_tmp.Length;

                    // 座標リストを節点番号順に並び替えて格納
                    coord_c_all = new double[node_cnt][];
                    for (int ino = 0; ino < node_cnt; ino++)
                    {
                        uint nodeNumber = no_c_all_tmp[ino];
                        double[] coord = coord_c_all_tmp[ino];
                        coord_c_all[nodeNumber] = coord;
                    }
                }

                System.Diagnostics.Debug.WriteLine("node_cnt: {0}", node_cnt);

                // 境界の節点リストを取得する
                uint[] no_c_all_fieldForceBcId = null;
                Dictionary<uint, uint> to_no_boundary_fieldForceBcId = null;
                if (FieldForceBcId != 0)
                {
                    WgUtil.GetBoundaryNodeList(World, FieldForceBcId, out no_c_all_fieldForceBcId, out to_no_boundary_fieldForceBcId);
                }
                // ポート数
                //  励振面の分を引く
                int portCnt = FieldPortBcIdList.Count - 1;
                IList<uint[]> no_c_all_fieldPortBcId_list = new List<uint[]>();
                IList<Dictionary<uint, uint>> to_no_boundary_fieldPortBcId_list = new List<Dictionary<uint, uint>>();

                for (int portIndex = 0; portIndex < (portCnt + 1); portIndex++)
                {
                    uint workFieldPortBcId = FieldPortBcIdList[portIndex];
                    uint[] work_no_c_all_fieldPortBcId = null;
                    Dictionary<uint, uint> work_to_no_boundary_fieldPortBcId = null;

                    WgUtil.GetBoundaryNodeList(World, workFieldPortBcId, out work_no_c_all_fieldPortBcId, out work_to_no_boundary_fieldPortBcId);

                    no_c_all_fieldPortBcId_list.Add(work_no_c_all_fieldPortBcId);
                    to_no_boundary_fieldPortBcId_list.Add(work_to_no_boundary_fieldPortBcId);
                }
                //強制境界を除いた節点
                //IList<IList<uint>> sortedNodes_Port_List = new List<IList<uint>>();
                //IList<Dictionary<uint, uint>> toSorted_Port_List = new List<Dictionary<uint, uint>>();
                sortedNodes_Port_List = new List<IList<uint>>();
                toSorted_Port_List = new List<Dictionary<uint, uint>>();
                for (int portIndex = 0; portIndex < (portCnt + 1); portIndex++)
                {
                    uint[] no_c_all_fieldPortBcId = no_c_all_fieldPortBcId_list[portIndex];
                    IList<uint> sortedNodes_Port = new List<uint>();
                    Dictionary<uint, uint> toSorted_Port = new Dictionary<uint, uint>();
                    int nodeCntB = no_c_all_fieldPortBcId.Length;
                    for (int ino = 0; ino < nodeCntB; ino++)
                    {
                        uint nodeNumber = no_c_all_fieldPortBcId[ino];
                        if (FieldForceBcId != 0)
                        {
                            // 強制境界を除く
                            if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumber)) continue;
                        }
                        sortedNodes_Port.Add(nodeNumber);
                        toSorted_Port.Add(nodeNumber, (uint)(sortedNodes_Port.Count - 1));
                    }
                    sortedNodes_Port_List.Add(sortedNodes_Port);
                    toSorted_Port_List.Add(toSorted_Port);
                }

                // 節点のソート
                //IList<uint> sortedNodes = new List<uint>();
                //Dictionary<uint, int> toSorted = new Dictionary<uint, int>();
                sortedNodes = new List<uint>();
                toSorted = new Dictionary<uint, uint>();
                for (uint nodeNumber = 0; nodeNumber < node_cnt; nodeNumber++)
                {
                    if (FieldForceBcId != 0)
                    {
                        // 強制境界を除く
                        if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumber)) continue;
                    }
                    sortedNodes.Add(nodeNumber);
                    toSorted.Add(nodeNumber, (uint)(sortedNodes.Count - 1));
                }
                uint free_node_cnt = (uint)sortedNodes.Count;

                WgUtil.GC_Collect();

                //------------------------------------------------------
                // 剛性行列、質量行列を作成
                //------------------------------------------------------
                WgUtilForTD.MkHelmholtzMat(
                    World,
                    FieldLoopId,
                    Medias,
                    LoopDic,
                    (uint)node_cnt,
                    free_node_cnt,
                    toSorted,
                    out KMat,
                    out MMat);

                //------------------------------------------------------
                // モード分布計算
                //------------------------------------------------------
                // 波数
                double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
                // 波長
                double waveLengthSrc = 2.0 * pi / k0Src;
                // 周波数
                double freqSrc = c0 / waveLengthSrc;
                // 角周波数
                double omegaSrc = 2.0 * pi * freqSrc;

                bool retPort = false;

                // 境界の界に導波路開口条件を追加
                for (int portIndex = 0; portIndex < (portCnt + 1); portIndex++)
                {
                    uint workFieldPortBcId = FieldPortBcIdList[portIndex];
                    double[,] ryy_1d_port1 = null;
                    double[,] txx_1d_port1 = null;
                    double[,] uzz_1d_port1 = null;
                    Complex[] eigen_values_port1 = null;
                    Complex[,] eigen_vecs_port1 = null;
                    retPort = WgUtil.SolvePortWaveguideEigen(
                        waveLengthSrc,
                        WaveModeDv,
                        World,
                        workFieldPortBcId,
                        no_c_all_fieldForceBcId,
                        Medias,
                        EdgeDic,
                        out ryy_1d_port1,
                        out txx_1d_port1,
                        out uzz_1d_port1,
                        out eigen_values_port1,
                        out eigen_vecs_port1);

                    // 境界節点数 (強制境界を含む)
                    uint[] no_c_all_fieldPortBcId = no_c_all_fieldPortBcId_list[portIndex];
                    int nodeCntB = no_c_all_fieldPortBcId.Length;
                    Dictionary<uint, uint> toSorted_Port = toSorted_Port_List[portIndex];
                    // 強制境界を除いた節点数
                    int nodeCntB_f = toSorted_Port.Count;

                    // 境界質量行列
                    double[] ryy_1d_port1_Buffer = MyMatrixUtil.matrix_ToBuffer(ryy_1d_port1);
                    double[] txx_1d_port1_Buffer = MyMatrixUtil.matrix_ToBuffer(txx_1d_port1);
                    double[] uzz_1d_port1_Buffer = MyMatrixUtil.matrix_ToBuffer(uzz_1d_port1);
                    double[] ryy_1d_port1_Buffer_f = new double[nodeCntB_f * nodeCntB_f];
                    double[] txx_1d_port1_Buffer_f = new double[nodeCntB_f * nodeCntB_f];
                    double[] uzz_1d_port1_Buffer_f = new double[nodeCntB_f * nodeCntB_f];
                    for (int ino = 0; ino < nodeCntB; ino++)
                    {
                        uint ino_global = no_c_all_fieldPortBcId[ino];
                        if (!toSorted_Port.ContainsKey(ino_global))
                        {
                            continue;
                        }
                        uint ino_f = toSorted_Port[ino_global];
                        for (int jno = 0; jno < nodeCntB; jno++)
                        {
                            uint jno_global = no_c_all_fieldPortBcId[jno];
                            if (!toSorted_Port.ContainsKey(jno_global))
                            {
                                continue;
                            }
                            uint jno_f = toSorted_Port[jno_global];
                            ryy_1d_port1_Buffer_f[ino_f + nodeCntB_f * jno_f] = ryy_1d_port1_Buffer[ino + nodeCntB * jno];
                            txx_1d_port1_Buffer_f[ino_f + nodeCntB_f * jno_f] = txx_1d_port1_Buffer[ino + nodeCntB * jno];
                            uzz_1d_port1_Buffer_f[ino_f + nodeCntB_f * jno_f] = uzz_1d_port1_Buffer[ino + nodeCntB * jno];
                        }
                    }
                    QbMatList.Add(ryy_1d_port1_Buffer_f);
                    RbMatList.Add(txx_1d_port1_Buffer_f);
                    TbMatList.Add(uzz_1d_port1_Buffer_f);

                    // 基本モード
                    uint imode = 0;
                    Complex betam = eigen_values_port1[imode];
                    Complex[] fmVec = MyMatrixUtil.matrix_GetRowVec(eigen_vecs_port1, (int)imode); // 強制境界を含む
                    // 実数部を取得する
                    double betamReal = betam.Real;
                    double[] fmVecReal_f = new double[nodeCntB_f]; // 強制境界を除く
                    for (int ino = 0; ino < fmVec.Length; ino++)
                    {
                        uint ino_global = no_c_all_fieldPortBcId[ino];
                        if (!toSorted_Port.ContainsKey(ino_global))
                        {
                            continue;
                        }
                        uint ino_f = toSorted_Port[ino_global];

                        fmVecReal_f[ino_f] = fmVec[ino].Real;
                        //System.Diagnostics.Debug.WriteLine("{0}", fmVecReal_f[ino_f]);
                    }
                    betaXSrcList.Add(betamReal);
                    profileSrcList.Add(fmVecReal_f);
                    if (Math.Abs(betamReal) < Constants.PrecisionLowerLimit)
                    {
                        return false;
                    }
                }

                /////////////////////////////////////////////////////////

                //------------------------------------------------------
                // 電界
                //-----------------------------------------------------
                uint free_node_cnt_all = free_node_cnt;
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    uint nodeCntB_f = (uint)sortedNodes_Port_List[portIndex].Count;
                    free_node_cnt_all += nodeCntB_f* (ABC_order - 1);
                }
                Ez_Pz = new double[free_node_cnt_all];
                Ez_Pz_Prev = new double[free_node_cnt_all];
                Ez_Pz_Prev2 = new double[free_node_cnt_all];

                //------------------------------------------------------
                // 全体係数行列の作成
                //------------------------------------------------------
                AMat = new double[free_node_cnt_all * free_node_cnt_all];
                double dt = timeDelta;
                for (int ino = 0; ino < free_node_cnt; ino++)
                {
                    for (int jno = 0; jno < free_node_cnt; jno++)
                    {
                        AMat[ino + free_node_cnt_all * jno] =
                            (1.0 / (dt * dt)) * MMat[ino + free_node_cnt * jno]
                            + newmarkBeta * KMat[ino + free_node_cnt * jno];
                    }
                }

                // 吸収境界パラメータ
                //IList<double[]> velo_List = new List<double[]>();
                //IList<double> b0_abc_List = new List<double>();
                //IList<double[]> a_abc_List = new List<double[]>();
                //IList<double[]> b_abc_List = new List<double[]>();
                velo_List.Clear();
                b0_abc_List.Clear();
                a_abc_List.Clear();
                b_abc_List.Clear();

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    double betaXSrc = betaXSrcList[portIndex];
                    double vpx = omegaSrc / betaXSrc;
                    double[] velo = new double[ABC_order];
                    for (int order = 0; order < ABC_order; order++)
                    {
                        //velo[order] = c0; // ガウシアンパルスの場合
                        //velo[order] = vpx; // 正弦波変調ガウシアンパルスの場合
                        velo[order] = vpx;
                    }
                    velo_List.Add(velo);
                }
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    double[] velo =velo_List[portIndex];
                    double b0_abc = 1.0 / velo[0];
                    //double[] a_abc = new double[ABC_order - 1]; // 一様媒質の場合
                    double[] b_abc = new double[ABC_order - 1];
                    for (int order = 0; order < (ABC_order - 1); order++)
                    {
                        //a_abc[order] = 1.0 / (velo[order] * velo[order]) - 1.0 / (c0 * c0);
                        b_abc[order] = 1.0 / velo[order] + 1.0 / velo[order + 1];
                    }
                    b0_abc_List.Add(b0_abc);
                    //a_abc_List.Add(a_abc);
                    b_abc_List.Add(b_abc);
                }

                // 吸収境界
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    double b0_abc = b0_abc_List[portIndex];

                    IList<uint> sortedNodes_Port = sortedNodes_Port_List[portIndex];
                    int nodeCntB_f = sortedNodes_Port.Count;
                    double[] QbMat = QbMatList[portIndex];
                    System.Diagnostics.Debug.Assert(QbMat.Length == (nodeCntB_f * nodeCntB_f));
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            //強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        System.Diagnostics.Debug.Assert(ino_f >= 0 && ino_f < free_node_cnt);
                        for (int jno = 0; jno < nodeCntB_f; jno++)
                        {
                            uint jno_global = sortedNodes_Port[jno];
                            if (!toSorted.ContainsKey(jno_global))
                            {
                                //強制境界は除外済み
                                System.Diagnostics.Debug.Assert(false);
                                continue;
                            }
                            int jno_f = (int)toSorted[jno_global];
                            System.Diagnostics.Debug.Assert(jno_f >= 0 && jno_f < free_node_cnt);
                            AMat[ino_f + free_node_cnt_all * jno_f] += (b0_abc / (2.0 * dt)) * QbMat[ino + nodeCntB_f * jno];
                        }
                    }
                }

                // Φ1の開始位置
                int[] nodeIndex_Pz1_List = new int[portCnt];
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    if (portIndex == 0)
                    {
                        nodeIndex_Pz1_List[portIndex] = (int)free_node_cnt;
                    }
                    else
                    {
                        int nodeCntB_f_PrevPort = sortedNodes_Port_List[portIndex - 1].Count;
                        nodeIndex_Pz1_List[portIndex] = nodeIndex_Pz1_List[portIndex - 1] + nodeCntB_f_PrevPort * (ABC_order - 1);
                    }
                }

                // Ez - Φ1
                if (ABC_order > 1)
                {
                    for (int portIndex = 0; portIndex < portCnt; portIndex++)
                    {
                        IList<uint> sortedNodes_Port = sortedNodes_Port_List[portIndex];
                        int nodeCntB_f = sortedNodes_Port.Count;
                        double[] QbMat = QbMatList[portIndex];

                        // Ezに関する式
                        for (int ino = 0; ino < nodeCntB_f; ino++)
                        {
                            // Ez
                            uint ino_global = sortedNodes_Port[ino];
                            if (!toSorted.ContainsKey(ino_global))
                            {
                                //強制境界は除外済み
                                System.Diagnostics.Debug.Assert(false);
                                continue;
                            }
                            int ino_f = (int)toSorted[ino_global];
                            System.Diagnostics.Debug.Assert(ino_f >= 0 && ino_f < free_node_cnt);

                            for (int jno = 0; jno < nodeCntB_f; jno++)
                            {
                                // Φ1
                                int jno_f = jno + nodeIndex_Pz1_List[portIndex];
                                AMat[ino_f + free_node_cnt_all * jno_f] = -1.0 * newmarkBeta * QbMat[ino + nodeCntB_f * jno];
                            }
                        }
                    }
                }

                // Φ1 ~ Φ(ABC_order - 1)
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    IList<uint> sortedNodes_Port = sortedNodes_Port_List[portIndex];
                    int nodeCntB_f = sortedNodes_Port.Count;
                    double[] QbMat = QbMatList[portIndex];
                    double[] RbMat = RbMatList[portIndex];
                    double[] TbMat = TbMatList[portIndex];
                    double[] velo = velo_List[portIndex];
                    double b0_abc = b0_abc_List[portIndex];
                    //double[] a_abc = a_abc_List[portIndex]; // 一様媒質のとき
                    double[] b_abc = b_abc_List[portIndex];

                    // Φ(order)に関する式
                    for (int order = 0; order < (ABC_order - 1); order++)
                    {
                        for (int ino = 0; ino < nodeCntB_f; ino++)
                        {
                            // order
                            int ino_f = ino + nodeCntB_f * order + nodeIndex_Pz1_List[portIndex];
                            for (int jno = 0; jno < nodeCntB_f; jno++)
                            {
                                int jno_f = 0;
                                // Φ(order)
                                jno_f = jno + nodeCntB_f * order + nodeIndex_Pz1_List[portIndex];
                                AMat[ino_f + free_node_cnt_all * jno_f] = (b_abc[order] / (2.0 * dt)) * QbMat[ino + nodeCntB_f * jno];

                                // Φ(order-1)
                                jno_f = 0;
                                if (order == 0)
                                {
                                    // Φ0 (Ez)
                                    uint jno_global = sortedNodes_Port[jno];
                                    if (!toSorted.ContainsKey(jno_global))
                                    {
                                        //強制境界は除外済み
                                        System.Diagnostics.Debug.Assert(false);
                                        continue;
                                    }
                                    jno_f = (int)toSorted[jno_global];
                                }
                                else
                                {
                                    jno_f = jno + nodeCntB_f * (order - 1) + nodeIndex_Pz1_List[portIndex];
                                }
                                // 一様媒質の場合
                                //AMat[ino_f + free_node_cnt_all * jno_f] =
                                //    -1.0 * (a_abc[order] / (dt * dt)) * QbMat[ino + nodeCntB_f * jno]
                                //    + RbMat[ino + nodeCntB_f * jno] * newmarkBeta;
                                // 媒質定数がy方向に変化する場合
                                AMat[ino_f + free_node_cnt_all * jno_f] =
                                    -1.0 * (1.0 / (velo[order] * velo[order] * dt * dt)) * QbMat[ino + nodeCntB_f * jno]
                                    + 1.0 * (1.0 / (c0 * c0* dt * dt)) * TbMat[ino + nodeCntB_f * jno]
                                    + RbMat[ino + nodeCntB_f * jno] * newmarkBeta;

                                // Φ(order + 1)
                                jno_f = 0;
                                if (order == (ABC_order - 2))
                                {
                                    // なし
                                }
                                else
                                {
                                    jno_f = jno + nodeCntB_f * (order + 1) + nodeIndex_Pz1_List[portIndex];
                                    AMat[ino_f + free_node_cnt_all * jno_f] = -1.0 * newmarkBeta * QbMat[ino + nodeCntB_f * jno];
                                }
                            }
                        }
                    }
                }

                // 逆行列を計算
                System.Diagnostics.Debug.WriteLine("calc [A]-1");
                Console.Write("calc [A]-1 ....");
                //AMat = MyMatrixUtil.matrix_Inverse(AMat, (int)free_node_cnt_all);
                AMat = MyMatrixUtil.matrix_Inverse_NoCopy(AMat, (int)free_node_cnt_all);
                Console.WriteLine(" done");

                WgUtil.GC_Collect();

                success = true;

            }
            catch (Exception exception)
            {
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
                success = false;
            }
            System.Diagnostics.Debug.WriteLine("mkFEMMat done ret: {0}", success);
            System.Diagnostics.Debug.WriteLine("ABC_order:{0}", ABC_order);
            System.Diagnostics.Debug.WriteLine("dt:{0}", timeDelta);
            return success;
        }
Beispiel #16
0
        /// <summary>
        /// 問題を解く
        /// </summary>
        /// <param name="probNo">問題番号</param>
        /// <param name="timeIndex">時刻のインデックス</param>
        /// <param name="timeLoopCnt">時間計算回数</param>
        /// <param name="newmarkBeta">Newmarkβ法のβ</param>
        /// <param name="timeDelta">時刻刻み</param>
        /// <param name="gaussianT0">ガウシアンパルスの遅延時間</param>
        /// <param name="gaussianTp">ガウシアンパルスの時間幅</param>
        /// <param name="NormalizedFreqSrc">励振するモードの規格化周波数</param>
        /// <param name="VIdRefList">観測点の頂点ID(= 節点番号 + 1)</param>
        /// <param name="NormalizedFreq1">開始規格化周波数</param>
        /// <param name="NormalizedFreq2">終了規格化周波数</param>
        /// <param name="initFlg">カメラ初期化フラグ</param>
        /// <param name="WaveguideWidth">導波路幅</param>
        /// <param name="WaveModeDv">波のモード区分</param>
        /// <param name="World">ワールド座標系</param>
        /// <param name="FieldValId">値のフィールドID</param>
        /// <param name="FieldLoopId">ループのフィールドID</param>
        /// <param name="FieldForceBcId">強制境界のフィールドID</param>
        /// <param name="FieldPortBcIdList">ポート1、ポート2、励振面の境界のフィールドID</param>
        /// <param name="Medias">媒質リスト</param>
        /// <param name="LoopDic">ループID→ループ情報マップ</param>
        /// <param name="EdgeDic">エッジID→エッジ情報マップ</param>
        /// <param name="IsShowAbsField">絶対値表示する?</param>
        /// <param name="node_cnt">節点数(強制境界を含む)</param>
        /// <param name="sortedNodes">ソート済み節点番号リスト</param>
        /// <param name="toSorted">節点番号→ソート済み節点インデックスマップ</param>
        /// <param name="sortedNodes_Port_List">境界のソート済み節点番号リスト(ポート1,ポート2,励振面)</param>
        /// <param name="toSorted_Port_List">境界の節点番号→ソート済み節点インデックスマップ(ポート1,ポート2,励振面)</param>
        /// <param name="KMat">剛性行列</param>
        /// <param name="MMat">質量行列</param>
        /// <param name="QbMatList">境界質量行列</param>
        /// <param name="betaXSrcList">境界の伝搬定数(ポート1、ポート2、励振面)</param>
        /// <param name="profileSrcList">境界のモード分布(ポート1、ポート2、励振面)</param>
        /// <param name="AMat">係数行列(逆行列)</param>
        /// <param name="Ez_Pz">電界分布(現在)</param>
        /// <param name="Ez_Pz_Prev">電界分布(1つ前)</param>
        /// <param name="Ez_Pz_Prev2">電界分布(2つ前)</param>
        /// <param name="EzTimeAryPort1">ポート1観測点の電界リスト(時間変化)</param>
        /// <param name="EzTimeAryPort2">ポート2観測点の電界リスト(時間変化)</param>
        /// <param name="DrawerAry">描画オブジェクトアレイ</param>
        /// <param name="Camera">カメラ</param>
        /// <returns></returns>
        private static bool solveProblem(
            int probNo,
            bool IsSolveStraightWg,
            ref int timeIndex,
            int timeLoopCnt,
            double newmarkBeta,
            double timeDelta,
            double gaussianT0,
            double gaussianTp,
            double NormalizedFreqSrc,
            double NormalizedFreq1,
            double NormalizedFreq2,
            bool initFlg,
            double WaveguideWidth,
            WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            uint FieldValId,
            uint FieldLoopId,
            uint FieldForceBcId,
            IList<uint> FieldPortBcIdList,
            IList<uint> VIdRefList,
            IList<MediaInfo> Medias,
            Dictionary<uint, wg2d.World.Loop> LoopDic,
            Dictionary<uint, wg2d.World.Edge> EdgeDic,
            bool IsShowAbsField,
            int node_cnt,
            IList<uint> sortedNodes,
            Dictionary<uint, uint> toSorted,
            IList<IList<uint>> sortedNodes_Port_List,
            IList<Dictionary<uint, uint>> toSorted_Port_List,
            double[] KMat,
            double[] MMat,
            IList<double[]> QbMatList,
            IList<double[]> RbMatList,
            IList<double[]> TbMatList,
            IList<double> betaXSrcList,
            IList<double[]> profileSrcList,
            IList<double[]> velo_List,
            IList<double> b0_abc_List,
            IList<double[]> a_abc_List,
            IList<double[]> b_abc_List,
            double[] AMat,
            ref double[] Ez_Pz,
            ref double[] Ez_Pz_Prev,
            ref double[] Ez_Pz_Prev2,
            ref IList<double> EzTimeAryPort1,
            ref IList<double> EzTimeAryPort2,
            ref CDrawerArrayField DrawerAry,
            CCamera Camera)
        {
            //long memorySize1 = GC.GetTotalMemory(false);
            //Console.WriteLine("    total memory: {0}", memorySize1);

            bool success = false;

            // ポート数
            //  励振面の分を引く
            int portCnt = FieldPortBcIdList.Count - 1;

            // 時刻の取得
            if (timeIndex == -1)
            {
                return success;
            }
            if (timeIndex >= timeLoopCnt)
            {
                timeIndex = -1;
                return success;
            }
            // 以下curTimeIndexに対する計算
            double curTime = timeIndex * timeDelta;

            double dt = timeDelta;

            try
            {
                // ワールド座標系のフィールド値をクリア
                WgUtil.ClearFieldValues(World, FieldValId);

                // 励振源のパラメータ
                // 波数
                double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
                // 波長
                double waveLengthSrc = 2.0 * pi / k0Src;
                // 周波数
                double freqSrc = c0 / waveLengthSrc;
                // 角周波数
                double omegaSrc = 2.0 * pi * freqSrc;

                //--------------------------------------------------------------
                // 電界
                //--------------------------------------------------------------
                uint free_node_cnt = (uint)sortedNodes.Count;
                uint free_node_cnt_all = free_node_cnt;
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    uint nodeCntB_f = (uint)sortedNodes_Port_List[portIndex].Count;
                    free_node_cnt_all += nodeCntB_f * (ABC_order - 1);
                }
                System.Diagnostics.Debug.Assert(Ez_Pz.Length == free_node_cnt_all);

                Ez_Pz_Prev.CopyTo(Ez_Pz_Prev2, 0);
                Ez_Pz.CopyTo(Ez_Pz_Prev, 0);
                for (int ino = 0; ino < free_node_cnt_all; ino++)
                {
                    Ez_Pz[ino] = 0.0;
                }

                //--------------------------------------------------------------
                // 残差
                //--------------------------------------------------------------
                double[] resVec = new double[free_node_cnt_all];

                double[] vec_MMat = new double[free_node_cnt];
                double[] vec_KMat = new double[free_node_cnt];
                for (int ino = 0; ino < free_node_cnt; ino++)
                {
                    vec_MMat[ino] = (2.0 / (dt * dt)) * Ez_Pz_Prev[ino] - (1.0 / (dt * dt)) * Ez_Pz_Prev2[ino];
                    vec_KMat[ino] = -(1.0 - 2.0 * newmarkBeta) * Ez_Pz_Prev[ino] - newmarkBeta * Ez_Pz_Prev2[ino];
                }
                vec_MMat = MyMatrixUtil.product_native(
                    MMat, (int)free_node_cnt, (int)free_node_cnt,
                    vec_MMat, (int)free_node_cnt);
                vec_KMat = MyMatrixUtil.product_native(
                    KMat, (int)free_node_cnt, (int)free_node_cnt,
                    vec_KMat, (int)free_node_cnt);
                double[] resVec_0 = MyMatrixUtil.plus(vec_MMat, vec_KMat);
                resVec_0.CopyTo(resVec, 0);

                // 吸収境界
                // Φ1の開始位置
                int[] nodeIndex_Pz1_List = new int[portCnt];
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    if (portIndex == 0)
                    {
                        nodeIndex_Pz1_List[portIndex] = (int)free_node_cnt;
                    }
                    else
                    {
                        int nodeCntB_f_PrevPort = sortedNodes_Port_List[portIndex - 1].Count;
                        nodeIndex_Pz1_List[portIndex] = nodeIndex_Pz1_List[portIndex - 1] + nodeCntB_f_PrevPort  * (ABC_order - 1);
                    }
                }

                // Ezに関する式
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    // 境界の節点番号リスト
                    IList<uint> sortedNodes_Port = sortedNodes_Port_List[portIndex];
                    // 境界の節点数(強制境界を含まない)
                    int nodeCntB_f = sortedNodes_Port.Count;
                    double[] QbMat = QbMatList[portIndex];
                    System.Diagnostics.Debug.Assert(QbMat.Length == (nodeCntB_f * nodeCntB_f));
                    double b0_abc = b0_abc_List[portIndex];

                    double[] work_Ez_Prev2 = new double[nodeCntB_f];
                    double[] work_Pz_order_2_Prev = new double[nodeCntB_f];
                    double[] work_Pz_order_2_Prev2 = new double[nodeCntB_f];
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        // Ez
                        work_Ez_Prev2[ino] = 0.0;
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            //強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        work_Ez_Prev2[ino] = Ez_Pz_Prev2[ino_f];
                    }

                    if (ABC_order > 1)
                    {
                        for (int ino = 0; ino < nodeCntB_f; ino++)
                        {
                            // Φ1
                            int ino_f = ino + nodeIndex_Pz1_List[portIndex];
                            work_Pz_order_2_Prev[ino] = Ez_Pz_Prev[ino_f];
                            work_Pz_order_2_Prev2[ino] = Ez_Pz_Prev2[ino_f];
                        }
                    }

                    double[] vec_QbMat = new double[nodeCntB_f];
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        vec_QbMat[ino] = (b0_abc / (2.0 * dt)) * work_Ez_Prev2[ino];
                        if (ABC_order > 1)
                        {
                            vec_QbMat[ino] +=
                                (1.0 - 2.0 * newmarkBeta) * work_Pz_order_2_Prev[ino]
                                + newmarkBeta * work_Pz_order_2_Prev2[ino];
                        }
                    }
                    vec_QbMat = MyMatrixUtil.product_native(
                        QbMat, nodeCntB_f, nodeCntB_f,
                        vec_QbMat, nodeCntB_f);

                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            //強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        resVec[ino_f] += vec_QbMat[ino];
                    }
                }

                // Φ1 ~ Φ(ABC_order - 1)
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    IList<uint> sortedNodes_Port = sortedNodes_Port_List[portIndex];
                    int nodeCntB_f = sortedNodes_Port.Count;
                    double[] QbMat = QbMatList[portIndex];
                    double[] RbMat = RbMatList[portIndex];
                    double[] TbMat = TbMatList[portIndex];
                    double[] velo = velo_List[portIndex];
                    double b0_abc = b0_abc_List[portIndex];
                    //double[] a_abc = a_abc_List[portIndex]; // 一様媒質の場合
                    double[] b_abc = b_abc_List[portIndex];

                    // Φorderに関する式
                    for (int order = 0; order < (ABC_order - 1); order++)
                    {
                        double[] work_Pz_order_0_Prev2 = new double[nodeCntB_f];
                        double[] work_Pz_order_1_Prev = new double[nodeCntB_f];
                        double[] work_Pz_order_1_Prev2 = new double[nodeCntB_f];
                        double[] work_Pz_order_2_Prev = new double[nodeCntB_f];
                        double[] work_Pz_order_2_Prev2 = new double[nodeCntB_f];
                        for (int ino = 0; ino < nodeCntB_f; ino++)
                        {
                            int ino_f = 0;
                            // Φorder
                            ino_f = ino + nodeCntB_f * (order) + nodeIndex_Pz1_List[portIndex];
                            work_Pz_order_0_Prev2[ino] = Ez_Pz_Prev2[ino_f];

                            // Φorder-1
                            ino_f = 0;
                            if (order == 0)
                            {
                                // Φ0 (Ez)
                                uint ino_global = sortedNodes_Port[ino];
                                if (!toSorted.ContainsKey(ino_global))
                                {
                                    //強制境界は除外済み
                                    System.Diagnostics.Debug.Assert(false);
                                    continue;
                                }
                                ino_f = (int)toSorted[ino_global];
                            }
                            else
                            {
                                ino_f = ino + nodeCntB_f * (order - 1) + nodeIndex_Pz1_List[portIndex];
                            }
                            work_Pz_order_1_Prev[ino] = Ez_Pz_Prev[ino_f];
                            work_Pz_order_1_Prev2[ino] = Ez_Pz_Prev2[ino_f];

                            // Φ(order + 1)
                            if (order == (ABC_order - 2))
                            {
                                // なし
                                work_Pz_order_2_Prev[ino] = 0.0;
                                work_Pz_order_2_Prev2[ino] = 0.0;
                            }
                            else
                            {
                                ino_f = ino + nodeCntB_f * (order + 1) + nodeIndex_Pz1_List[portIndex];
                                work_Pz_order_2_Prev[ino] = Ez_Pz_Prev[ino_f];
                                work_Pz_order_2_Prev2[ino] = Ez_Pz_Prev2[ino_f];
                            }
                        }
                        double[] vec_QbMat = new double[nodeCntB_f];
                        double[] vec_RbMat = new double[nodeCntB_f];
                        double[] vec_TbMat = new double[nodeCntB_f]; // 媒質定数がy方向に変化する場合
                        for (int ino = 0; ino < nodeCntB_f; ino++)
                        {
                            // 一様媒質の場合
                            //vec_QbMat[ino] =
                            //    (b_abc[order] / (2.0 * dt)) * work_Pz_order_0_Prev2[ino]
                            //    + (a_abc[order] / (dt * dt)) * (
                            //      -2.0 * work_Pz_order_1_Prev[ino] + work_Pz_order_1_Prev2[ino]
                            //      )
                            //    + (
                            //      (1.0 - 2.0 * newmarkBeta) * work_Pz_order_2_Prev[ino]
                            //      + newmarkBeta * work_Pz_order_2_Prev2[ino]
                            //      );
                            // 媒質定数がy方向に変化する場合
                            vec_QbMat[ino] =
                                (b_abc[order] / (2.0 * dt)) * work_Pz_order_0_Prev2[ino]
                                + (1.0 / (velo[order] * velo[order] * dt * dt)) * (
                                  -2.0 * work_Pz_order_1_Prev[ino] + work_Pz_order_1_Prev2[ino]
                                  )
                                + (
                                  (1.0 - 2.0 * newmarkBeta) * work_Pz_order_2_Prev[ino]
                                  + newmarkBeta * work_Pz_order_2_Prev2[ino]
                                  );
                            // 媒質定数がy方向に変化する場合
                            vec_TbMat[ino] =
                                (-1.0 / (c0 * c0 * dt * dt)) * (
                                  -2.0 * work_Pz_order_1_Prev[ino] + work_Pz_order_1_Prev2[ino]
                                  );
                            // 共用
                            vec_RbMat[ino] =
                                -1.0 * (
                                    (1.0 - 2.0 * newmarkBeta) * work_Pz_order_1_Prev[ino]
                                    + newmarkBeta * work_Pz_order_1_Prev2[ino]
                                  );
                        }
                        vec_QbMat = MyMatrixUtil.product_native(
                            QbMat, nodeCntB_f, nodeCntB_f,
                            vec_QbMat, nodeCntB_f);
                        vec_RbMat = MyMatrixUtil.product_native(
                            RbMat, nodeCntB_f, nodeCntB_f,
                            vec_RbMat, nodeCntB_f);
                        vec_TbMat = MyMatrixUtil.product_native(
                            TbMat, nodeCntB_f, nodeCntB_f,
                            vec_TbMat, nodeCntB_f);

                        for (int ino = 0; ino < nodeCntB_f; ino++)
                        {
                            int ino_f = ino + nodeCntB_f * (order) + nodeIndex_Pz1_List[portIndex];
                            resVec[ino_f] = vec_QbMat[ino] + vec_RbMat[ino] + vec_TbMat[ino];
                        }
                    }
                }

                //--------------------------------------------------------------
                // 励振源
                //--------------------------------------------------------------
                {
                    int portIndex = portCnt; // ポートリストの最後の要素が励振境界
                    // 境界の節点番号リスト
                    IList<uint> sortedNodes_Port = sortedNodes_Port_List[portIndex];
                    // 境界の節点数(強制境界を含まない)
                    int nodeCntB_f = sortedNodes_Port.Count;
                    double[] QbMat = QbMatList[portIndex];
                    double betaXSrc = betaXSrcList[portIndex];
                    double[] profileSrc = profileSrcList[portIndex];

                    double srcF1 = 0.0;
                    double srcF2 = 0.0;
                    double srcF0 = 0.0;

                    int n = timeIndex;
                    // ガウシアンパルス
                    if ((n * dt) <= (2.0 * gaussianT0 + dt))
                    {
                        /*
                        // ガウシアンパルス
                        srcF1 = Math.Exp(-1.0 * ((n + 1) * dt - gaussianT0) * ((n + 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF2 = Math.Exp(-1.0 * ((n - 1) * dt - gaussianT0) * ((n - 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF0 = Math.Exp(-1.0 * ((n) * dt - gaussianT0) * ((n) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                         */

                        // 正弦波変調ガウシアンパルス
                        srcF1 = Math.Cos(omegaSrc * ((n + 1) * dt - gaussianT0))
                                * Math.Exp(-1.0 * ((n + 1) * dt - gaussianT0) * ((n + 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF2 = Math.Cos(omegaSrc * ((n - 1) * dt - gaussianT0))
                                * Math.Exp(-1.0 * ((n - 1) * dt - gaussianT0) * ((n - 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF0 = Math.Cos(omegaSrc * ((n) * dt - gaussianT0))
                                * Math.Exp(-1.0 * ((n) * dt - gaussianT0) * ((n) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                    }

                    /*
                    // 正弦波
                    srcF1 = Math.Sin(omegaSrc * (n + 1) * dt);
                    srcF2 = Math.Sin(omegaSrc * (n - 1) * dt);
                    srcF0 = Math.Sin(omegaSrc * (n) * dt);
                     */

                    // 境界積分
                    double[] srcdFdt = new double[nodeCntB_f];
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        double normalizeFactor = -1.0;
                        srcdFdt[ino] = normalizeFactor * profileSrc[ino] * (srcF1 - srcF2) / (2.0 * dt);
                    }
                    double vpx = omegaSrc / betaXSrc;
                    double[] vec_QbMat = MyMatrixUtil.product((-2.0 / vpx), srcdFdt);
                    vec_QbMat = MyMatrixUtil.product_native(
                        QbMat, nodeCntB_f, nodeCntB_f,
                        vec_QbMat, nodeCntB_f);
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            // 強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        resVec[ino_f] += vec_QbMat[ino];
                    }

                    /*
                    // 領域積分
                    double[] srcdFdt2_f = new double[free_node_cnt];
                    double[] srcF_f = new double[free_node_cnt];
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            // 強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        double normalizeFactor = -1.0;
                        //double normalizeFactor = -omegaSrc * myu0 / betaXSrc;
                        srcF_f[ino_f] = normalizeFactor * profileSrc[ino] * srcF0;
                        srcdFdt2_f[ino_f] = normalizeFactor * profileSrc[ino] * (srcF1 - 2.0 * srcF0 + srcF2) / (dt * dt);
                    }
                    double[] vec_MMatSrc = MyMatrixUtil.product_native(
                        MMat, (int)free_node_cnt, (int)free_node_cnt,
                        srcdFdt2_f, (int)free_node_cnt
                        );
                    double[] vec_KMatSrc = MyMatrixUtil.product_native(
                        KMat, (int)free_node_cnt, (int)free_node_cnt,
                        srcF_f, (int)free_node_cnt
                        );
                    for (int ino = 0; ino < free_node_cnt; ino++)
                    {
                        resVec[ino] += vec_MMatSrc[ino] + vec_KMatSrc[ino];
                    }
                     */
                }

                //------------------------------------------------------------------
                // Ezを求める
                //------------------------------------------------------------------
                /*
                // 連立方程式を解く
                {
                    int matLen = (int)free_node_cnt_all;
                    double[] A = new double[matLen * matLen];
                    AMat.CopyTo(A, 0); // コピーを取る
                    double[] B = resVec;

                    double[] X = null;
                    int x_row = matLen;
                    int x_col = 1;
                    int a_row = matLen;
                    int a_col = matLen;
                    int b_row = matLen;
                    int b_col = 1;
                    KrdLab.clapack.Function.dgesv(ref X, ref x_row, ref x_col, A, a_row, a_col, B, b_row, b_col);

                    X.CopyTo(Ez_Pz, 0);
                }
                 */

                // 逆行列を用いる
                Ez_Pz = MyMatrixUtil.product_native(
                    AMat, (int)free_node_cnt_all, (int)free_node_cnt_all,
                    resVec, (int)free_node_cnt_all
                    );

                // 電界を取得
                double[] Ez = new double[free_node_cnt];
                for (int ino = 0; ino < free_node_cnt; ino++)
                {
                    Ez[ino] = Ez_Pz[ino];
                }

                // 観測点
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    // 頂点IDから1を引いたものが節点番号
                    uint nodeNumber = VIdRefList[portIndex] - 1;
                    int ino_f = (int)toSorted[nodeNumber];
                    double fVal = Ez[ino_f];
                    if (portIndex == 0)
                    {
                        if (EzTimeAryPort1 != null)
                        {
                            EzTimeAryPort1.Add(fVal);
                        }
                    }
                    else if (portIndex == 1)
                    {
                        if (EzTimeAryPort2 != null)
                        {
                            EzTimeAryPort2.Add(fVal);
                        }
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                }

                // 解ベクトルをワールド座標系にセット
                WgUtil.SetFieldValueForDisplay(World, FieldValId, Ez, toSorted);

                if ((timeIndex + 1) % 50 == 0)
                {
                    Console.WriteLine("{0}", (timeIndex + 1));
                }

                //------------------------------------------------------------------
                // 描画する界の追加
                //------------------------------------------------------------------
                DrawerAry.Clear();
                DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                if (initFlg)
                {
                    // カメラの変換行列初期化
                    DrawerAry.InitTrans(Camera);

                    // 表示位置調整
                    setupPanAndScale(probNo, IsSolveStraightWg, Camera);
                }
                success = true;

            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
            }
            return success;
        }
Beispiel #17
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 disconLength = 2.0 * WaveguideWidth;
            double meshL = WaveguideWidth * 0.05;

            NormalizedFreq1 = 1.0;
            NormalizedFreq2 = 2.0;
            FreqDelta = 0.01;
            GraphFreqInterval = 0.2;

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.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 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(disconLength, 0.0)); // 頂点3
                pts.Add(new CVector2D(disconLength, WaveguideWidth)); // 頂点4
                cad2d.AddPolygon(pts);

                // 図面表示
                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 = 1;
                uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                aEA.Add(lId1);
                {
                    World.Loop loop = new 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);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint eId_cad;
                uint eId;
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                // 頂点2-頂点3
                eId_cad = 2;
                eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                aEA.Add(eId);
                // 頂点4-頂点1
                eId_cad = 4;
                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で設定
            }
            // 開口条件1
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId1 = 0;
            {
                uint eId_cad;
                uint eId;
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                // 頂点1-頂点2
                eId_cad = 1;
                eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                aEA.Add(eId);
                {
                    World.Edge edge = new World.Edge();
                    edge.Set(eId, Medias.IndexOf(mediaVacumn));
                    EdgeDic.Add(eId, edge);
                }
                FieldPortBcId1 = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldPortBcId1, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }

            // 開口条件2
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId2 = 0;
            {
                uint eId_cad;
                uint eId;
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                // 頂点3-頂点1
                eId_cad = 3;
                eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                aEA.Add(eId);
                {
                    World.Edge edge = new World.Edge();
                    edge.Set(eId, Medias.IndexOf(mediaVacumn));
                    EdgeDic.Add(eId, edge);
                }
                FieldPortBcId2 = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldPortBcId2, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }

            return true;
        }
Beispiel #18
0
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainLogic()
        {
            Disposed = false;
            Camera = new CCamera();
            DrawerAry = new CDrawerArrayField();
            World = new CFieldWorld();
            //FieldValueSetter = new CFieldValueSetter();
            //Ls = new CZLinearSystem();
            //Prec = new CZPreconditioner_ILU();
            EigenValueList = new List<Complex>();
            CadDrawerAry = new CDrawerArray();

            // Glutのアイドル時処理でなく、タイマーで再描画イベントを発生させる
            MyTimer.Tick += (sender, e) =>
            {
                if (IsTimerProcRun)
                {
                    return;
                }
                IsTimerProcRun = true;
                if (IsAnimation && BetaIndex != -1 && !IsCadShow)
                {
                    // 問題を解く
                    solveProblem(
                        ProbNo,
                        ref BetaIndex,
                        Beta1,
                        Beta2,
                        BetaDelta,
                        (BetaIndex == 0), // false,
                        WaveguideWidth,
                        WaveModeDv,
                        IsPCWaveguide,
                        LatticeA,
                        PeriodicDistance,
                        PCWaveguidePorts,
                        CalcModeIndex,
                        IsSVEA,
                        ref PrevModalVec,
                        IsShowAbsField,
                        MinNormalizedFreq,
                        MaxNormalizedFreq,
                        ref World,
                        FieldValId,
                        FieldLoopId,
                        FieldForceBcId,
                        FieldPortBcId1,
                        FieldPortBcId2,
                        Medias,
                        LoopDic,
                        EdgeDic,
                        ref EigenValueList,
                        ref DrawerAry,
                        Camera
                        );
                    if (BetaIndex != -1)
                    {
                        BetaIndex++;
                    }
                    //DEBUG
                    //Glut.glutPostRedisplay();
                    {
                        // POSTだとメッセージが1つにまとめられる場合がある?
                        // 直接描画する
                        int[] viewport = new int[4];
                        Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
                        int winW = viewport[2];
                        int winH = viewport[3];
                        Camera.SetWindowAspect((double)winW / winH);
                        Gl.glViewport(0, 0, winW, winH);
                        Gl.glMatrixMode(Gl.GL_PROJECTION);
                        Gl.glLoadIdentity();
                        DelFEM4NetCom.View.DrawerGlUtility.SetProjectionTransform(Camera);
                        myGlutDisplay();
                    }
                }
                IsTimerProcRun = false;
            };
            //MyTimer.Interval = 1000 / 60;
            MyTimer.Interval = 1000 / 10;
            //MyTimer.Interval = 2000;
        }
Beispiel #19
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;
        }
Beispiel #20
0
        /// <summary>
        /// 問題を設定する
        /// </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>
        private 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
            )
        {
            bool success = false;

            // 媒質リストのクリア
            Medias.Clear();
            // ワールド座標系ループ情報のクリア
            LoopDic.Clear();
            // ワールド座標系辺情報のクリア
            EdgeDic.Clear();

            // フォトニック結晶導波路解析用
            IsPCWaveguide = false;
            latticeA = 0.0;
            periodicDistance = 0.0;
            PCWaveguidePorts.Clear();
            // 基本モードを計算する
            CalcModeIndex = 0;

            SetProblemProcDelegate func = null;
            //isCadShow = false;
            try
            {
                if (probNo == 0)
                {
                    // 直線導波管
                    func = Problem00.SetProblem;
                }
                else if (probNo == 1)
                {
                    // PC欠陥導波路
                    func = Problem01.SetProblem;
                }
                else if (probNo == 2)
                {
                    // PC欠陥導波路 2チャンネル
                    func = Problem02.SetProblem;
                }
                else if (probNo == 3)
                {
                    // 三角形格子 PC欠陥導波路
                    func = Problem03.SetProblem;
                    //func = Problem03_2.SetProblem; // 1列目ロッドの半径を大きくする
                }
                else if (probNo == 4)
                {
                    // 三角形格子 PC欠陥導波路(斜め領域)
                    func = Problem04.SetProblem;
                }
                else if (probNo == 5)
                {
                    // 三角形格子 PC欠陥導波路 2チャンネル
                    func = Problem05.SetProblem;
                }
                else
                {
                    return success;
                }

                success = func(
                    probNo,
                    WaveguideWidth,
                    ref Beta1,
                    ref Beta2,
                    ref BetaDelta,
                    ref GraphFreqInterval,
                    ref MinNormalizedFreq,
                    ref MaxNormalizedFreq,
                    ref GraphBetaInterval,
                    ref WaveModeDv,
                    ref IsPCWaveguide,
                    ref latticeA,
                    ref periodicDistance,
                    ref PCWaveguidePorts,
                    ref CalcModeIndex,
                    ref World,
                    ref FieldValId,
                    ref FieldLoopId,
                    ref FieldForceBcId,
                    ref FieldPortBcId1,
                    ref FieldPortBcId2,
                    ref Medias,
                    ref LoopDic,
                    ref EdgeDic,
                    ref isCadShow,
                    ref CadDrawerAry,
                    ref Camera
                    );
                //success = true;
            }
            catch (Exception exception)
            {
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            return success;
        }
Beispiel #21
0
        /// <summary>
        /// ループ内の節点番号と座標の取得(要素アレイ単位)
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">フィールド値ID</param>
        /// <param name="eaId">要素アレイID</param>
        /// <param name="to_no_boundary">全体節点番号→境界上節点番号マップ</param>
        /// <returns></returns>
        private static bool getLoopCoordList_EachElementAry(
            CFieldWorld world, uint fieldValId, uint eaId,
            double rotAngle, double[] rotOrigin,
            ref Dictionary <uint, uint> to_no_loop, ref IList <double[]> coord_c_list, ref IList <uint[]> elem_no_c_list, ref IList <uint> elem_loopId_list)
        {
            // 要素アレイを取得する
            CElemAry ea = world.GetEA(eaId);

            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.TRI);
            if (ea.ElemType() != ELEM_TYPE.TRI)
            {
                return(false);
            }

            // フィールドを取得
            CField valField = world.GetField(fieldValId);

            // 座標セグメントを取得
            CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, world);
            // 座標のノードセグメントを取得
            CNodeAry.CNodeSeg ns_c_co = valField.GetNodeSeg(ELSEG_TYPE.CORNER, false, world);

            uint node_cnt = ea.Size() + 1;  // 全節点数

            // 三角形要素の節点数
            uint nno = 3;
            // 座標の次元
            uint ndim = 2;

            // 要素節点の全体節点番号
            uint[] no_c = new uint[nno];
            // 要素節点の座標
            double[][] coord_c = new double[nno][];
            for (int inoes = 0; inoes < nno; inoes++)
            {
                coord_c[inoes] = new double[ndim];
            }

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);

                // ループID
                elem_loopId_list.Add(eaId);
                // 要素内節点番号
                {
                    uint[] work_no_c = new uint[nno];
                    no_c.CopyTo(work_no_c, 0);
                    elem_no_c_list.Add(work_no_c);
                }

                // 座標を取得
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    double[] tmpval = null;
                    ns_c_co.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == ndim);
                    for (int i = 0; i < tmpval.Length; i++)
                    {
                        coord_c[inoes][i] = tmpval[i];
                    }
                }
                if (Math.Abs(rotAngle) >= Constants.PrecisionLowerLimit)
                {
                    // 座標を回転移動する
                    for (uint inoes = 0; inoes < nno; inoes++)
                    {
                        double[] srcPt  = coord_c[inoes];
                        double[] destPt = GetRotCoord(srcPt, rotAngle, rotOrigin);
                        for (int i = 0; i < ndim; i++)
                        {
                            coord_c[inoes][i] = destPt[i];
                        }
                    }
                }

                for (uint ino = 0; ino < nno; ino++)
                {
                    if (!to_no_loop.ContainsKey(no_c[ino]))
                    {
                        uint ino_loop_tmp = (uint)to_no_loop.Count;
                        to_no_loop[no_c[ino]] = ino_loop_tmp;
                        coord_c_list.Add(new double[] { coord_c[ino][0], coord_c[ino][1] });
                        System.Diagnostics.Debug.Assert(coord_c_list.Count == (ino_loop_tmp + 1));
                    }
                }
            }
            return(true);
        }
Beispiel #22
0
        /// <summary>
        /// ロッド部セルのメッシュ作成
        /// </summary>
        /// <param name="isRodCell">セルの種類がロッド?</param>
        /// <param name="ndivForOneLattice">格子1辺の分割数</param>
        /// <param name="rodRadiusRatio">ロッドの半径割合</param>
        /// <param name="rodCircleDiv">ロッドの円周方向分割数</param>
        /// <param name="rodRadiusDiv">ロッドの半径方向分割数(1でもメッシュサイズが小さければ複数に分割される)</param>
        /// <param name="World">DelFEMワールド座標系</param>
        /// <param name="FieldValId">DelFEM値のフィールドID</param>
        /// <param name="FieldLoopId">DelFEMループのフィールドID</param>
        /// <param name="FieldForceBcId">DelFEM強制境界のフィールドID</param>
        /// <param name="FieldPortBcIds">DelFEM境界のフィールドID</param>
        /// <param name="RodLoopId">ロッドのワールド座標系ループID</param>
        private static void mkMeshCell_Rod_Tri_FirstOrder(
            bool isRodCell,
            int ndivForOneLattice,
            double rodRadiusRatio,
            int rodCircleDiv,
            int rodRadiusDiv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList <uint> FieldPortBcIds,
            out uint RodLoopId
            )
        {
            // Y方向周期構造距離
            //  セルの領域は1.0 x 1.0に規格化されてるものとする
            double periodicDistanceY = 1.0;
            // 格子定数
            double latticeA = periodicDistanceY;
            // 周期構造距離
            double periodicDistanceX = latticeA;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // ロッドの比誘電率
            //double rodEps = 3.4 * 3.4;
            // 格子1辺の分割数
            //int ndivForOneLattice = 8;
            // 境界上の総分割数
            int ndiv = ndivForOneLattice;
            // ロッドの円周分割数
            ////int rodCircleDiv = 12;
            //int rodCircleDiv = 8;
            // ロッドの半径の分割数
            ////int rodRadiusDiv = 4;
            //int rodRadiusDiv = 1;
            // メッシュの長さ
            double meshL = 1.05 * periodicDistanceY / ndiv;

            // Cad
            uint         baseLoopId = 0;
            IList <uint> rodLoopIds = new List <uint>();
            // ワールド座標系
            uint            baseId = 0;
            CIDConvEAMshCad conv   = null;

            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                // 領域を追加
                {
                    List <CVector2D> pts = new List <CVector2D>();
                    pts.Add(new CVector2D(0.0, periodicDistanceY));
                    pts.Add(new CVector2D(0.0, 0.0));
                    pts.Add(new CVector2D(periodicDistanceX, 0.0));
                    pts.Add(new CVector2D(periodicDistanceX, periodicDistanceY));
                    // 多角形追加
                    uint lId = cad2d.AddPolygon(pts).id_l_add;
                    System.Diagnostics.Debug.Assert(lId != 0);
                    baseLoopId = lId;
                }
                // 周期構造境界上の頂点を追加
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // 境界1:左
                {
                    uint   id_e = 1;
                    double x1   = 0.0;
                    double y1   = periodicDistanceY;
                    double x2   = x1;
                    double y2   = 0.0;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                // 境界2:右
                {
                    uint   id_e = 3;
                    double x1   = periodicDistanceX;
                    double y1   = 0.0;
                    double x2   = x1;
                    double y2   = periodicDistanceY;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                // 境界3:下
                {
                    uint   id_e = 2;
                    double x1   = 0.0;
                    double y1   = 0.0;
                    double x2   = periodicDistanceX;
                    double y2   = y1;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                // 境界4:上
                {
                    uint   id_e = 4;
                    double x1   = periodicDistanceX;
                    double y1   = periodicDistanceY;
                    double x2   = 0.0;
                    double y2   = y1;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }

                // ロッドを追加
                if (isRodCell)
                {
                    double x0  = periodicDistanceX * 0.5;
                    double y0  = periodicDistanceY * 0.5;
                    uint   lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                    rodLoopIds.Add(lId);
                }
                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                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;
            RodLoopId   = 0;
            const int mediaIndexCladding = 0;
            const int mediaIndexCore     = 1;

            {
                // 領域 + ロッド
                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] = mediaIndexCladding;

                // ロッド
                int offset = 1;
                rodLoopIds.ToArray().CopyTo(loopId_cad_list, offset);
                for (int i = offset; i < mediaIndex_list.Length; i++)
                {
                    mediaIndex_list[i] = mediaIndexCore;
                }
                // 要素アレイのリスト
                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);
                    System.Diagnostics.Debug.Assert(lId1 != 0);
                    if (mediaIndex == mediaIndexCore)
                    {
                        System.Diagnostics.Debug.Assert(RodLoopId == 0); // 1セル内にロッドは1つだけなので
                        RodLoopId = lId1;
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                System.Diagnostics.Debug.Assert(FieldLoopId != 0);
            }

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

            // 開口条件
            int boundaryCnt = 4;

            for (int boundaryIndex = 0; boundaryIndex < boundaryCnt; boundaryIndex++)
            {
                uint   work_fieldPortBcId = 0;
                uint[] eId_cad_list       = new uint[ndiv];
                int[]  mediaIndex_list    = new int[eId_cad_list.Length];
                if (boundaryIndex == 0)
                {
                    eId_cad_list[0] = 1;
                }
                else if (boundaryIndex == 1)
                {
                    eId_cad_list[0] = 3;
                }
                else if (boundaryIndex == 2)
                {
                    eId_cad_list[0] = 2;
                }
                else if (boundaryIndex == 3)
                {
                    eId_cad_list[0] = 4;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                mediaIndex_list[0] = mediaIndexCladding;
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    if (boundaryIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndiv - 1) - (i - 1));
                    }
                    else if (boundaryIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndiv - 1) * 2 - (i - 1));
                    }
                    else if (boundaryIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndiv - 1) * 3 - (i - 1));
                    }
                    else if (boundaryIndex == 3)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndiv - 1) * 4 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    mediaIndex_list[i] = mediaIndexCladding;
                }
                // 要素アレイのリスト
                IList <uint> aEA = new List <uint>();
                for (int i = 0; i < eId_cad_list.Length; i++)
                {
                    uint eId_cad    = eId_cad_list[i];
                    int  mediaIndex = mediaIndex_list[i];

                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    System.Diagnostics.Debug.Assert(eId != 0);
                    aEA.Add(eId);
                }
                work_fieldPortBcId = World.GetPartialField(FieldValId, aEA);
                System.Diagnostics.Debug.Assert(work_fieldPortBcId != 0);
                FieldPortBcIds.Add(work_fieldPortBcId);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="Ls"></param>
        /// <param name="Prec"></param>
        /// <param name="tmpBuffer"></param>
        /// <param name="resVec"></param>
        /// <param name="value_c_all"></param>
        /// <param name="isConverged"></param>
        /// <returns></returns>
        public static bool SolvePCOCG(
            ref CFieldWorld World, ref uint FieldValId,
            ref CZLinearSystem Ls, ref CZPreconditioner_ILU Prec, ref int[] tmpBuffer,
            ref KrdLab.clapack.Complex[] resVec, out KrdLab.clapack.Complex[] value_c_all, out bool isConverged)
        {
            bool success = false;

            //------------------------------------------------------------------
            // マージの終了
            //------------------------------------------------------------------
            double res = Ls.FinalizeMarge();

            tmpBuffer = null;

            // マトリクスサイズの取得
            // 要素剛性行列(コーナ-コーナー)
            CZMatDia_BlkCrs_Ptr mat_cc = Ls.GetMatrixPtr(FieldValId, ELSEG_TYPE.CORNER, World);
            // マトリクスのサイズ
            int matLen = (int)mat_cc.NBlkMatCol();

            //------------------------------------------------------------------
            // リニアシステムを解く
            //------------------------------------------------------------------
            System.Diagnostics.Debug.WriteLine("Solve_PCOCG : CZSolverLsIter.Solve_PCOCG");
            // プリコンディショナに値を設定してILU分解を行う
            Prec.SetValue(Ls);
            //double tol = 1.0e-1;
            //double tol = 1.0e-2;
            //double tol = 0.5e-3;
            //double tol = 1.0e-4;
            double tol = 1.0e-6;
            //uint maxIter = 500;
            //uint maxIter = 1000;
            //uint maxIter = 2000;
            //uint maxIter = 5000;
            //uint maxIter = 10000;
            uint maxIter = 20000;
            //uint maxIter = uint.MaxValue;
            uint iter = maxIter;
            bool ret  = CZSolverLsIter.Solve_PCOCG(ref tol, ref iter, Ls, Prec);

            System.Diagnostics.Debug.WriteLine("iter : " + iter + " Res : " + tol + " ret : " + ret);
            if (iter == maxIter)
            {
                System.Diagnostics.Debug.WriteLine("Not converged");
                isConverged = false;
            }
            else
            {
                isConverged = true;
            }
            System.Diagnostics.Debug.WriteLine("Solve_PCOCG solved");

            //------------------------------------------------------------------
            // 計算結果の後処理
            //------------------------------------------------------------------
            // 計算結果をワールド座標系に反映する
            Ls.UpdateValueOfField(FieldValId, World, FIELD_DERIVATION_TYPE.VALUE);

            {
                uint node_cnt = (uint)matLen;
                //value_c_all = new System.Numerics.Complex[node_cnt]; // コーナーの値
                value_c_all = new KrdLab.clapack.Complex[node_cnt]; // コーナーの値

                CField valField = World.GetField(FieldValId);
                // 要素アレイIDのリストを取得
                IList <uint> aIdEA = valField.GetAryIdEA();
                // 要素アレイを走査
                foreach (uint eaId in aIdEA)
                {
                    CElemAry          ea      = World.GetEA(eaId);
                    CElemAry.CElemSeg es_c_va = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, true, World);
                    CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, World);
                    // 要素の節点数
                    uint nno = 1; //点
                    // 要素節点の全体節点番号
                    uint[] no_c = new uint[nno];
                    // 要素節点の値
                    Complex[] value_c = new Complex[nno];
                    // 節点の値の節点セグメント
                    CNodeAry.CNodeSeg ns_c_val = valField.GetNodeSeg(ELSEG_TYPE.CORNER, true, World);
                    for (uint ielem = 0; ielem < ea.Size(); ielem++)
                    {
                        // 要素配列から要素セグメントの節点番号を取り出す
                        es_c_co.GetNodes(ielem, no_c);

                        // 節点の値を取って来る
                        es_c_va.GetNodes(ielem, no_c);
                        for (uint inoes = 0; inoes < nno; inoes++)
                        {
                            Complex[] tmpval = null;
                            ns_c_val.GetValue(no_c[inoes], out tmpval);
                            System.Diagnostics.Debug.Assert(tmpval.Length == 1);
                            value_c[inoes] = tmpval[0];
                            //System.Diagnostics.Debug.Write( "(" + value_c[inoes].Real + "," + value_c[inoes].Imag + ")" );
                        }

                        for (uint ino = 0; ino < nno; ino++)
                        {
                            //DelFEMの節点番号は0開始
                            //uint ino_global = no_c[ino] - 1;
                            uint    ino_global = no_c[ino];
                            Complex cvalue     = value_c[ino];
                            //value_c_all[ino_global] = new KrdLab.clapack.Complex(cvalue.Real, cvalue.Imag);
                            value_c_all[ino_global].Real      = cvalue.Real;
                            value_c_all[ino_global].Imaginary = cvalue.Imag;
                        }
                    }
                }
            }

            Ls.Clear();
            Ls.Dispose();
            Ls = null;
            Prec.Clear();
            Prec.Dispose();
            Prec = null;
            World.Clear();
            World.Dispose();
            World = null;
            System.Diagnostics.Debug.WriteLine("Solve_PCOCG End");
            return(success);
        }
Beispiel #24
0
        /// <summary>
        /// 問題を設定する
        /// </summary>
        /// <param name="probNo">問題番号</param>
        /// <param name="IsSolveStraightWg">直線導波路を解く?</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">値のフィールドID</param>
        /// <param name="FieldLoopId">ループのフィールドID</param>
        /// <param name="FieldForceBcId">強制境界のフィールドID</param>
        /// <param name="FieldPortBcIdList">ポートのフィールドIDリスト</param>
        /// <param name="VIdRefList">観測点頂点IDリスト</param>
        /// <param name="Medias">媒質リスト</param>
        /// <param name="LoopDic">ループID→ループ情報マップ</param>
        /// <param name="EdgeDic">エッジID→エッジ情報マップ</param>
        /// <param name="isCadShow">図面表示する?</param>
        /// <param name="CadDrawerAry">図面表示用描画オブジェクトアレイ</param>
        /// <param name="Camera">カメラ</param>
        /// <returns></returns>
        private static bool setProblem(
            int probNo,
            bool IsSolveStraightWg,
            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
            )
        {
            bool success = false;

            timeLoopCnt = 0;
            timeDelta = 0.0;
            gaussianT0 = 0.0;
            gaussianTp = 0.0;

            FieldValId = 0;
            FieldLoopId = 0;
            FieldForceBcId = 0;
            FieldPortBcIdList.Clear();
            VIdRefList.Clear();

            // 媒質リストのクリア
            Medias.Clear();
            // ワールド座標系ループ情報のクリア
            LoopDic.Clear();
            // ワールド座標系辺情報のクリア
            EdgeDic.Clear();

            // 波のモード区分
            WaveModeDv = WgUtil.WaveModeDV.TE;
            //isCadShow = false;

            SetProblemProcDelegate func = null;
            try
            {

                if (probNo == 0)
                {
                    // 直線導波管
                    //func = Problem00.SetProblem;
                    // 誘電体スラブ導波路
                    func = Problem03_0.SetProblem;
                }
                else if (probNo == 1)
                {
                    if (IsSolveStraightWg)
                    {
                        // 直線導波管
                        func = Problem00.SetProblem;
                    }
                    else
                    {
                        // 計算対象導波管
                        // 直角コーナーベンド
                        func = Problem01.SetProblem;
                    }
                }
                else if (probNo == 2)
                {
                    if (IsSolveStraightWg)
                    {
                        // 直線導波管
                        func = Problem00.SetProblem;
                    }
                    else
                    {
                        // 計算対象導波管
                        // 誘電体装荷共振器
                        func = Problem02.SetProblem;
                    }
                }
                else if (probNo == 3)
                {
                    if (IsSolveStraightWg)
                    {
                        // 誘電体導波路直線
                        func = Problem03_0.SetProblem;
                    }
                    else
                    {
                        // 誘電体導波路グレーティング
                        func = Problem03.SetProblem;
                    }
                }
                else
                {
                    return success;
                }
                success = func(
                    probNo,
                    ref WaveguideWidth,
                    ref timeLoopCnt,
                    ref timeDelta,
                    ref gaussianT0,
                    ref gaussianTp,
                    ref NormalizedFreqSrc,
                    ref NormalizedFreq1,
                    ref NormalizedFreq2,
                    ref GraphFreqInterval,
                    ref WaveModeDv,
                    ref World,
                    ref FieldValId,
                    ref FieldLoopId,
                    ref FieldForceBcId,
                    ref FieldPortBcIdList,
                    ref VIdRefList,
                    ref Medias,
                    ref LoopDic,
                    ref EdgeDic,
                    ref isCadShow,
                    ref CadDrawerAry,
                    ref Camera
                    );
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            return success;
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////
        // DekFEMの処理を隠ぺいした簡易版
        ////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// PCOCGで線形方程式を解く
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="resVec"></param>
        /// <param name="value_c_all"></param>
        /// <param name="isConverged"></param>
        /// <returns></returns>
        //public static bool SolvePCOCG(ref MyUtilLib.Matrix.MyComplexMatrix mat, ref System.Numerics.Complex[] resVec, out System.Numerics.Complex[] value_c_all, out bool isConverged)
        public static bool SolvePCOCG(ref MyUtilLib.Matrix.MyComplexMatrix mat, ref KrdLab.clapack.Complex[] resVec, out KrdLab.clapack.Complex[] value_c_all, out bool isConverged)
        {
            bool success = false;

            int matLen = mat.RowSize;

            System.Diagnostics.Debug.WriteLine("SolvePCOCG 1");
            //------------------------------------------------------------------
            // ワールド座標系を生成
            //------------------------------------------------------------------
            uint        baseId = 0;
            CFieldWorld World  = new CFieldWorld();

            setupWorld((uint)matLen, ref World, out baseId);

            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元-->ポイントにしたので0次元? 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            uint FieldValId = World.MakeField_FieldElemDim(baseId, 0,
                                                           FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            System.Diagnostics.Debug.WriteLine("SolvePCOCG 2");
            //------------------------------------------------------------------
            // リニアシステム
            //------------------------------------------------------------------
            CZLinearSystem       Ls   = new CZLinearSystem();
            CZPreconditioner_ILU Prec = new CZPreconditioner_ILU();

            //------------------------------------------------------------------
            // 界パターン追加
            //------------------------------------------------------------------
            Ls.AddPattern_Field(FieldValId, World);
            //  POINTのフィールドなので対角要素のパターンのみ追加される。非対角要素のパターンは追加されない

            // 非対角要素のパターンの追加
            {
                uint node_cnt = (uint)matLen;
                // 要素剛性行列(コーナ-コーナー)
                CZMatDia_BlkCrs_Ptr mat_cc = Ls.GetMatrixPtr(FieldValId, ELSEG_TYPE.CORNER, World);
                // 要素残差ベクトル(コーナー)
                CZVector_Blk_Ptr res_c = Ls.GetResidualPtr(FieldValId, ELSEG_TYPE.CORNER, World);

                // パターンを追加
                using (CIndexedArray crs = new CIndexedArray())
                {
                    crs.InitializeSize(mat_cc.NBlkMatCol());

                    //crs.Fill(mat_cc.NBlkMatCol(), mat_cc.NBlkMatRow());
                    using (UIntVectorIndexer index = crs.index)
                        using (UIntVectorIndexer ary = crs.array)
                        {
                            for (int iblk = 0; iblk < (int)crs.Size(); iblk++)
                            {
                                index[iblk] = 0;
                            }
                            for (int iblk = 0; iblk < mat_cc.NBlkMatCol(); iblk++)
                            {
                                // 現在のマトリクスのインデックス設定をコピーする
                                uint npsup = 0;
                                ConstUIntArrayIndexer cur_rows = mat_cc.GetPtrIndPSuP((uint)iblk, out npsup);
                                foreach (uint row_index in cur_rows)
                                {
                                    ary.Add(row_index);
                                }
                                index[iblk + 1] = (uint)ary.Count;
                                //System.Diagnostics.Debug.WriteLine("chk:{0} {1}", iblk, npsup);
                                // Note: インデックス設定はされていないので常にnpsup == 0 (cur_rows.Count == 0)

                                // すべての節点に関して列を追加
                                int ino_global = iblk;
                                int col        = iblk;
                                if (col != -1 && ino_global != -1)
                                {
                                    // 関連付けられていない節点をその行の列データの最後に追加
                                    int last_index = (int)index[col + 1] - 1;
                                    int add_cnt    = 0;
                                    for (int jno_global = 0; jno_global < node_cnt; jno_global++)
                                    {
                                        // 行列の0要素を除く
                                        //if (System.Numerics.Complex.Abs(mat[(int)ino_global, (int)jno_global]) < Constants.PrecisionLowerLimit)
                                        //if (System.Numerics.Complex.Abs(mat[(int)ino_global, (int)jno_global]) < 1.0e-15)
                                        //if (mat._body[ino_global + jno_global * mat.RowSize].Magnitude < Constants.PrecisionLowerLimit)
                                        KrdLab.clapack.Complex cvalue = mat._body[ino_global + jno_global * mat.RowSize];
                                        if (cvalue.Real == 0 && cvalue.Imaginary == 0)
                                        {
                                            continue;
                                        }
                                        uint row = (uint)jno_global;
                                        if (ino_global != jno_global) // 対角要素は除く
                                        {
                                            if (!cur_rows.Contains(row))
                                            {
                                                ary.Insert(last_index + 1 + add_cnt, row);
                                                add_cnt++;
                                                //System.Diagnostics.Debug.WriteLine("added:" + col + " " + row);
                                            }
                                        }
                                    }
                                    if (add_cnt > 0)
                                    {
                                        index[col + 1] = (uint)ary.Count;
                                    }
                                }
                            }
                        }
                    crs.Sort();
                    System.Diagnostics.Debug.Assert(crs.CheckValid());
                    // パターンを削除する
                    mat_cc.DeletePattern();
                    // パターンを追加する
                    mat_cc.AddPattern(crs);
                }
            }

            System.Diagnostics.Debug.WriteLine("SolvePCOCG 3");
            //------------------------------------------------------------------
            // プリコンディショナ―
            //------------------------------------------------------------------
            // set Preconditioner
            //Prec.SetFillInLevel(1);
            // フィルインなしで不完全LU分解した方が収束が早く、また解もそれなりの結果だったので0に設定した
            //Prec.SetFillInLevel(0);
            // フィルインなしでは、収束しない場合がある。フィルインレベルを最大にする
            //Prec.SetFillInLevel((uint)mat.RowSize);
            //   完全LU分解(だと思われる) Prec.SetLinearSystemの処理が遅い
            //Prec.SetFillInLevel(3);
            //   誘電体スラブ導波路だと最低このレベル。これでも収束しない場合がある
            //以上から
            //メインの導波管の計算時間を短くしたいのでフィルインなしにする
            //Prec.SetFillInLevel(0);
            //    導波管だとこれで十分
            // フィルインレベルの設定(既定値)
            Prec.SetFillInLevel(DefFillInLevel);
            // ILU(0)のパターン初期化
            Prec.SetLinearSystem(Ls);
            System.Diagnostics.Debug.WriteLine("SolvePCOCG 4");

            //------------------------------------------------------------------
            // 剛性行列、残差ベクトルのマージ
            //------------------------------------------------------------------
            Ls.InitializeMarge();
            {
                uint  ntmp      = Ls.GetTmpBufferSize();
                int[] tmpBuffer = new int[ntmp];
                for (int i = 0; i < ntmp; i++)
                {
                    tmpBuffer[i] = -1;
                }

                uint node_cnt = (uint)matLen;

                // 要素剛性行列(コーナ-コーナー)
                CZMatDia_BlkCrs_Ptr mat_cc = Ls.GetMatrixPtr(FieldValId, ELSEG_TYPE.CORNER, World);
                // 要素残差ベクトル(コーナー)
                CZVector_Blk_Ptr res_c = Ls.GetResidualPtr(FieldValId, ELSEG_TYPE.CORNER, World);

                bool[,] add_flg = new bool[node_cnt, node_cnt];
                for (int i = 0; i < node_cnt; i++)
                {
                    for (int j = 0; j < node_cnt; j++)
                    {
                        add_flg[i, j] = false;
                        // 0要素はマージ対象でないので最初から除外する
                        //if (System.Numerics.Complex.Abs(mat[i, j]) < Constants.PrecisionLowerLimit)
                        //if (mat._body[i + j * mat.RowSize].Magnitude < Constants.PrecisionLowerLimit)
                        KrdLab.clapack.Complex cvalue = mat._body[i + j * mat.RowSize];
                        if (cvalue.Real == 0 && cvalue.Imaginary == 0)
                        {
                            add_flg[i, j] = true;
                        }
                    }
                }
                for (int iblk = 0; iblk < mat_cc.NBlkMatCol(); iblk++)
                {
                    // 自分及び自分自身と関連のある"row"の要素をマージする( 1 x rowcntのベクトル : 行列の横ベクトルに対応)
                    uint npsup = 0;
                    ConstUIntArrayIndexer cur_rows = mat_cc.GetPtrIndPSuP((uint)iblk, out npsup);
                    uint      colcnt       = 1;
                    uint      rowcnt       = (uint)cur_rows.Count + 1; // cur_rowsには自分自身は含まれないので+1する
                    Complex[] emattmp      = new Complex[colcnt * rowcnt];
                    uint[]    no_c_tmp_col = new uint[colcnt];
                    uint[]    no_c_tmp_row = new uint[rowcnt];
                    no_c_tmp_col[0] = (uint)iblk;
                    no_c_tmp_row[0] = (uint)iblk;
                    for (int irow = 0; irow < cur_rows.Count; irow++)
                    {
                        no_c_tmp_row[irow + 1] = cur_rows[irow];
                    }
                    {
                        uint ino        = 0;
                        uint ino_global = no_c_tmp_col[ino];
                        for (int jno = 0; jno < rowcnt; jno++)
                        {
                            uint jno_global = no_c_tmp_row[jno];
                            //emat[ino, jno]
                            if (!add_flg[ino_global, jno_global])
                            {
                                //System.Numerics.Complex cvalue = (System.Numerics.Complex)mat[ino_global, jno_global];
                                //System.Numerics.Complex cvalue = (System.Numerics.Complex)mat._body[ino_global + jno_global * mat.RowSize];
                                KrdLab.clapack.Complex cvalue = mat._body[ino_global + jno_global * mat.RowSize];
                                emattmp[ino * rowcnt + jno]     = new Complex(cvalue.Real, cvalue.Imaginary);
                                add_flg[ino_global, jno_global] = true;
                            }
                            else
                            {
                                // ここにはこない
                                System.Diagnostics.Debug.Assert(false);
                                emattmp[ino * rowcnt + jno] = new Complex(0, 0);
                            }
                        }
                    }
                    // マージ!
                    mat_cc.Mearge(1, no_c_tmp_col, rowcnt, no_c_tmp_row, 1, emattmp, ref tmpBuffer);
                }
                for (int i = 0; i < node_cnt; i++)
                {
                    for (int j = 0; j < node_cnt; j++)
                    {
                        //System.Diagnostics.Debug.WriteLine( i + " " + j + " " + add_flg[i, j] );
                        System.Diagnostics.Debug.Assert(add_flg[i, j]);
                    }
                }

                // 残差ベクトルにマージ
                for (uint ino_global = 0; ino_global < node_cnt; ino_global++)
                {
                    // 残差ベクトルにマージする
                    uint no_tmp = ino_global;
                    //System.Numerics.Complex cvalue = resVec[ino_global];
                    KrdLab.clapack.Complex cvalue = resVec[ino_global];
                    Complex val = new Complex(cvalue.Real, cvalue.Imaginary);
                    res_c.AddValue(no_tmp, 0, val);
                }
            }
            double res = Ls.FinalizeMarge();

            //------------------------------------------------------------------
            // リニアシステムを解く
            //------------------------------------------------------------------
            System.Diagnostics.Debug.WriteLine("Solve_PCOCG 5: CZSolverLsIter.Solve_PCOCG");
            // プリコンディショナに値を設定してILU分解を行う
            Prec.SetValue(Ls);
            //double tol = 1.0e-1;
            //double tol = 1.0e-2;
            //double tol = 0.5e-3;
            //double tol = 1.0e-4;
            double tol = 1.0e-6;
            //uint maxIter = 500;
            //uint maxIter = 1000;
            //uint maxIter = 2000;
            //uint maxIter = 5000;
            //uint maxIter = 10000;
            uint maxIter = 20000;
            //uint maxIter = uint.MaxValue;
            uint iter = maxIter;
            bool ret  = CZSolverLsIter.Solve_PCOCG(ref tol, ref iter, Ls, Prec);

            System.Diagnostics.Debug.WriteLine("iter : " + iter + " Res : " + tol + " ret : " + ret);
            if (iter == maxIter)
            {
                System.Diagnostics.Debug.WriteLine("Not converged");
                isConverged = false;
            }
            else
            {
                isConverged = true;
            }
            System.Diagnostics.Debug.WriteLine("Solve_PCOCG 6");

            //------------------------------------------------------------------
            // 計算結果の後処理
            //------------------------------------------------------------------
            // 計算結果をワールド座標系に反映する
            Ls.UpdateValueOfField(FieldValId, World, FIELD_DERIVATION_TYPE.VALUE);

            {
                uint node_cnt = (uint)matLen;
                //value_c_all = new System.Numerics.Complex[node_cnt]; // コーナーの値
                value_c_all = new KrdLab.clapack.Complex[node_cnt]; // コーナーの値

                CField valField = World.GetField(FieldValId);
                // 要素アレイIDのリストを取得
                IList <uint> aIdEA = valField.GetAryIdEA();
                // 要素アレイを走査
                foreach (uint eaId in aIdEA)
                {
                    CElemAry          ea      = World.GetEA(eaId);
                    CElemAry.CElemSeg es_c_va = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, true, World);
                    CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, World);
                    // 要素の節点数
                    uint nno = 1; //点
                    // 要素節点の全体節点番号
                    uint[] no_c = new uint[nno];
                    // 要素節点の値
                    Complex[] value_c = new Complex[nno];
                    // 節点の値の節点セグメント
                    CNodeAry.CNodeSeg ns_c_val = valField.GetNodeSeg(ELSEG_TYPE.CORNER, true, World);
                    for (uint ielem = 0; ielem < ea.Size(); ielem++)
                    {
                        // 要素配列から要素セグメントの節点番号を取り出す
                        es_c_co.GetNodes(ielem, no_c);

                        // 節点の値を取って来る
                        es_c_va.GetNodes(ielem, no_c);
                        for (uint inoes = 0; inoes < nno; inoes++)
                        {
                            Complex[] tmpval = null;
                            ns_c_val.GetValue(no_c[inoes], out tmpval);
                            System.Diagnostics.Debug.Assert(tmpval.Length == 1);
                            value_c[inoes] = tmpval[0];
                            //System.Diagnostics.Debug.Write( "(" + value_c[inoes].Real + "," + value_c[inoes].Imag + ")" );
                        }

                        for (uint ino = 0; ino < nno; ino++)
                        {
                            //DelFEMの節点番号は0開始
                            //uint ino_global = no_c[ino] - 1;
                            uint    ino_global = no_c[ino];
                            Complex cvalue     = value_c[ino];
                            //value_c_all[ino_global] = new KrdLab.clapack.Complex(cvalue.Real, cvalue.Imag);
                            value_c_all[ino_global].Real      = cvalue.Real;
                            value_c_all[ino_global].Imaginary = cvalue.Imag;
                        }
                    }
                }
            }

            Ls.Clear();
            Ls.Dispose();
            Prec.Clear();
            Prec.Dispose();
            World.Clear();
            World.Dispose();
            System.Diagnostics.Debug.WriteLine("Solve_PCOCG End");
            return(success);
        }
Beispiel #26
0
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainLogic()
        {
            Disposed = false;
            Camera = new CCamera();
            DrawerAry = new CDrawerArrayField();
            World = new CFieldWorld();
            //FieldValueSetter = new CFieldValueSetter();
            CadDrawerAry = new CDrawerArray();
            IsInitedCamera = true;

            // Glutのアイドル時処理でなく、タイマーで再描画イベントを発生させる
            MyTimer.Tick +=(sender, e) =>
            {
                if (IsTimerProcRun)
                {
                    return;
                }
                IsTimerProcRun = true;
                runTimerProc();
                IsTimerProcRun = false;
            };
            MyTimer.Interval = 1000 / 120;
            //MyTimer.Interval = 1000 / 60;
            //MyTimer.Interval = 1000 / 10;
            //MyTimer.Interval = 2000;
        }
        /// <summary>
        /// リニアシステム初期化(マージ開始までの処理)
        /// </summary>
        /// <param name="matPattern">行列の非0要素パターン</param>
        /// <param name="Ls"></param>
        /// <param name="Prec"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        public static void SetupLinearSystem(
            bool[,] matPattern,
            out CFieldWorld World, out uint FieldValId,
            out CZLinearSystem Ls, out CZPreconditioner_ILU Prec, out int[] tmpBuffer)
        {
            World     = new CFieldWorld();
            Ls        = new CZLinearSystem();
            Prec      = new CZPreconditioner_ILU();
            tmpBuffer = null;

            int matLen = matPattern.GetLength(0);

            //------------------------------------------------------------------
            // ワールド座標系を生成
            //------------------------------------------------------------------
            uint baseId = 0;

            setupWorld((uint)matLen, ref World, out baseId);

            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元-->ポイントにしたので0次元? 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 0,
                                                      FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            //------------------------------------------------------------------
            // 界パターン追加
            //------------------------------------------------------------------
            Ls.AddPattern_Field(FieldValId, World);
            //  POINTのフィールドなので対角要素のパターンのみ追加される。非対角要素のパターンは追加されない

            // 非対角要素のパターンの追加
            {
                uint node_cnt = (uint)matLen;
                // 要素剛性行列(コーナ-コーナー)
                CZMatDia_BlkCrs_Ptr mat_cc = Ls.GetMatrixPtr(FieldValId, ELSEG_TYPE.CORNER, World);
                // 要素残差ベクトル(コーナー)
                CZVector_Blk_Ptr res_c = Ls.GetResidualPtr(FieldValId, ELSEG_TYPE.CORNER, World);

                // パターンを追加
                using (CIndexedArray crs = new CIndexedArray())
                {
                    crs.InitializeSize(mat_cc.NBlkMatCol());

                    //crs.Fill(mat_cc.NBlkMatCol(), mat_cc.NBlkMatRow());
                    using (UIntVectorIndexer index = crs.index)
                        using (UIntVectorIndexer ary = crs.array)
                        {
                            //BUGFIX
                            //for (int iblk = 0; iblk < (int)crs.Size(); iblk++)
                            // indexのサイズは crs.Size() + 1 (crs.Size() > 0のとき)
                            for (int iblk = 0; iblk < index.Count; iblk++)
                            {
                                index[iblk] = 0;
                            }
                            for (int iblk = 0; iblk < mat_cc.NBlkMatCol(); iblk++)
                            {
                                // 現在のマトリクスのインデックス設定をコピーする
                                uint npsup = 0;
                                ConstUIntArrayIndexer cur_rows = mat_cc.GetPtrIndPSuP((uint)iblk, out npsup);
                                foreach (uint row_index in cur_rows)
                                {
                                    ary.Add(row_index);
                                }
                                index[iblk + 1] = (uint)ary.Count;
                                //System.Diagnostics.Debug.WriteLine("chk:{0} {1}", iblk, npsup);
                                // Note: インデックス設定はされていないので常にnpsup == 0 (cur_rows.Count == 0)

                                // すべての節点に関して列を追加
                                int ino_global = iblk;
                                int col        = iblk;
                                if (col != -1 && ino_global != -1)
                                {
                                    // 関連付けられていない節点をその行の列データの最後に追加
                                    //int last_index = (int)index[col + 1] - 1;
                                    //System.Diagnostics.Debug.Assert(last_index == ary.Count - 1);
                                    int add_cnt = 0;
                                    for (int jno_global = 0; jno_global < node_cnt; jno_global++)
                                    {
                                        if (!matPattern[ino_global, jno_global])
                                        {
                                            continue;
                                        }
                                        uint row = (uint)jno_global;
                                        //if (ino_global != jno_global)  // 対角要素は除く
                                        if (col != row) // 対角要素は除く
                                        {
                                            if (!cur_rows.Contains(row))
                                            {
                                                //ary.Insert(last_index + 1 + add_cnt, row);
                                                ary.Add(row);
                                                add_cnt++;
                                                //System.Diagnostics.Debug.WriteLine("added:" + col + " " + row);
                                            }
                                        }
                                    }
                                    if (add_cnt > 0)
                                    {
                                        index[col + 1] = (uint)ary.Count;
                                    }
                                }
                            }
                        }
                    crs.Sort();
                    System.Diagnostics.Debug.Assert(crs.CheckValid());
                    // パターンを削除する
                    mat_cc.DeletePattern();
                    // パターンを追加する
                    mat_cc.AddPattern(crs);
                }
            }

            //------------------------------------------------------------------
            // プリコンディショナ―
            //------------------------------------------------------------------
            // set Preconditioner
            //Prec.SetFillInLevel(1);
            // フィルインなしで不完全LU分解した方が収束が早く、また解もそれなりの結果だったので0に設定した
            //Prec.SetFillInLevel(0);
            // フィルインなしでは、収束しない場合がある。フィルインレベルを最大にする
            //Prec.SetFillInLevel((uint)mat.RowSize);
            //   完全LU分解(だと思われる) Prec.SetLinearSystemの処理が遅い
            //Prec.SetFillInLevel(3);
            //   誘電体スラブ導波路だと最低このレベル。これでも収束しない場合がある
            //以上から
            //メインの導波管の計算時間を短くしたいのでフィルインなしにする
            //Prec.SetFillInLevel(0);
            //    導波管だとこれで十分
            // フィルインレベルの設定(既定値)
            Prec.SetFillInLevel(DefFillInLevel);
            // ILU(0)のパターン初期化
            Prec.SetLinearSystem(Ls);

            //------------------------------------------------------------------
            // 剛性行列、残差ベクトルのマージ開始
            //------------------------------------------------------------------
            Ls.InitializeMarge();
            uint ntmp = Ls.GetTmpBufferSize();

            tmpBuffer = new int[ntmp];
            for (int i = 0; i < ntmp; i++)
            {
                tmpBuffer[i] = -1;
            }
        }
Beispiel #28
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;
        }
        /// <summary>
        /// ワールド座標系を構成する
        /// </summary>
        /// <param name="ncolrow">行列のrowSize(==columnSize)</param>
        /// <param name="world">ワールド座標系オブジェクト</param>
        /// <param name="id_field_base">フィールドIDのベース</param>
        /// <returns></returns>
        private static bool setupWorld(uint ncolrow, ref CFieldWorld world, out uint id_field_base)
        {
            bool success = false;

            id_field_base = 0;

            uint id_na, id_ns_co;
            {
                // 節点を生成
                uint ndim  = 2;
                uint nnode = ncolrow;
                id_na = world.AddNodeAry(nnode);
                // 書き込み用に節点アレイのポインタを取得
                CNodeAryPtr na = world.GetNAPtr(id_na);
                id_ns_co = na.GetFreeSegID();
                CNodeAry.CNodeSeg ns_co = new CNodeAry.CNodeSeg(ndim, "COORD");
                IList <Pair <uint, CNodeAry.CNodeSeg> > ns_input_ary = new List <Pair <uint, CNodeAry.CNodeSeg> >();
                ns_input_ary.Add(new Pair <uint, CNodeAry.CNodeSeg>(id_ns_co, ns_co));
                // 座標は分からないので空リストを追加
                IList <double> coord = new List <double>();
                for (int i = 0; i < nnode; i++)
                {
                    for (int k = 0; k < ndim; k++)
                    {
                        coord.Add(0);
                    }
                }
                IList <int> add_id_ary = na.AddSegment(ns_input_ary, coord);
            }

            IList <CField.CElemInterpolation> aElemIntp = new List <CField.CElemInterpolation>();// 要素Index
            IList <Pair <uint, uint> >        aEaEs     = new List <Pair <uint, uint> >();

            {
                // 要素を生成
                uint id_ea;
                uint id_es;
                // 本当は三角形要素で要素を追加するところだが、わからないので
                // 要素は点で追加する
                int  ilayer = 0;
                uint nnode  = ncolrow;
                uint nnoel  = 1; // 要素内節点数
                //CAD_ELEM_TYPE itype_cad_part = CAD_ELEM_TYPE.VERTEX;
                uint nelem = nnode / nnoel;
                id_ea = world.AddElemAry(nelem, ELEM_TYPE.POINT);
                // 書き込み用に要素アレイのポインタを取得
                CElemAryPtr ea = world.GetEAPtr(id_ea);
                // 節点番号のリスト
                IList <int> lnods = new List <int>((int)nnode);
                for (int ino = 0; ino < nnode; ino++)
                {
                    //lnods.Add(ino + 1);
                    //DelFEMの節点番号は0開始
                    lnods.Add(ino);
                }
                uint id_es_tmp       = ea.GetFreeSegID();
                CElemAry.CElemSeg es = new CElemAry.CElemSeg(id_na, ELSEG_TYPE.CORNER);
                id_es = (uint)ea.AddSegment(id_es_tmp, es, lnods);

                aEaEs.Add(new Pair <uint, uint>(id_ea, id_es));
                CField.CElemInterpolation ei = new CField.CElemInterpolation(id_ea, 0, id_es, 0, 0, 0, 0);
                ei.ilayer = ilayer;
                aElemIntp.Add(ei);
            }
            {
                // 要素と節点の関連付け
                // 書き込み用に節点アレイのポインタを取得する
                CNodeAryPtr na = world.GetNAPtr(id_na);
                for (int ieaes = 0; ieaes < aEaEs.Count; ieaes++)
                {
                    na.AddEaEs(aEaEs[ieaes]);
                }
            }
            {
                // フィールドを生成
                uint id_field_parent            = 0;                                                                       // 親フィールド
                CField.CNodeSegInNodeAry nsna_c = new CField.CNodeSegInNodeAry(id_na, false, id_ns_co, 0, false, 0, 0, 0); // CORNER節点
                CField.CNodeSegInNodeAry nsna_b = new CField.CNodeSegInNodeAry();                                          // BUBBLE節点

                id_field_base = world.AddField(id_field_parent, aElemIntp, nsna_c, nsna_b);
            }

            return(success);
        }
Beispiel #30
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;
        }
Beispiel #31
0
        /// <summary>
        /// PML媒質内の要素の残差ベクトルを加算する(要素アレイ単位)
        /// </summary>
        /// <param name="timeIndex"></param>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="pmlStPosX"></param>
        /// <param name="pmlLength"></param>
        /// <param name="dt"></param>
        /// <param name="newmarkBeta"></param>
        /// <param name="media"></param>
        /// <param name="eaId"></param>
        /// <param name="node_cnt"></param>
        /// <param name="free_node_cnt"></param>
        /// <param name="toSorted"></param>
        /// <param name="Ez_Prev"></param>
        /// <param name="Ez_Prev2"></param>
        /// <param name="w2_F_e_EA"></param>
        /// <param name="w2_G_e_EA"></param>
        /// <param name="resVec"></param>
        /// <returns></returns>
        private static bool addPmlResVec_EachElementAry(
            int timeIndex,
            CFieldWorld world,
            uint fieldValId,
            bool isPmlYDirection,
            double pmlStPosX,
            double pmlLength,
            double dt,
            double newmarkBeta,
            MediaInfo media,
            uint eaId,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            double[] Ez_Prev,
            double[] Ez_Prev2,
            ref double[][] w2_F_e_EA,
            ref double[][] w2_G_e_EA,
            ref double[] resVec)
        {
            System.Diagnostics.Debug.Assert(free_node_cnt == resVec.Length);
            System.Diagnostics.Debug.Assert(world.IsIdEA(eaId));
            // 要素アレイを取得
            CElemAry ea = world.GetEA(eaId);
            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.TRI);
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            // 値のフィールドを取得
            CField valField = world.GetField(fieldValId);
            // 値の要素セグメント(コーナー)を取得
            CElemAry.CElemSeg es_c_va = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, true, world);
            // 座標の要素セグメント(コーナー)を取得
            CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, world);

            uint nno = 3;
            uint ndim = 2;
            // 要素節点の全体節点番号
            uint[] no_c = new uint[nno];
            // 要素節点の値
            Complex[] value_c = new Complex[nno];
            // 要素節点の座標
            double[,] coord_c = new double[nno, ndim];
            // 要素行列
            double[,] eMMat = new double[nno, nno];
            double[,] eKXMat = new double[nno, nno];
            double[,] eKYMat = new double[nno, nno];

            CNodeAry.CNodeSeg ns_c_val = valField.GetNodeSeg(ELSEG_TYPE.CORNER, true, world);
            CNodeAry.CNodeSeg ns_c_co = valField.GetNodeSeg(ELSEG_TYPE.CORNER, false, world);

            // 初回ステップ
            if (timeIndex == 0)
            {
                w2_F_e_EA = new double[ea.Size()][];
                w2_G_e_EA = new double[ea.Size()][];
                for (int ielem = 0; ielem < ea.Size(); ielem++)
                {
                    w2_F_e_EA[ielem] = new double[nno];
                    w2_G_e_EA[ielem] = new double[nno];
                }
            }

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);
                // 座標を取得
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    double[] tmpval = null;
                    ns_c_co.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == ndim);
                    for (int i = 0; i < tmpval.Length; i++)
                    {
                        coord_c[inoes, i] = tmpval[i];
                    }
                }

                // 節点の値を取って来る
                es_c_va.GetNodes(ielem, no_c);
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    Complex[] tmpval = null;
                    ns_c_val.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == 1);
                    value_c[inoes] = tmpval[0];
                }

                // 節点座標
                double[] p1 = new double[ndim];
                double[] p2 = new double[ndim];
                double[] p3 = new double[ndim];
                for (int i = 0; i < ndim; i++)
                {
                    p1[i] = coord_c[0, i];
                    p2[i] = coord_c[1, i];
                    p3[i] = coord_c[2, i];
                }
                // 面積を求める
                double area = CKerEMatTri.TriArea(p1, p2, p3);

                // 形状関数の微分を求める
                double[,] dldx = null;
                double[] const_term = null;
                CKerEMatTri.TriDlDx(out dldx, out const_term, p1, p2, p3);

                // ∫(dLi/dx)(dLj/dx) dxdy
                double[,] integralDLDX = new double[3, 3];
                // ∫(dLi/dy)(dLj/dy) dxdy
                double[,] integralDLDY = new double[3, 3];
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDX[ino, jno] = area * dldx[ino, 0] * dldx[jno, 0];
                    }
                }
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDY[ino, jno] = area * dldx[ino, 1] * dldx[jno, 1];
                    }
                }
                /*
                // ∫(dLi/dx)Lj dxdy
                double[,] integralDLDXL = new double[3, 3];
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDXL[ino, jno] = area * dldx[ino, 0] / 3.0;
                    }
                }
                // ∫(dLi/dy)Lj dxdy
                double[,] integralDLDYL = new double[3, 3];
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDYL[ino, jno] = area * dldx[ino, 1] / 3.0;
                    }
                }
                 */
                // ∫LiLj dxdy
                double[,] integralL = new double[3, 3]
                {
                    { area / 6.0 , area / 12.0, area / 12.0 },
                    { area / 12.0, area /  6.0, area / 12.0 },
                    { area / 12.0, area / 12.0, area /  6.0 },

                };

                // 要素剛性行列、要素質量行列を作る
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        // 要素剛性行列
                        eKXMat[ino, jno] = media.P[1, 1] * integralDLDX[ino, jno];
                        eKYMat[ino, jno] = media.P[0, 0] * integralDLDY[ino, jno];
                        // 要素質量行列
                        eMMat[ino, jno] = eps0 * myu0 * media.Q[2, 2] * integralL[ino, jno];
                    }
                }

                // PML媒質パラメータ
                double posXG = (p1[0] + p2[0] + p3[0]) / 3.0;
                if (isPmlYDirection)
                {
                    posXG = (p1[1] + p2[1] + p3[1]) / 3.0;
                }
                double sigmaX_e = 0.0;
                double c1_F_e = 0.0;
                double c1_G_e = 0.0;
                double c3_G_e = 0.0;
                GetPmlParameter(
                    posXG,
                    pmlStPosX,
                    pmlLength,
                    dt,
                    out sigmaX_e,
                    out c1_F_e,
                    out c1_G_e,
                    out c3_G_e);

                // w2_F, w2_Gの更新
                double[] w2_F_e = w2_F_e_EA[(int)ielem];
                double[] w2_G_e = w2_G_e_EA[(int)ielem];
                for (int ino = 0; ino < nno; ino++)
                {
                    uint iNodeNumber = no_c[ino];
                    if (!toSorted.ContainsKey(iNodeNumber)) continue;
                    int inoGlobal = (int)toSorted[iNodeNumber];

                    w2_F_e[ino] = c1_F_e * Ez_Prev2[inoGlobal] + w2_F_e[ino];
                    w2_G_e[ino] = c1_G_e * Ez_Prev2[inoGlobal] + c3_G_e * w2_G_e[ino];
                }

                // 残差ベクトルにマージする
                double[,] work_eKXMat = eKXMat;
                double[,] work_eKYMat = eKYMat;
                if (isPmlYDirection)
                {
                    work_eKXMat = eKYMat;
                    work_eKYMat = eKXMat;
                }
                for (int ino = 0; ino < nno; ino++)
                {
                    uint iNodeNumber = no_c[ino];
                    if (!toSorted.ContainsKey(iNodeNumber)) continue;
                    int inoGlobal = (int)toSorted[iNodeNumber];
                    double resVec_inoGlobal = 0.0;
                    for (int jno = 0; jno < nno; jno++)
                    {
                        uint jNodeNumber = no_c[jno];
                        if (!toSorted.ContainsKey(jNodeNumber)) continue;
                        int jnoGlobal = (int)toSorted[jNodeNumber];

                        resVec_inoGlobal +=
                            (sigmaX_e / eps0) * (1.0 / (2.0 * dt)) * eMMat[ino, jno] * Ez_Prev2[jnoGlobal]
                            - 1.0 * work_eKYMat[ino, jno] * (
                                (1.0 - newmarkBeta) * c1_F_e * Ez_Prev[jnoGlobal]
                                + w2_F_e[jno]
                                )
                            - 1.0 * work_eKXMat[ino, jno] * (
                                (newmarkBeta * c3_G_e * c1_G_e + (1.0 - 2.0 * newmarkBeta) * c1_G_e) * Ez_Prev[jnoGlobal]
                                + (newmarkBeta * c3_G_e * c3_G_e + (1.0 - 2.0 * newmarkBeta) * c3_G_e + newmarkBeta) * w2_G_e[jno]
                                );
                    }
                    resVec[inoGlobal] += resVec_inoGlobal;
                }
            }

            return true;
        }
Beispiel #32
0
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainLogic()
        {
            Disposed = false;
            Camera = new CCamera();
            DrawerAry = new CDrawerArrayField();
            World = new CFieldWorld();
            FieldValueSetter = new CFieldValueSetter();
            Ls = new CLinearSystem_Field();
            Prec = new CPreconditioner_ILU();

            // Glutのアイドル時処理でなく、タイマーで再描画イベントを発生させる
            MyTimer.Tick +=(sender, e) =>
            {
                Glut.glutPostRedisplay();
            };
            MyTimer.Interval = 1000 / 60;
        }
Beispiel #33
0
        ////////////////////////////////////////////////////////////////////////
        // 型
        ////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// ヘルムホルツの方程式 PML要素の全体行列の追加
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">値のフィールドID</param>
        /// <param name="pmlStPosX">PML媒質開始位置X座標</param>
        /// <param name="pmlLength">PML長さ</param>
        /// <param name="dt">時刻刻み幅</param>
        /// <param name="newmarkBeta">Newmark法 β</param>
        /// <param name="medias">媒質リスト</param>
        /// <param name="loopDic">ループID→ループ情報マップ</param>
        /// <param name="node_cnt">解析領域全体の節点数</param>
        /// <param name="free_node_cnt">解析領域全体の自由節点数(強制境界を除いた節点数)</param>
        /// <param name="toSorted">節点番号→ソート済み(強制境界を除いた)節点リストのインデックスマップ</param>
        /// <param name="AMat">全体行列</param>
        /// <returns></returns>
        public static bool AddPmlMat(
            CFieldWorld world,
            uint fieldValId,
            bool isPmlYDirection,
            double pmlStPosX,
            double pmlLength,
            double dt,
            double newmarkBeta,
            IList<MediaInfo> medias,
            Dictionary<uint, World.Loop> loopDic,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            ref MyDoubleBandMatrix AMat)
        {
            // 値のフィールドIDかチェック
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            // 値のフィールドを取得する
            CField valField = world.GetField(fieldValId);
            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return false;
            }

            // 要素アレイのリストを取得する
            IList<uint> aIdEA = valField.GetAryIdEA();
            foreach (uint eaId in aIdEA)
            {
                if (valField.GetInterpolationType(eaId, world) == INTERPOLATION_TYPE.TRI11)
                {
                    // 媒質を取得する
                    MediaInfo media = new MediaInfo();
                    {
                        // ループのIDのはず
                        uint lId = eaId;
                        if (loopDic.ContainsKey(lId))
                        {
                            World.Loop loop = loopDic[lId];
                            media = medias[loop.MediaIndex];
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    bool res = addPmlMat_EachElementAry(
                        world,
                        fieldValId,
                        isPmlYDirection,
                        pmlStPosX,
                        pmlLength,
                        dt,
                        newmarkBeta,
                        media,
                        eaId,
                        node_cnt,
                        free_node_cnt,
                        toSorted,
                        ref AMat
                        );
                    if (!res)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
Beispiel #34
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;
        }
Beispiel #35
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;
        }
        /// <summary>
        /// ヘルムホルツの方程式 Sommerfelt放射条件(要素アレイ単位)
        /// </summary>
        /// <param name="ls"></param>
        /// <param name="waveLength"></param>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="eaId"></param>
        /// <param name="tmpBuffer"></param>
        /// <returns></returns>
        private static bool AddLinSys_SommerfeltRadiationBC_EachElementAry(CZLinearSystem ls, double waveLength, CFieldWorld world, uint fieldValId, uint eaId, int[] tmpBuffer)
        {
            System.Diagnostics.Debug.Assert(world.IsIdEA(eaId));
            CElemAry ea = world.GetEA(eaId);
            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.LINE);
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            CField valField = world.GetField(fieldValId);
            CElemAry.CElemSeg es_c_va = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, true, world);
            CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, world);

            // 線要素の節点数
            uint nno = 2;
            // 座標の次元
            uint ndim = 2;
            // 要素節点の全体節点番号
            uint[] no_c = new uint[nno];
            // 要素節点の値
            Complex[] value_c = new Complex[nno];
            // 要素節点の座標
            double[][] coord_c = new double[nno][];
            for (int inoes = 0; inoes < nno; inoes++)
            {
                coord_c[inoes] = new double[ndim];
            }
            // 要素剛性行列 (i, j) --> (i * RowSize + j)
            Complex[] ematBuffer = new Complex[nno * nno];
            // 要素節点等価内力、外力、残差ベクトル
            Complex[] eres_c = new Complex[nno];
            // 要素剛性行列(コーナ-コーナー)
            CZMatDia_BlkCrs_Ptr mat_cc = ls.GetMatrixPtr(fieldValId, ELSEG_TYPE.CORNER, world);
            // 要素残差ベクトル(コーナー)
            CZVector_Blk_Ptr res_c = ls.GetResidualPtr(fieldValId, ELSEG_TYPE.CORNER, world);

            CNodeAry.CNodeSeg ns_c_val = valField.GetNodeSeg(ELSEG_TYPE.CORNER, true, world);
            CNodeAry.CNodeSeg ns_c_co = valField.GetNodeSeg(ELSEG_TYPE.CORNER, false, world);

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);

                // 座標を取得
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    double[] tmpval = null;
                    ns_c_co.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == ndim);
                    for (int i = 0; i < tmpval.Length; i++)
                    {
                        coord_c[inoes][i] = tmpval[i];
                    }
                }

                // 節点の値を取って来る
                es_c_va.GetNodes(ielem, no_c);
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    Complex[] tmpval = null;
                    ns_c_val.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == 1);
                    value_c[inoes] = tmpval[0];
                }
                double elen = Math.Sqrt((coord_c[0][0] - coord_c[1][0]) * (coord_c[0][0] - coord_c[1][0]) + (coord_c[0][1] - coord_c[1][1]) * (coord_c[0][1] - coord_c[1][1]));

                double k = 2.0 * pi / waveLength;
                Complex tmp_val1 = (k / 6.0 * elen) * (new Complex(0, 1));
                Complex tmp_val2 = -1 / (2.0 * elen * k) * (new Complex(0, 1));
                //emat[0, 0]
                ematBuffer[0] = tmp_val1 * 2 + tmp_val2;
                //emat[0, 1]
                ematBuffer[1] = tmp_val1 - tmp_val2;
                //emat[1, 0]
                ematBuffer[nno] = tmp_val1 - tmp_val2;
                //emat[1, 1]
                ematBuffer[nno + 1] = tmp_val1 * 2 + tmp_val2;

                // 要素節点等価内力ベクトルを求める
                for (int ino = 0; ino < nno; ino++)
                {
                    eres_c[ino] = new Complex(0.0);
                    for (int jno = 0; jno < nno; jno++)
                    {
                        eres_c[ino] -= ematBuffer[ino * nno + jno] * value_c[jno];
                    }
                }

                // 要素剛性行列にマージする
                mat_cc.Mearge(nno, no_c, nno, no_c, 1, ematBuffer, ref tmpBuffer);

                // 残差ベクトルにマージする
                for (int inoes = 0; inoes < nno; inoes++)
                {
                    res_c.AddValue(no_c[inoes], 0, eres_c[inoes]);
                }
            }
            return true;
        }
Beispiel #37
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
            )
        {
            IsPCWaveguide = true;
            // フォトニック結晶導波路(TEモード)
            // 反復で解く?
            //isSolveEigenItr = false; // 反復で解かない
            // 基本モードを計算する
            //CalcModeIndex = 0;
            // 高次モードを指定する
            //CalcModeIndex = 4;

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

            //NormalizedFreq1 = Math.Floor((2.0 * WaveguideWidth / (latticeA / 0.302)) * 10.0) * 0.1; //6.7;
            //NormalizedFreq2 = Math.Ceiling((2.0 * WaveguideWidth / (latticeA / 0.443)) * 10.0) * 0.1;// 9.7;
            //FreqDelta = 0.02;
            //GraphFreqInterval = 0.5;
            // フォトニック結晶導波路の場合、a/λを規格化周波数とする
            NormalizedFreq1 = 0.300;//0.302;
            NormalizedFreq2 = 0.440;//0.443;
            FreqDelta = 0.002;
            GraphFreqInterval = 0.02;

            // 速波モードを表示
            MinBeta = 0;
            MaxBeta = 1.0; //((int)Math.Ceiling(Math.Sqrt(rodEps) * 10.0)) * 0.1 + 1.0e-12;
            GraphBetaInterval = 0.2; //0.5;
            minEffN = 0;
            maxEffN = 1.0;// Math.Sqrt(rodEps);

            // 波のモード
            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 < 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);
                }

                // 図面表示
                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);
                }
                WgUtilForPeriodicEigen.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;
                WgUtilForPeriodicEigen.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);
                }
                WgUtilForPeriodicEigen.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);
                }
                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 - latticeA * (rodCntHalf + 1)) && coord[1] <= (WaveguideWidth - latticeA * (rodCntHalf)))
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Beispiel #38
0
        /// <summary>
        /// PC導波路 4ポート方向性結合器
        /// </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
            )
        {
            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小伝搬定数
            double minEffN = 0;
            // 最大伝搬定数
            double maxEffN = 0;

            // フォトニック導波路 方向性結合器
            //  問題4: ポート1から入射
            //  問題5: ポート2から入射
            const int ProbNo_Input2 = 5;

            // ロッドの数(半分)
            //const int rodCntHalf = 5;
            const int rodCntHalf = 3;
            // 中央のロッドの数
            int rodCntMiddle = 2;
            // 格子の数
            int latticeCnt = rodCntHalf * 2 + 1;
            // 格子定数
            latticeA = WaveguideWidth / (double)latticeCnt;
            // 周期構造距離
            periodicDistance = latticeA;
            // ロッドの半径
            double rodRadius = 0.18 * latticeA;
            // ロッドの比誘電率
            double rodEps = 3.4 * 3.4;
            // 格子1辺の分割数
            //const int ndivForOneLattice = 6;
            const int ndivForOneLattice = 6;
            // 境界の総分割数
            int ndiv = latticeCnt * ndivForOneLattice;
            // ロッドの円周の分割数
            //const int rodCircleDiv = 8;
            const int rodCircleDiv = 8;
            // ロッドの半径の分割数
            const int rodRadiusDiv = 1;
            // 上下ロッド領域の幅
            double rodAreaHalfWidth = rodCntHalf * latticeA;
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 50;
            const int rodCntDiscon = 26;
            System.Diagnostics.Debug.Assert(rodCntDiscon > (rodCntHalf + 1) * 2);
            double disconLength = latticeA * rodCntDiscon;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = latticeA;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / ndiv;

            minEffN = 0.0;
            maxEffN = 1.0;

            NormalizedFreq1 = 0.300;//0.302;
            NormalizedFreq2 = 0.440;//0.443;
            FreqDelta = 0.002;
            GraphFreqInterval = 0.02;

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

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            /*
            if (WaveModeDv == 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 portCnt = 4;
            // 図面作成、メッシュ生成
            // 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>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                double channel2BaseY = WaveguideWidth + (-rodCntHalf + rodCntMiddle) * latticeA;
                {
                    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 + rodAreaHalfWidth * 2 + disconLength, 0.0)); // 頂点4
                    pts.Add(new CVector2D(inputWgLength * 2 + rodAreaHalfWidth * 2 + disconLength, 0.0)); // 頂点5
                    pts.Add(new CVector2D(inputWgLength * 2 + rodAreaHalfWidth * 2 + disconLength, WaveguideWidth)); // 頂点6
                    pts.Add(new CVector2D(inputWgLength + rodAreaHalfWidth * 2 + disconLength, WaveguideWidth)); // 頂点7
                    pts.Add(new CVector2D(inputWgLength + rodAreaHalfWidth * 2 + disconLength, channel2BaseY + latticeA + rodAreaHalfWidth)); // 頂点8
                    pts.Add(new CVector2D(inputWgLength + rodAreaHalfWidth * 2 + disconLength, channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength)); // 頂点9
                    pts.Add(new CVector2D(inputWgLength + rodAreaHalfWidth * 2 + disconLength - WaveguideWidth, channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength)); // 頂点10
                    pts.Add(new CVector2D(inputWgLength + rodAreaHalfWidth * 2 + disconLength - WaveguideWidth, channel2BaseY + latticeA + rodAreaHalfWidth)); // 頂点11
                    pts.Add(new CVector2D(inputWgLength + WaveguideWidth, channel2BaseY + latticeA + rodAreaHalfWidth)); // 頂点12
                    pts.Add(new CVector2D(inputWgLength + WaveguideWidth, channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength)); // 頂点13
                    pts.Add(new CVector2D(inputWgLength, channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength)); // 頂点14
                    pts.Add(new CVector2D(inputWgLength, channel2BaseY + latticeA + rodAreaHalfWidth)); // 頂点15
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth)); // 頂点16
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 16).id_e_add;
                System.Diagnostics.Debug.Assert(eIdAdd1 != 0);
                uint eIdAdd2 = cad2d.ConnectVertex_Line(4, 7).id_e_add;
                System.Diagnostics.Debug.Assert(eIdAdd2 != 0);
                uint eIdAdd3 = cad2d.ConnectVertex_Line(8, 11).id_e_add;
                System.Diagnostics.Debug.Assert(eIdAdd3 != 0);
                uint eIdAdd4 = cad2d.ConnectVertex_Line(12, 15).id_e_add;
                System.Diagnostics.Debug.Assert(eIdAdd4 != 0);
                // 入出力導波路の周期構造境界上の頂点を追加
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // ポート1(左)
                {
                    uint id_e = 1;
                    double x1 = 0.0;
                    double y1 = WaveguideWidth;
                    double x2 = x1;
                    double y2 = 0.0;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                {
                    uint id_e = 17;
                    double x1 = inputWgLength;
                    double y1 = 0.0;
                    double x2 = x1;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                // ポート2(左上)
                {
                    uint id_e = 13;
                    double x1 = inputWgLength + WaveguideWidth;
                    double y1 = channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength;
                    double x2 = inputWgLength;
                    double y2 = y1;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                {
                    uint id_e = 20;
                    double x1 = inputWgLength + WaveguideWidth;
                    double y1 = channel2BaseY + latticeA + rodAreaHalfWidth;
                    double x2 = inputWgLength;
                    double y2 = y1;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                // ポート3(右)
                {
                    uint id_e = 5;
                    double x1 = inputWgLength * 2 + rodAreaHalfWidth * 2 + disconLength;
                    double y1 = 0.0;
                    double x2 = x1;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                {
                    uint id_e = 18;
                    double x1 = inputWgLength + rodAreaHalfWidth * 2 + disconLength;
                    double y1 = 0.0;
                    double x2 = x1;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                // ポート4(右上)
                {
                    uint id_e = 9;
                    double x1 = inputWgLength + rodAreaHalfWidth * 2 + disconLength;
                    double y1 = channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength;
                    double x2 = inputWgLength + rodAreaHalfWidth * 2 + disconLength - WaveguideWidth;
                    double y2 = y1;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }
                {
                    uint id_e = 19;
                    double x1 = inputWgLength + rodAreaHalfWidth * 2 + disconLength;
                    double y1 = channel2BaseY + latticeA + rodAreaHalfWidth;
                    double x2 = inputWgLength + rodAreaHalfWidth * 2 + disconLength - WaveguideWidth;
                    double y2 = y1;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x2, y2);
                }

                // ロッドを追加
                // 入出力導波路
                int rodCntInputWg = 1;
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (portIndex == 0)
                    {
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (portIndex == 1)
                    {
                        baseLoopId = 5;
                        inputWgNo = 2;
                    }
                    else if (portIndex == 2)
                    {
                        baseLoopId = 3;
                        inputWgNo = 3;
                    }
                    else if (portIndex == 3)
                    {
                        baseLoopId = 4;
                        inputWgNo = 4;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    for (int col = 0; col < rodCntInputWg; col++)
                    {

                        for (int row = 0; row < rodCntHalf; row++)
                        {
                            double x0 = 0.0;
                            double y0 = 0.0;
                            if (portIndex == 0)
                            {
                                x0 = latticeA * 0.5 + col * latticeA;
                                y0 = WaveguideWidth - row * latticeA - latticeA * 0.5;
                            }
                            else if (portIndex == 1)
                            {
                                x0 = inputWgLength + latticeA * 0.5 + row * latticeA;
                                y0 = channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength - latticeA * 0.5 - col * latticeA;
                            }
                            else if (portIndex == 2)
                            {
                                x0 = inputWgLength + rodAreaHalfWidth * 2 + disconLength + latticeA * 0.5 + col * latticeA;
                                y0 = WaveguideWidth - row * latticeA - latticeA * 0.5;
                            }
                            else if (portIndex == 3)
                            {
                                x0 = inputWgLength + rodAreaHalfWidth * 2 + disconLength - WaveguideWidth + latticeA * 0.5 + row * latticeA;
                                y0 = channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength - latticeA * 0.5 - col * latticeA;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                            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);
                            }
                            else if (inputWgNo == 3)
                            {
                                rodLoopIds_InputWg3.Add(lId);
                            }
                            else if (inputWgNo == 4)
                            {
                                rodLoopIds_InputWg4.Add(lId);
                            }
                        }
                        for (int row = 0; row < rodCntHalf; row++)
                        {
                            double x0 = 0.0;
                            double y0 = 0.0;
                            if (portIndex == 0)
                            {
                                x0 = latticeA * 0.5 + col * latticeA;
                                y0 = latticeA * rodCntHalf - row * latticeA - latticeA * 0.5;
                            }
                            else if (portIndex == 1)
                            {
                                x0 = inputWgLength + WaveguideWidth - latticeA * rodCntHalf + latticeA * 0.5 + row * latticeA;
                                y0 = channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength - latticeA * 0.5 - col * latticeA;
                            }
                            else if (portIndex == 2)
                            {
                                x0 = inputWgLength + rodAreaHalfWidth * 2 + disconLength + latticeA * 0.5 + col * latticeA;
                                y0 = latticeA * rodCntHalf - row * latticeA - latticeA * 0.5;
                            }
                            else if (portIndex == 3)
                            {
                                x0 = inputWgLength + rodAreaHalfWidth * 2 + disconLength - latticeA * rodCntHalf + latticeA * 0.5 + row * latticeA;
                                y0 = channel2BaseY + latticeA + rodAreaHalfWidth + inputWgLength - latticeA * 0.5 - col * latticeA;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            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);
                            }
                            else if (inputWgNo == 3)
                            {
                                rodLoopIds_InputWg3.Add(lId);
                            }
                            else if (inputWgNo == 4)
                            {
                                rodLoopIds_InputWg4.Add(lId);
                            }
                        }
                    }
                }
                // 不連続領域
                int rodCntAllX = rodCntHalf * 2 + rodCntDiscon;
                for (int col = 0; col < rodCntAllX; col++)
                {
                    uint baseLoopId = 2;

                    // 上のロッド
                    for (int row = 0; row < (rodCntHalf + 1); row++)
                    {
                        if ((col == rodCntHalf || col == (rodCntAllX - rodCntHalf - 1)) && row < rodCntHalf) continue;
                        if (row == rodCntHalf && (col >= (rodCntHalf + 1) && col <= (rodCntAllX - rodCntHalf - 2))) continue;
                        if (row == (rodCntHalf - 1) && (col == (rodCntHalf + 1) || col == (rodCntAllX - rodCntHalf - 2))) continue;
                        double x0 = inputWgLength + latticeA * 0.5 + col * latticeA;
                        double y0 = WaveguideWidth + (rodCntMiddle + 1) * latticeA - row * latticeA - latticeA * 0.5;
                        uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                        rodLoopIds.Add(lId);
                    }
                    // 中央結合部
                    for (int row = 0; row < rodCntMiddle; row++)
                    {
                        double x0 = inputWgLength + latticeA * 0.5 + col * latticeA;
                        double y0 = (WaveguideWidth + (rodCntMiddle + 1) * latticeA) * 0.5 + latticeA * rodCntMiddle * 0.5 - row * latticeA - latticeA * 0.5;
                        uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                        rodLoopIds.Add(lId);
                    }
                    // 下のロッド
                    for (int row = 0; row < rodCntHalf; row++)
                    {
                        double x0 = inputWgLength + latticeA * 0.5 + col * latticeA;
                        double y0 = latticeA * rodCntHalf - row * latticeA - latticeA * 0.5;
                        uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                        rodLoopIds.Add(lId);
                    }
                    /*
                    // 中央の2つのロッドとロッドの間のメッシュの対称性を改善する
                    // ODDモードが伝搬モードになる付近でEVEN→ODDに変換される現象が発生したので改良
                    // ロッドの分割を細かくして、さらに全体の分割数を上げると改善されるが、
                    // 中央の2つのロッドの間に頂点を1点追加するだけでも改善できる
                    if (rodCntMiddle % 2 == 0) // 中央のロッドが偶数本のとき
                    {
                        // 中央のロッドとロッドの間に頂点を追加
                        double x = inputWgLength + latticeA * 0.5 + col * latticeA;
                        double y = (WaveguideWidth + (rodCntMiddle + 1) * latticeA) * 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);
                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);
            }

            // 4ポート情報リスト作成
            //const uint portCnt = 4;
            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;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            if (probNo == ProbNo_Input2)
            {
                // 入射ポート:ポート2
                WgPortInfoList[1].IsIncidentPort = true;
            }
            else
            {
                // 入射ポート:ポート1
                WgPortInfoList[0].IsIncidentPort = true;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = { 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16 };
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }

            // 開口条件1
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 13;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else if (portIndex == 2)
                {
                    eId_cad_list[0] = 5;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else if (portIndex == 3)
                {
                    eId_cad_list[0] = 9;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 3 - (i - 1));
                    }
                    else if (portIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 5 - (i - 1));
                    }
                    else if (portIndex == 3)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 7 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    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] = 5;
                    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] = 3;
                    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] = 4;
                    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;

                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 17;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 20;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else if (portIndex == 2)
                {
                    eId_cad_list[0] = 18;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else if (portIndex == 3)
                {
                    eId_cad_list[0] = 19;
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 4 - (i - 1));
                    }
                    else if (portIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 6 - (i - 1));
                    }
                    else if (portIndex == 3)
                    {
                        eId_cad_list[i] = (uint)(20 + (ndiv - 1) * 8 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    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 ((portIndex == 0 &&
                                (coord[1] >= (WaveguideWidth - latticeA * (rodCntHalf + 1)) && coord[1] <= (WaveguideWidth - latticeA * (rodCntHalf))))
                            || (portIndex == 1 &&
                                   (coord[0] >= ((inputWgLength + WaveguideWidth) - latticeA * (rodCntHalf + 1)) && coord[0] <= ((inputWgLength + WaveguideWidth) - latticeA * (rodCntHalf))))
                            || (portIndex == 2 &&
                                   (coord[1] >= (WaveguideWidth - latticeA * (rodCntHalf + 1)) && coord[1] <= (WaveguideWidth - latticeA * (rodCntHalf))))
                            || (portIndex == 3 &&
                                   (coord[0] >= ((inputWgLength + rodAreaHalfWidth * 2 + disconLength) - latticeA * (rodCntHalf + 1)) && coord[0] <= ((inputWgLength + rodAreaHalfWidth * 2 + disconLength) - latticeA * (rodCntHalf))))
                            )
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Beispiel #39
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;
        }
Beispiel #40
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="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
            )
        {
            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0;
            // 最大屈折率
            double maxEffN = 0;

            // 直線導波管
            // 導波路不連続領域の長さ
            double disconLength = 4.0 * WaveguideWidth / 2.0;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = 0.1 * WaveguideWidth / 2.0;
            // 周期構造距離
            periodicDistance = inputWgLength;
            // 格子定数(互換性の為設定)
            latticeA = 2.0 * WaveguideWidth;
            // 境界分割数
            const int ndiv = 20 * 3;
            double meshL = 1.1 * WaveguideWidth / ndiv;
            minEffN = 0.0;
            maxEffN = 1.0;

            NormalizedFreq1 = 1.0;
            NormalizedFreq2 = 2.0;
            FreqDelta = 0.01;
            GraphFreqInterval = 0.2;

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.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 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;
                // 入出力導波路の周期構造境界上の頂点を追加
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // 入力導波路
                {
                    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 = 9;
                    double x1 = inputWgLength;
                    double y1 = 0.0;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x1, y2);
                }
                // 出力導波路
                {
                    uint id_e = 5;
                    double x1 = inputWgLength * 2 + disconLength;
                    double y1 = 0.0;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x1, y2);
                }
                {
                    uint id_e = 10;
                    double x1 = inputWgLength + disconLength;
                    double y1 = 0.0;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x1, y2);
                }
                // 図面表示
                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);
                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 = { 1, 2, 3 };
                int[] mediaIndex_list = { Medias.IndexOf(mediaVacumn), Medias.IndexOf(mediaVacumn), Medias.IndexOf(mediaVacumn) };
                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;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = { 2, 3, 4, 6, 7, 8 };
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }

            // 開口条件1
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[0];
                wgPortInfo1.FieldPortBcId = 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(mediaVacumn);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(10 + (ndiv - 1) - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaVacumn);
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtil.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);
                }
            }

            // 開口条件2
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo2 = WgPortInfoList[1];
                wgPortInfo2.FieldPortBcId = 0;

                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 5;
                mediaIndex_list[0] = Medias.IndexOf(mediaVacumn);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(10 + (ndiv - 1) * 3 - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaVacumn);
                }
                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);
                wgPortInfo2.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo2.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[0];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = { 1 };
                int[] mediaIndex_list = { Medias.IndexOf(mediaVacumn) };

                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を取得
            //   辺単位で媒質を指定する
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[0];
                wgPortInfo1.FieldInputWgBcId = 0;

                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];

                eId_cad_list[0] = 9;
                mediaIndex_list[0] = Medias.IndexOf(mediaVacumn);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(10 + (ndiv - 1) * 2 - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaVacumn);
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路2
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo2 = WgPortInfoList[1];
                wgPortInfo2.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = { 3 };
                int[] mediaIndex_list = { Medias.IndexOf(mediaVacumn) };

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

                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];

                eId_cad_list[0] = 10;
                mediaIndex_list[0] = Medias.IndexOf(mediaVacumn);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(10 + (ndiv - 1) * 4 - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaVacumn);
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo2.InputWgEdgeDic);
                wgPortInfo2.FieldInputWgBcId = fieldPortBcId;
            }
            return true;
        }
Beispiel #41
0
        /////////////////////////////////////////////////
        // 定数
        /////////////////////////////////////////////////
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainLogic()
        {
            Disposed = false;
            Camera = new CCamera();
            DrawerAry = new CDrawerArrayField();
            World = new CFieldWorld();
            FieldValueSetterAry = new List<CFieldValueSetter>();

            // Glutのアイドル時処理でなく、タイマーで再描画イベントを発生させる
            MyTimer.Tick += (sender, e) =>
            {
                Glut.glutPostRedisplay();
            };
            MyTimer.Interval = 1000 / 60;
        }
Beispiel #42
0
        /// <summary>
        /// 問題を解く
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="betaIndex"></param>
        /// <param name="Beta1"></param>
        /// <param name="Beta2"></param>
        /// <param name="BetaDelta"></param>
        /// <param name="initFlg"></param>
        /// <param name="WaveguideWidth"></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="isSVEA"></param>
        /// <param name="PrevModalVec"></param>
        /// <param name="IsShowAbsField"></param>
        /// <param name="MinNormalizedFreq"></param>
        /// <param name="MaxNormalizedFreq"></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="EigenValueList"></param>
        /// <param name="DrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        private static bool solveProblem(
            int probNo,
            ref int betaIndex,
            double Beta1,
            double Beta2,
            double BetaDelta,
            bool initFlg,
            double WaveguideWidth,
            WgUtil.WaveModeDV WaveModeDv,
            bool IsPCWaveguide,
            double latticeA,
            double periodicDistance,
            IList<IList<uint>> PCWaveguidePorts,
            int CalcModeIndex,
            bool isSVEA,
            ref KrdLab.clapack.Complex[] PrevModalVec,
            bool IsShowAbsField,
            double MinNormalizedFreq,
            double MaxNormalizedFreq,
            ref CFieldWorld World,
            uint FieldValId,
            uint FieldLoopId,
            uint FieldForceBcId,
            uint FieldPortBcId1,
            uint FieldPortBcId2,
            IList<MediaInfo> Medias,
            Dictionary<uint, wg2d.World.Loop> LoopDic,
            Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref IList<Complex> EigenValueList,
            ref CDrawerArrayField DrawerAry,
            CCamera Camera)
        {
            //long memorySize1 = GC.GetTotalMemory(false);
            //Console.WriteLine("    total memory: {0}", memorySize1);

            bool success = false;
            bool showException = true;
            try
            {
                // 緩慢変化包絡線近似 SVEA(slowly varying envelope approximation)で表現?
                //  true: v = v(x, y)exp(-jβx)と置いた場合
                //  false: 直接Bloch境界条件を指定する場合
                //bool isSVEA = false; // falseの時の方が妥当な解が得られる
                //bool isSVEA = false;
                // モード追跡する?
                bool isModeTrace = true;
                if (!IsPCWaveguide)
                {
                    isModeTrace = false;
                }
                System.Diagnostics.Debug.WriteLine("isSVEA: {0}", isSVEA);
                System.Diagnostics.Debug.WriteLine("isModeTrace: {0}, CalcModeIndex: {1}", isModeTrace, CalcModeIndex);

                if (betaIndex == 0)
                {
                    PrevModalVec = null;
                }

                // 規格化伝搬定数
                double beta = getBeta(
                    ref betaIndex,
                    Beta1,
                    Beta2,
                    BetaDelta);
                if (betaIndex == -1)
                {
                    return success;
                }
                System.Diagnostics.Debug.WriteLine("beta: {0}    beta*d/(2.0 * pi): {1}",
                    beta,
                    beta * periodicDistance / (2.0 * pi));

                if (probNo == 3)
                {
                    /*
                    // probNo == 3 theta = 45 defectRodCnt = 3 even 1st
                    if (beta < 0.32 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                     */

                    /*
                    // probNo == 3 theta = 60 defectRodCnt = 1 r = 0.30 even
                    if (beta < 0.20 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                     */

                    /*
                    // probNo == 3 theta = 30 defectRodCnt = 1 r = 0.30 n = 3.4 even
                    if (beta < 0.08 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.92 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */

                    /*
                    // probNo == 3 theta = 60 defectRodCnt = 1 r = 0.35 even
                    if (beta < 0.08 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.92 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */
                    /*
                    // probNo == 3 theta = 30 defectRodCnt = 3 r = 0.28 even 1st
                    if (beta < 0.16 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                     */
                    /*
                    // probNo == 3 theta = 30 defectRodCnt = 3 r = 0.28 even 2nd
                    if (beta > 0.39 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */
                    /*
                    // probNo == 3 theta = 30 defectRodCnt = 3 r = 0.28 odd 2nd
                    if (beta > 0.20 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */

                    if (beta < 0.10 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }

                }
                else if (probNo == 5)
                {
                    /*
                    // for latticeTheta = 60 r = 0.30a  n = 3.4 air hole even 1st above decoupling point
                    // for latticeTheta = 60 r = 0.30a  n = 3.4 air hole odd 1st above decoupling point
                    if (beta < 0.13 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.2501 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */
                    /*
                    // for latticeTheta = 60 r = 0.30a air hole  n = 3.4 even 1st below decoupling point
                    // for latticeTheta = 60 r = 0.30a air hole  n = 3.4 odd 1st below decoupling point
                    if (beta < 0.2501 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.4801 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */

                    /*
                    // for latticeTheta = 60 r = 0.30a  n = 2.76 air hole even 1st above & below decoupling point
                    if (beta < 0.1601 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.4801 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */
                    /*
                    // for latticeTheta = 60 r = 0.30a  n = 2.76 air hole odd 1st above decoupling point
                    if (beta < 0.1601 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.2601 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }
                     */

                    // for latticeTheta = 60 r = 0.30a air hole  n = 2.76 even 1st below decoupling point
                    // for latticeTheta = 60 r = 0.30a air hole  n = 2.76 odd 1st below decoupling point
                    if (beta < 0.2601 * (2.0 * pi / periodicDistance))
                    {
                        showException = false;
                        throw new Exception();
                    }
                    if (beta > 0.4801 * (2.0 * pi / periodicDistance))
                    {
                        betaIndex = -1;
                        return success;
                    }

                }

                // 全節点数を取得する
                uint node_cnt = 0;
                node_cnt = WgUtilForPeriodicEigenBetaSpecified.GetNodeCnt(World, FieldLoopId);

                System.Diagnostics.Debug.WriteLine("node_cnt: {0}", node_cnt);

                // 境界の節点リストを取得する
                uint[] no_c_all_fieldForceBcId = null;
                Dictionary<uint, uint> to_no_boundary_fieldForceBcId = null;
                if (FieldForceBcId != 0)
                {
                    WgUtil.GetBoundaryNodeList(World, FieldForceBcId, out no_c_all_fieldForceBcId, out to_no_boundary_fieldForceBcId);
                }
                uint[] no_c_all_fieldPortBcId1 = null;
                Dictionary<uint, uint> to_no_boundary_fieldPortBcId1 = null;
                WgUtil.GetBoundaryNodeList(World, FieldPortBcId1, out no_c_all_fieldPortBcId1, out to_no_boundary_fieldPortBcId1);
                uint[] no_c_all_fieldPortBcId2 = null;
                Dictionary<uint, uint> to_no_boundary_fieldPortBcId2 = null;
                WgUtil.GetBoundaryNodeList(World, FieldPortBcId2, out no_c_all_fieldPortBcId2, out to_no_boundary_fieldPortBcId2);

                // 節点のソート
                IList<uint> sortedNodes = new List<uint>();
                Dictionary<uint, int> toSorted = new Dictionary<uint, int>();
                //   境界1と境界2は周期構造条件より同じ界の値をとる
                // ポート境界1
                for (int i = 0; i < no_c_all_fieldPortBcId1.Length; i++)
                {
                    // 境界1の節点を追加
                    uint nodeNumberPortBc1 = no_c_all_fieldPortBcId1[i];
                    if (FieldForceBcId != 0)
                    {
                        // 強制境界を除く
                        if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumberPortBc1)) continue;
                    }
                    sortedNodes.Add(nodeNumberPortBc1);
                    int nodeIndex = sortedNodes.Count - 1;
                    toSorted.Add(nodeNumberPortBc1, nodeIndex);
                }
                uint boundary_node_cnt = (uint)sortedNodes.Count; // 境界1
                // 内部領域
                for (uint nodeNumber = 0; nodeNumber < node_cnt; nodeNumber++)
                {
                    // 追加済み節点はスキップ
                    //if (toSorted.ContainsKey(nodeNumber)) continue;
                    // 境界1は除く
                    if (to_no_boundary_fieldPortBcId1.ContainsKey(nodeNumber)) continue;
                    // 境界2は除く
                    if (to_no_boundary_fieldPortBcId2.ContainsKey(nodeNumber)) continue;
                    if (FieldForceBcId != 0)
                    {
                        // 強制境界を除く
                        if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumber)) continue;
                    }
                    sortedNodes.Add(nodeNumber);
                    toSorted.Add(nodeNumber, sortedNodes.Count - 1);
                }
                uint free_node_cnt = (uint)sortedNodes.Count;  // 境界1 + 内部領域
                for (int i = 0; i < no_c_all_fieldPortBcId2.Length; i++)
                {
                    // 境界2の節点を追加
                    uint nodeNumberPortBc2 = no_c_all_fieldPortBcId2[i];
                    if (FieldForceBcId != 0)
                    {
                        // 強制境界を除く
                        if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumberPortBc2)) continue;
                    }
                    sortedNodes.Add(nodeNumberPortBc2);
                    int nodeIndex = sortedNodes.Count - 1;
                    toSorted.Add(nodeNumberPortBc2, nodeIndex);
                }
                uint free_node_cnt0 = (uint)sortedNodes.Count;  // 境界1 + 内部領域 + 境界2

                // 剛性行列、質量行列を作成
                KrdLab.clapack.Complex[] KMat0 = null;
                KrdLab.clapack.Complex[] MMat0 = null;
                {
                    KrdLab.clapack.Complex betaForMakingMat = 0.0;
                    if (isSVEA)
                    {
                        betaForMakingMat = new KrdLab.clapack.Complex(beta, 0.0); // v = v(x, y)exp(-jβx)と置いた場合
                    }
                    else
                    {
                        betaForMakingMat = 0.0; // 直接Bloch境界条件を指定する場合
                    }
                    WgUtilForPeriodicEigenBetaSpecified.MkPeriodicHelmholtzMat(
                        betaForMakingMat,
                        false, // isYDirectionPeriodic: false
                        World,
                        FieldLoopId,
                        Medias,
                        LoopDic,
                        node_cnt,
                        free_node_cnt0,
                        toSorted,
                        out KMat0,
                        out MMat0);
                }

                // 境界2の節点は境界1の節点と同一とみなす
                //   境界上の分割が同じであることが前提条件
                KrdLab.clapack.Complex[] KMat = new KrdLab.clapack.Complex[free_node_cnt * free_node_cnt];
                KrdLab.clapack.Complex[] MMat = new KrdLab.clapack.Complex[free_node_cnt * free_node_cnt];
                /*
                // v = v(x, y)exp(-jβx)と置いた場合
                for (int i = 0; i < free_node_cnt; i++)
                {
                    for (int j = 0; j < free_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] = KMat0[i + free_node_cnt0 * j];
                        MMat[i + free_node_cnt * j] = MMat0[i + free_node_cnt0 * j];
                    }
                }
                for (int i = 0; i < free_node_cnt; i++)
                {
                    for (int j = 0; j < boundary_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] += KMat0[i + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                        MMat[i + free_node_cnt * j] += MMat0[i + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                    }
                }
                for (int i = 0; i < boundary_node_cnt; i++)
                {
                    for (int j = 0; j < free_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] += KMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * j];
                        MMat[i + free_node_cnt * j] += MMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * j];
                    }
                    for (int j = 0; j < boundary_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] += KMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                        MMat[i + free_node_cnt * j] += MMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                    }
                }
                 */
                // 直接Bloch境界条件を指定する場合
                KrdLab.clapack.Complex expA = 1.0;
                if (isSVEA)
                {
                    expA = 1.0;
                }
                else
                {
                    expA = KrdLab.clapack.Complex.Exp(-1.0 * KrdLab.clapack.Complex.ImaginaryOne * beta * periodicDistance);
                }
                for (int i = 0; i < free_node_cnt; i++)
                {
                    for (int j = 0; j < free_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] = KMat0[i + free_node_cnt0 * j];
                        MMat[i + free_node_cnt * j] = MMat0[i + free_node_cnt0 * j];
                    }
                }
                for (int i = 0; i < free_node_cnt; i++)
                {
                    for (int j = 0; j < boundary_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] += expA * KMat0[i + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                        MMat[i + free_node_cnt * j] += expA * MMat0[i + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                    }
                }
                for (int i = 0; i < boundary_node_cnt; i++)
                {
                    for (int j = 0; j < free_node_cnt; j++)
                    {
                        KMat[i + free_node_cnt * j] += (1.0 / expA) * KMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * j];
                        MMat[i + free_node_cnt * j] += (1.0 / expA) * MMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * j];
                    }
                    for (int j = 0; j < boundary_node_cnt; j++)
                    {
                        //KMat[i + free_node_cnt * j] += (1.0 / expA) * expA * KMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                        //MMat[i + free_node_cnt * j] += (1.0 / expA) * expA * MMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                        //より下記と等価
                        KMat[i + free_node_cnt * j] += KMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                        MMat[i + free_node_cnt * j] += MMat0[(free_node_cnt + boundary_node_cnt - 1 - i) + free_node_cnt0 * (free_node_cnt + boundary_node_cnt - 1 - j)];
                    }
                }

                // 規格化周波数
                KrdLab.clapack.Complex complexNormalizedFreq_ans = 0.0;
                // 界ベクトルは全節点分作成
                KrdLab.clapack.Complex[] resVec = null;
                resVec = new KrdLab.clapack.Complex[node_cnt]; //全節点

                {
                    int matLen = (int)free_node_cnt;
                    KrdLab.clapack.Complex[] evals = null;
                    KrdLab.clapack.Complex[,] evecs = null;
                    KrdLab.clapack.Complex[] A = new KrdLab.clapack.Complex[KMat.Length];
                    KrdLab.clapack.Complex[] B = new KrdLab.clapack.Complex[MMat.Length];
                    for (int i = 0; i < matLen * matLen; i++)
                    {
                        A[i] = KMat[i];
                        B[i] = MMat[i];
                    }
                    /*
                    // 一般化複素固有値解析
                    //   [A],[B]は内部で書き換えられるので注意
                    KrdLab.clapack.Complex[] ret_evals = null;
                    KrdLab.clapack.Complex[][] ret_evecs = null;
                    System.Diagnostics.Debug.WriteLine("KrdLab.clapack.FunctionExt.zggev");
                    KrdLab.clapack.FunctionExt.zggev(A, matLen, matLen, B, matLen, matLen, ref ret_evals, ref ret_evecs);

                    evals = ret_evals;
                    System.Diagnostics.Debug.Assert(ret_evals.Length == ret_evecs.Length);
                    // 2次元配列に格納する
                    evecs = new KrdLab.clapack.Complex[ret_evecs.Length, matLen];
                    for (int i = 0; i < ret_evecs.Length; i++)
                    {
                        KrdLab.clapack.Complex[] ret_evec = ret_evecs[i];
                        for (int j = 0; j < ret_evec.Length; j++)
                        {
                            evecs[i, j] = ret_evec[j];
                        }
                    }
                     */
                    // エルミートバンド行列の固有値解析
                    {
                        KrdLab.clapack.Complex[] ret_evals = null;
                        KrdLab.clapack.Complex[,] ret_evecs = null;
                        solveHermitianBandMatGeneralizedEigen(matLen, A, B, ref ret_evals, ref ret_evecs);
                        evals = ret_evals;
                        evecs = ret_evecs;
                    }

                    // 固有値のソート
                    WgUtilForPeriodicEigenBetaSpecified.Sort1DEigenMode(evals, evecs);
                    /*
                    // check
                    for (int imode = 0; imode < evals.Length; imode++)
                    {
                        // 固有周波数
                        KrdLab.clapack.Complex complex_k0_eigen = KrdLab.clapack.Complex.Sqrt(evals[imode]);
                        // 規格化周波数
                        KrdLab.clapack.Complex complexNormalizedFreq = latticeA * (complex_k0_eigen / (2.0 * pi));
                        System.Diagnostics.Debug.WriteLine("a/λ  ( " + imode + " ) = " + complexNormalizedFreq.Real + " + " + complexNormalizedFreq.Imaginary + " i ");
                    }
                     */
                    // 欠陥モードを取得
                    IList<int> defectModeIndexList = new List<int>();
                    // フォトニック結晶導波路解析用
                    if (IsPCWaveguide)
                    {
                        int hitModeIndex = -1;
                        double hitNorm = 0.0;
                        for (int imode = 0; imode < evals.Length; imode++)
                        {
                            // 固有周波数
                            KrdLab.clapack.Complex complex_k0_eigen = KrdLab.clapack.Complex.Sqrt(evals[imode]);
                            // 規格化周波数
                            KrdLab.clapack.Complex complexNormalizedFreq = latticeA * (complex_k0_eigen / (2.0 * pi));
                            // 界ベクトル
                            KrdLab.clapack.Complex[] fieldVec = MyUtilLib.Matrix.MyMatrixUtil.matrix_GetRowVec(evecs, imode);

                            // フォトニック結晶導波路の導波モードを判定する
                            System.Diagnostics.Debug.Assert(free_node_cnt == fieldVec.Length);
                            bool isHitDefectMode = isDefectModeBetaSpecified(
                                free_node_cnt,
                                sortedNodes,
                                toSorted,
                                PCWaveguidePorts,
                                MinNormalizedFreq,
                                MaxNormalizedFreq,
                                complexNormalizedFreq,
                                fieldVec);

                            if (isHitDefectMode
                                && isModeTrace && PrevModalVec != null)
                            {
                                // 同じ固有モード?
                                double ret_norm = 0.0;
                                bool isHitSameMode = isSameModeBetaSpecified(
                                    node_cnt,
                                    PrevModalVec,
                                    free_node_cnt,
                                    sortedNodes,
                                    toSorted,
                                    PCWaveguidePorts,
                                    MinNormalizedFreq,
                                    MaxNormalizedFreq,
                                    complexNormalizedFreq,
                                    fieldVec,
                                    out ret_norm);
                                if (isHitSameMode)
                                {
                                    // より分布の近いモードを採用する
                                    if (Math.Abs(ret_norm - 1.0) < Math.Abs(hitNorm - 1.0))
                                    {
                                        hitModeIndex = imode;
                                        hitNorm = ret_norm;
                                        System.Diagnostics.Debug.WriteLine("PC defectMode(ModeTrace): a/λ  ( " + imode + " ) = " + complexNormalizedFreq.Real + " + " + complexNormalizedFreq.Imaginary + " i ");
                                    }
                                }
                            }
                            if (isHitDefectMode)
                            {
                                System.Diagnostics.Debug.WriteLine("PC defectMode: a/λ  ( " + imode + " ) = " + complexNormalizedFreq.Real + " + " + complexNormalizedFreq.Imaginary + " i ");
                                if (!isModeTrace || PrevModalVec == null) // モード追跡でないとき、またはモード追跡用の参照固有モードベクトルがないとき
                                {
                                    defectModeIndexList.Add(imode);
                                }
                            }
                        }
                        if (isModeTrace && hitModeIndex != -1)
                        {
                            System.Diagnostics.Debug.Assert(defectModeIndexList.Count == 0);
                            System.Diagnostics.Debug.WriteLine("hitModeIndex: {0}", hitModeIndex);
                            defectModeIndexList.Add(hitModeIndex);
                        }
                    }
                    // 基本モードを取得する(k0^2最小値)
                    int tagtModeIndex = 0;
                    // フォトニック結晶導波路解析用
                    if (IsPCWaveguide)
                    {
                        tagtModeIndex = -1;
                        if (isModeTrace && PrevModalVec != null)
                        {
                            if (defectModeIndexList.Count > 0)
                            {
                                tagtModeIndex = defectModeIndexList[0];
                            }
                        }
                        else
                        {
                            if (defectModeIndexList.Count > 0)
                            {
                                if ((defectModeIndexList.Count - 1) >= CalcModeIndex)
                                {
                                    tagtModeIndex = defectModeIndexList[CalcModeIndex];
                                }
                                else
                                {
                                    tagtModeIndex = -1;
                                }
                            }
                            else
                            {
                                tagtModeIndex = -1;
                                System.Diagnostics.Debug.WriteLine("!!!!!!!!! Not converged photonic crystal waveguide mode");
                            }
                        }
                    }
                    if (tagtModeIndex == -1)
                    {
                        System.Diagnostics.Debug.WriteLine("!!!!!!!!! Not found mode");
                        complexNormalizedFreq_ans = 0;
                        for (int i = 0; i < resVec.Length; i++)
                        {
                            resVec[i] = 0;
                        }
                    }
                    else
                    {
                        // 伝搬定数、固有ベクトルの格納
                        KrdLab.clapack.Complex complex_k0_eigen_ans = KrdLab.clapack.Complex.Sqrt(evals[tagtModeIndex]);
                        complexNormalizedFreq_ans = latticeA * (complex_k0_eigen_ans / (2.0 * pi));
                        KrdLab.clapack.Complex[] evec = MyUtilLib.Matrix.MyMatrixUtil.matrix_GetRowVec(evecs, tagtModeIndex);
                        System.Diagnostics.Debug.WriteLine("a/λ  ( " + tagtModeIndex + " ) = " + complexNormalizedFreq_ans.Real + " + " + complexNormalizedFreq_ans.Imaginary + " i ");
                        for (int ino = 0; ino < evec.Length; ino++)
                        {
                            //System.Diagnostics.Debug.WriteLine("    ( " + imode + ", " + ino + " ) = " + evec[ino].Real + " + " + evec[ino].Imaginary + " i ");
                            uint nodeNumber = sortedNodes[ino];
                            resVec[nodeNumber] = evec[ino];
                        }
                    }
                }

                // ポート境界1の節点の値を境界2にも格納する
                for (int i = 0; i < no_c_all_fieldPortBcId1.Length; i++)
                {
                    // 境界1の節点
                    uint nodeNumberPortBc1 = no_c_all_fieldPortBcId1[i];
                    // 境界1の節点の界の値を取得
                    KrdLab.clapack.Complex cvalue = resVec[nodeNumberPortBc1];

                    // 境界2の節点
                    uint nodeNumberPortBc2 = no_c_all_fieldPortBcId2[no_c_all_fieldPortBcId2.Length - 1 - i];
                    //resVec[nodeNumberPortBc2] = cvalue; // v = v(x, y)exp(-jβx)と置いた場合
                    resVec[nodeNumberPortBc2] = expA * cvalue; // 直接Bloch境界条件を指定する場合
                }

                // 位相調整
                KrdLab.clapack.Complex phaseShift = 1.0;
                double maxAbs = double.MinValue;
                KrdLab.clapack.Complex fValueAtMaxAbs = 0.0;
                {
                    /*
                    for (int ino = 0; ino < no_c_all_fieldPortBcId1.Length; ino++)
                    {
                        uint nodeNumberPortBc1 = no_c_all_fieldPortBcId1[ino];
                        KrdLab.clapack.Complex cvalue = resVec[ino];
                        double abs = KrdLab.clapack.Complex.Abs(cvalue);
                        if (abs > maxAbs)
                        {
                            maxAbs = abs;
                            fValueAtMaxAbs = cvalue;
                        }
                    }
                     */
                    for (int ino = 0; ino < resVec.Length; ino++)
                    {
                        KrdLab.clapack.Complex cvalue = resVec[ino];
                        double abs = KrdLab.clapack.Complex.Abs(cvalue);
                        if (abs > maxAbs)
                        {
                            maxAbs = abs;
                            fValueAtMaxAbs = cvalue;
                        }
                    }
                }
                if (maxAbs >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    phaseShift = fValueAtMaxAbs / maxAbs;
                }
                System.Diagnostics.Debug.WriteLine("phaseShift: {0} (°)", Math.Atan2(phaseShift.Imaginary, phaseShift.Real) * 180.0 / pi);
                for (int i = 0; i < resVec.Length; i++)
                {
                    resVec[i] /= phaseShift;
                }

                // 前回の固有ベクトルを更新
                if (isModeTrace && complexNormalizedFreq_ans.Real != 0.0 && Math.Abs(complexNormalizedFreq_ans.Imaginary) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    //PrevModalVec = resVec;
                    PrevModalVec = new KrdLab.clapack.Complex[node_cnt];
                    resVec.CopyTo(PrevModalVec, 0);
                }
                else
                {
                    // クリアしない(特定周波数で固有値が求まらないときがある。その場合でも同じモードを追跡できるように)
                    //PrevModalVec = null;
                }

                //------------------------------------------------------------------
                // 計算結果の後処理
                //------------------------------------------------------------------
                // 固有ベクトルの計算結果をワールド座標系にセットする
                WgUtilForPeriodicEigenBetaSpecified.SetFieldValueForDisplay(World, FieldValId, resVec);

                // 表示用にデータを格納する
                if (betaIndex == 0)
                {
                    EigenValueList.Clear();
                }

                // 表示用加工
                Complex evalueToShow = new Complex(complexNormalizedFreq_ans.Real, complexNormalizedFreq_ans.Imaginary);
                EigenValueList.Add(evalueToShow);

                // 描画する界の値を加工して置き換える
                //    そのまま描画オブジェクトにフィールドを渡すと、複素数で格納されているフィールド値の実数部が表示されます。
                //    絶対値を表示したかったので、下記処理を追加しています。
                if (IsShowAbsField)
                {
                    WgUtil.ReplaceFieldValueForDisplay(World, FieldValId); // 絶対値表示
                }
                // DEBUG
                //WgUtil.ReplaceFieldValueForDisplay(World, FieldValId); // 絶対値表示
                //WgUtil.ReplaceFieldValueForDisplay(World, FieldValId, 1); // 虚数部表示

                //------------------------------------------------------------------
                // 描画する界の追加
                //------------------------------------------------------------------
                DrawerAry.Clear();
                DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                if (initFlg)
                {
                    // カメラの変換行列初期化
                    DrawerAry.InitTrans(Camera);

                    // 表示位置調整
                    setupPanAndScale(probNo, Camera);
                }
                success = true;
            }
            catch (Exception exception)
            {
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                if (showException)
                {
                    Console.WriteLine(exception.Message + " " + exception.StackTrace);
                }
                // 表示用にデータを格納する
                if (betaIndex == 0)
                {
                    EigenValueList.Clear();
                }
                EigenValueList.Add(new Complex(0.0, 0.0));

                DrawerAry.Clear();
                DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                if (initFlg)
                {
                    // カメラの変換行列初期化
                    DrawerAry.InitTrans(Camera);

                    // 表示位置調整
                    setupPanAndScale(probNo, Camera);
                }
            }
            return success;
        }
Beispiel #43
0
 /// <summary>
 /// 使用中のリソースをすべてクリーンアップします。
 /// </summary>
 /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
 protected virtual void Dispose(bool disposing)
 {
     if (Disposed)
     {
         return;
     }
     Disposed = true;
     if (DrawerAry != null)
     {
         DrawerAry.Clear();
         DrawerAry.Dispose();
         DrawerAry = null;
     }
     if (Camera != null)
     {
         Camera.Dispose();
         Camera = null;
     }
     if (World != null)
     {
         World.Clear();
         World.Dispose();
         World = null;
     }
     if (FieldValueSetterAry != null)
     {
         clearFieldValueSetterAry(FieldValueSetterAry);
         FieldValueSetterAry = null;
     }
 }
Beispiel #44
0
 /// <summary>
 /// 使用中のリソースをすべてクリーンアップします。
 /// </summary>
 /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
 protected virtual void Dispose(bool disposing)
 {
     if (Disposed)
     {
         return;
     }
     Disposed = true;
     MyTimer.Enabled = false;
     if (DrawerAry != null)
     {
         DrawerAry.Clear();
         DrawerAry.Dispose();
         DrawerAry = null;
     }
     if (Camera != null)
     {
         Camera.Dispose();
         Camera = null;
     }
     if (World != null)
     {
         World.Clear();
         World.Dispose();
         World = null;
     }
     //if (FieldValueSetter != null)
     //{
     //    FieldValueSetter.Clear();
     //    FieldValueSetter.Dispose();
     //    FieldValueSetter = null;
     //}
     //if (Ls != null)
     //{
     //    Ls.Clear();
     //    Ls.Dispose();
     //    Ls = null;
     //}
     //if (Prec != null)
     //{
     //    Prec.Clear();
     //    Prec.Dispose();
     //    Prec = null;
     //}
     if (CadDrawerAry != null)
     {
         CadDrawerAry.Clear();
         CadDrawerAry.Dispose();
         CadDrawerAry = null;
     }
 }
Beispiel #45
0
        /// <summary>
        /// セルのメッシュ座標一覧取得
        /// </summary>
        /// <param name="World"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcIds"></param>
        /// <param name="ptsInCell"></param>
        /// <param name="nodeBInCell"></param>
        /// <param name="elemLoopIdInCell"></param>
        /// <param name="elemNodeInCell"></param>
        private static void getCoordListFromMeshCell_Tri_FirstOrder(
            CFieldWorld World,
            uint FieldLoopId,
            uint FieldForceBcId,
            IList <uint> FieldPortBcIds,
            out double[,] ptsInCell,
            out uint[,] nodeBInCell,
            out uint[] elemLoopIdInCell,
            out uint[,] elemNodeInCell
            )
        {
            // 全節点数を取得する
            uint node_cnt = 0;

            //node_cnt = WgUtilForPeriodicEigenBetaSpecified.GetNodeCnt(World, FieldLoopId);
            double[][] coord_c_all = null;
            uint[][]   elem_no_c   = null;
            uint[]     elem_loopId = null;
            {
                uint[] no_c_all_tmp = null;
                Dictionary <uint, uint> to_no_all_tmp = null;
                double[][] coord_c_all_tmp            = null;
                WgUtil.GetLoopCoordList(World, FieldLoopId, out no_c_all_tmp, out to_no_all_tmp, out coord_c_all_tmp, out elem_no_c, out elem_loopId);
                node_cnt = (uint)no_c_all_tmp.Length;

                // 座標リストを節点番号順に並び替えて格納
                coord_c_all = new double[node_cnt][];
                for (int ino = 0; ino < node_cnt; ino++)
                {
                    uint     nodeNumber = no_c_all_tmp[ino];
                    double[] coord      = coord_c_all_tmp[ino];
                    coord_c_all[nodeNumber] = coord;
                }
            }

            System.Diagnostics.Debug.WriteLine("node_cnt: {0}", node_cnt);

            // 境界の節点リストを取得する
            uint[] no_c_all_fieldForceBcId = null;
            Dictionary <uint, uint> to_no_boundary_fieldForceBcId = null;

            if (FieldForceBcId != 0)
            {
                WgUtil.GetBoundaryNodeList(World, FieldForceBcId, out no_c_all_fieldForceBcId, out to_no_boundary_fieldForceBcId);
            }
            int            boundaryCnt = FieldPortBcIds.Count;
            IList <uint[]> no_c_all_fieldPortBcId_list = new List <uint[]>();
            IList <Dictionary <uint, uint> > to_no_boundary_fieldPortBcId_list = new List <Dictionary <uint, uint> >();

            for (int i = 0; i < boundaryCnt; i++)
            {
                uint[] work_no_c_all_fieldPortBcId = null;
                Dictionary <uint, uint> work_to_no_boundary_fieldPortBcId = null;
                uint work_fieldPortBcId = FieldPortBcIds[i];
                WgUtil.GetBoundaryNodeList(World, work_fieldPortBcId, out work_no_c_all_fieldPortBcId, out work_to_no_boundary_fieldPortBcId);
                no_c_all_fieldPortBcId_list.Add(work_no_c_all_fieldPortBcId);
                to_no_boundary_fieldPortBcId_list.Add(work_to_no_boundary_fieldPortBcId);
            }

            {
                ptsInCell = new double[node_cnt, 2];
                for (int ino = 0; ino < node_cnt; ino++)
                {
                    for (int idim = 0; idim < 2; idim++)
                    {
                        ptsInCell[ino, idim] = coord_c_all[ino][idim];
                    }
                }
                int nodeCntB1 = no_c_all_fieldPortBcId_list[0].Length;
                nodeBInCell = new uint[boundaryCnt, nodeCntB1]; // 正方格子、上下左右境界の節点数は同じ
                for (int boundaryIndex = 0; boundaryIndex < boundaryCnt; boundaryIndex++)
                {
                    uint[] work_no_c_all_B = no_c_all_fieldPortBcId_list[boundaryIndex];
                    System.Diagnostics.Debug.Assert(nodeCntB1 == work_no_c_all_B.Length); // 正方格子、上下左右境界の節点数は同じ
                    for (int inoB = 0; inoB < work_no_c_all_B.Length; inoB++)
                    {
                        nodeBInCell[boundaryIndex, inoB] = work_no_c_all_B[inoB];
                    }
                }
                int elemCnt = elem_loopId.Length;
                elemLoopIdInCell = new uint[elemCnt];
                for (int ie = 0; ie < elemCnt; ie++)
                {
                    elemLoopIdInCell[ie] = elem_loopId[ie];
                }
                elemNodeInCell = new uint[elemCnt, 3];
                for (int ie = 0; ie < elemCnt; ie++)
                {
                    for (int inoe = 0; inoe < 3; inoe++)
                    {
                        elemNodeInCell[ie, inoe] = elem_no_c[ie][inoe];
                    }
                }
            }

            /*
             * using (StreamWriter sw = new StreamWriter("tmp.txt"))
             * {
             *  sw.WriteLine("//// {0}", node_cnt);
             *  for (int ino = 0; ino < node_cnt; ino++)
             *  {
             *      sw.WriteLine("{{{0}, {1}}},", coord_c_all[ino][0], coord_c_all[ino][1]);
             *  }
             *  sw.WriteLine("//// {0}", boundaryCnt);
             *  for (int boundaryIndex = 0; boundaryIndex < boundaryCnt; boundaryIndex++)
             *  {
             *      uint[] work_no_c_all_B = no_c_all_fieldPortBcId_list[boundaryIndex];
             *      sw.WriteLine("//// {0}", work_no_c_all_B.Length);
             *      for (int inoB = 0; inoB < work_no_c_all_B.Length; inoB++)
             *      {
             *          sw.WriteLine("{0},", work_no_c_all_B[inoB]);
             *      }
             *  }
             *  int elemCnt = elem_loopId.Length;
             *  sw.WriteLine("//// {0}", elemCnt);
             *  for (int ie = 0; ie < elemCnt; ie++)
             *  {
             *      sw.WriteLine("{0},", elem_loopId[ie]);
             *  }
             *  sw.WriteLine("//// {0}", elemCnt);
             *  for (int ie = 0; ie < elemCnt; ie++)
             *  {
             *      sw.WriteLine("{{{0}, {1}, {2}}},", elem_no_c[ie][0], elem_no_c[ie][1], elem_no_c[ie][2]);
             *  }
             * }
             */
        }