/** * @brief 円柱を設定 * @param [in] R Controlクラスのポインタ * @param [in] pos_x 中心座標(x,y) (無次元) * @param [in] pos_y 中心座標(x,y) (無次元) * @param [in] radius 半径 (無次元) * @param [in] len_z 円柱のZ方向の長さ (無次元) * @param [in] mid_solid 固体媒質ID * @param [out] cut カット情報 * @param [out] bid 境界ID */ void IP_Cylinder::setCircle(Control* R, const REAL_TYPE pos_x, const REAL_TYPE pos_y, const REAL_TYPE radius, const REAL_TYPE len_z, const int mid_solid, long long* cut, int* bid) { Vec3r pch(pitch); ///< 無次元格子幅 Vec3r org(origin); ///< ノードローカル基点座標の無次元値 REAL_TYPE dx = pitch[0]; REAL_TYPE dy = pitch[1]; REAL_TYPE dz = pitch[2]; REAL_TYPE cx = pos_x; ///< 円柱の中心座標(無次元) REAL_TYPE cy = pos_y; ///< 円柱の中心座標(無次元) REAL_TYPE rs = radius; ///< 円柱の半径(無次元) int mid_s = mid_solid; // 球のbbox Vec3r box_min; ///< Bounding boxの最小値 Vec3r box_max; ///< Bounding boxの最大値 Vec3i box_st; ///< Bounding boxの始点インデクス Vec3i box_ed; ///< Bounding boxの終点インデクス box_min.assign( -(REAL_TYPE)rs+cx, -(REAL_TYPE)rs+cy, 0.0 ); // Z方向はダミー box_max.assign( (REAL_TYPE)rs+cx, (REAL_TYPE)rs+cy, 0.0 ); box_st = find_index(box_min, org, pch); box_ed = find_index(box_max, org, pch); int ix = size[0]; int jx = size[1]; int kx = size[2]; int gd = guide; // ローカルな無次元基点座標 REAL_TYPE ox = origin[0]; REAL_TYPE oy = origin[1]; REAL_TYPE oz = origin[2]; // グローバルな無次元座標 REAL_TYPE zs = oz; REAL_TYPE ze; if ( mode == dim_2d ) { ze = oz + region[2] + dz; // Z方向には全セルを対象, dzは安全係数 } else { ze = oz + len_z; // Z-面からの距離 } // カット情報 Vec3r p[5]; Vec3r base; // セルのシフト量 Vec3r b; // セルセンタ座標 REAL_TYPE lb[5]; // 内外判定フラグ for (int k=1; k<=kx; k++) { for (int j=box_st.y-1; j<=box_ed.y+1; j++) { for (int i=box_st.x-1; i<=box_ed.x+1; i++) { REAL_TYPE z = org.z + 0.5*dz + dz*(REAL_TYPE)(k-1); if ( z <= ze ) { base.assign((REAL_TYPE)i-0.5, (REAL_TYPE)j-0.5, (REAL_TYPE)k-0.5); b = org + base*pch; p[0].assign(b.x , b.y , b.z ); // p p[1].assign(b.x-dx, b.y , b.z ); // w p[2].assign(b.x+dx, b.y , b.z ); // e p[3].assign(b.x , b.y-dy, b.z ); // s p[4].assign(b.x , b.y+dy, b.z ); // n // (cx, cy, *)が球の中心 for (int l=0; l<5; l++) { REAL_TYPE x = p[l].x - cx; REAL_TYPE y = p[l].y - cy; REAL_TYPE rr = sqrt(x*x + y*y); lb[l] = ( rr <= rs ) ? -1.0 : 1.0; // 内側がマイナス } // cut test 注意! インデクスが1-4 for (int l=1; l<=4; l++) { if ( lb[0]*lb[l] < 0.0 ) { REAL_TYPE s = cut_line_2d(p[0], l, rs); size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd); int r = quantize9(s); setCut9(cut[m], r, l-1); setBit5(bid[m], mid_s, l-1); int rr = quantize9(1.0-s); size_t m1; switch (l-1) { case X_minus: m1 = _F_IDX_S3D(i-1, j, k, ix, jx, kx, gd); setBit5(bid[m1], mid_s, X_plus); setCut9(cut[m1], rr, X_plus); break; case X_plus: m1 = _F_IDX_S3D(i+1, j, k, ix, jx, kx, gd); setBit5(bid[m1], mid_s, X_minus); setCut9(cut[m1], rr, X_minus); break; case Y_minus: m1 = _F_IDX_S3D(i, j-1, k, ix, jx, kx, gd); setBit5(bid[m1], mid_s, Y_plus); setCut9(cut[m1], rr, Y_plus); break; case Y_plus: m1 = _F_IDX_S3D(i, j+1, k, ix, jx, kx, gd); setBit5(bid[m1], mid_s, Y_minus); setCut9(cut[m1], rr, Y_minus); break; } } } } // if z branch } } } if ( mode == dim_2d ) return; // Z+方向 #pragma omp parallel for firstprivate(ix, jx, kx, gd, mid_s, ox, oy, oz, dx, dy, dz, ze, rs, cx, cy) schedule(static) for (int k=1; k<=kx; k++) { for (int j=1; j<=jx; j++) { for (int i=1; i<=ix; i++) { size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd); REAL_TYPE x = ox + 0.5*dx + dx*(i-1); // position of cell center REAL_TYPE y = oy + 0.5*dy + dy*(j-1); REAL_TYPE z = oz + 0.5*dz + dz*(k-1); REAL_TYPE s = (ze - z)/dz; REAL_TYPE xx = x - cx; REAL_TYPE yy = y - cy; if ( (xx*xx + yy*yy) <= rs*rs ) { if ( (z <= ze) && (ze < z+dz) ) { setBit5(bid[m], mid_s, Z_plus); int r = quantize9(s); setCut9(cut[m], r, Z_plus); size_t m1 = _F_IDX_S3D(i, j, k+1, ix, jx, kx, gd); setBit5(bid[m1], mid_s, Z_minus); int rr = quantize9(1.0-s); setCut9(cut[m1], rr, Z_minus); } else if ( (z-dz < ze) && (ze < z) ) { setBit5(bid[m], mid_s, Z_minus); int r = quantize9(-s); setCut9(cut[m], r, Z_minus); size_t m1 = _F_IDX_S3D(i, j, k-1, ix, jx, kx, gd); setBit5(bid[m1], mid_s, Z_plus); int rr = quantize9(1.0+s); setCut9(cut[m1], rr, Z_plus); } } } } } // Z-方向 #pragma omp parallel for firstprivate(ix, jx, kx, gd, mid_s, ox, oy, oz, dx, dy, dz, zs, rs, cx, cy) schedule(static) for (int k=1; k<=kx; k++) { for (int j=1; j<=jx; j++) { for (int i=1; i<=ix; i++) { size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd); REAL_TYPE x = ox + 0.5*dx + dx*(i-1); // position of cell center REAL_TYPE y = oy + 0.5*dy + dy*(j-1); REAL_TYPE z = oz + 0.5*dz + dz*(k-1); REAL_TYPE s = (zs - z)/dz; REAL_TYPE xx = x - cx; REAL_TYPE yy = y - cy; if ( (xx*xx + yy*yy) <= rs*rs ) { if ( (z <= zs) && (zs < z+dz) ) { setBit5(bid[m], mid_s, Z_plus); int r = quantize9(s); setCut9(cut[m], r, Z_plus); size_t m1 = _F_IDX_S3D(i, j, k+1, ix, jx, kx, gd); setBit5(bid[m1], mid_s, Z_minus); int rr = quantize9(1.0-s); setCut9(cut[m1], rr, Z_minus); } else if ( (z-dz < zs) && (zs < z) ) { setBit5(bid[m], mid_s, Z_minus); int r = quantize9(-s); setCut9(cut[m], r, Z_minus); size_t m1 = _F_IDX_S3D(i, j, k-1, ix, jx, kx, gd); setBit5(bid[m1], mid_s, Z_plus); int rr = quantize9(1.0+s); setCut9(cut[m1], rr, Z_plus); } } } } } }