make_plate_hole Subroutine

public subroutine make_plate_hole(mesh, size_x, size_y, radius, n_theta, n_r, center)

XY平面の長方形プレートから円形穴を除いたメッシュを生成する。 穴境界は n_theta 分割の多角形近似で表し、外周は長方形境界に一致させる。

Arguments

Type IntentOptional Attributes Name
type(mesh_type), intent(out) :: mesh

生成した穴あきプレートメッシュ。

real(kind=dp), intent(in), optional :: size_x

X方向サイズ [m](省略時 1.0)。

real(kind=dp), intent(in), optional :: size_y

X方向サイズ [m](省略時 1.0)。 Y方向サイズ [m](省略時 1.0)。

real(kind=dp), intent(in), optional :: radius

X方向サイズ [m](省略時 1.0)。 Y方向サイズ [m](省略時 1.0)。 穴半径 [m](省略時 0.2)。

integer(kind=i32), intent(in), optional :: n_theta

穴の周方向分割数(省略時 48)。

integer(kind=i32), intent(in), optional :: n_r

穴の周方向分割数(省略時 48)。 穴縁から外周までの半径方向分割数(省略時 4)。

real(kind=dp), intent(in), optional :: center(3)

X方向サイズ [m](省略時 1.0)。 Y方向サイズ [m](省略時 1.0)。 穴半径 [m](省略時 0.2)。


Calls

proc~~make_plate_hole~~CallsGraph proc~make_plate_hole make_plate_hole proc~init_mesh init_mesh proc~make_plate_hole->proc~init_mesh proc~push_tri push_tri proc~make_plate_hole->proc~push_tri proc~ray_to_rectangle ray_to_rectangle proc~make_plate_hole->proc~ray_to_rectangle proc~transition_corner_count transition_corner_count proc~make_plate_hole->proc~transition_corner_count proc~transition_corners transition_corners proc~make_plate_hole->proc~transition_corners proc~update_mesh_geometry update_mesh_geometry proc~init_mesh->proc~update_mesh_geometry proc~edge_order_index edge_order_index proc~transition_corner_count->proc~edge_order_index proc~transition_corners->proc~transition_corner_count proc~corner_between corner_between proc~transition_corners->proc~corner_between proc~edge_next_ccw edge_next_ccw proc~transition_corners->proc~edge_next_ccw proc~build_collision_grid build_collision_grid proc~update_mesh_geometry->proc~build_collision_grid proc~cross~2 cross proc~update_mesh_geometry->proc~cross~2 proc~cell_id~2 cell_id proc~build_collision_grid->proc~cell_id~2 proc~coord_to_cell~2 coord_to_cell proc~build_collision_grid->proc~coord_to_cell~2

Called by

proc~~make_plate_hole~~CalledByGraph proc~make_plate_hole make_plate_hole proc~build_one_template build_one_template proc~build_one_template->proc~make_plate_hole proc~build_template_mesh build_template_mesh proc~build_template_mesh->proc~build_one_template proc~build_mesh_from_config build_mesh_from_config proc~build_mesh_from_config->proc~build_template_mesh proc~load_or_init_run_state load_or_init_run_state proc~load_or_init_run_state->proc~build_mesh_from_config program~main main program~main->proc~load_or_init_run_state

Source Code

  subroutine make_plate_hole(mesh, size_x, size_y, radius, n_theta, n_r, center)
    type(mesh_type), intent(out) :: mesh
    real(dp), intent(in), optional :: size_x, size_y, radius, center(3)
    integer(i32), intent(in), optional :: n_theta, n_r
    real(dp) :: sx, sy, r_hole, c(3), pi, angle, f0, f1
    real(dp) :: x_min, x_max, y_min, y_max, min_margin
    real(dp) :: p00(3), p01(3), p10(3), p11(3), corners(3, 3)
    integer(i32) :: nt, nr0, it, ir, itri, nelem, n_corner, k
    integer(i32), allocatable :: edge_ids(:)
    real(dp), allocatable :: hole_pts(:, :), outer_pts(:, :)
    real(dp), allocatable :: v0(:, :), v1(:, :), v2(:, :)

    sx = 1.0d0; sy = 1.0d0; r_hole = 0.2d0; nt = 48; nr0 = 4; c = 0.0d0
    if (present(size_x)) sx = size_x
    if (present(size_y)) sy = size_y
    if (present(radius)) r_hole = radius
    if (present(n_theta)) nt = n_theta
    if (present(n_r)) nr0 = n_r
    if (present(center)) c = center
    if (sx <= 0.0d0 .or. sy <= 0.0d0) error stop "size_x and size_y must be positive"
    if (nt < 3 .or. nr0 <= 0) error stop "n_theta >= 3 and n_r > 0"

    x_min = c(1) - 0.5d0*sx
    x_max = c(1) + 0.5d0*sx
    y_min = c(2) - 0.5d0*sy
    y_max = c(2) + 0.5d0*sy
    min_margin = min(min(c(1) - x_min, x_max - c(1)), min(c(2) - y_min, y_max - c(2)))
    if (r_hole <= 0.0d0) error stop "radius must be > 0 for plate_hole"
    if (r_hole >= min_margin) error stop "plate_hole radius must be smaller than half-width/half-height"

    allocate (hole_pts(3, nt + 1), outer_pts(3, nt + 1), edge_ids(nt + 1))
    pi = acos(-1.0d0)
    do it = 0, nt
      angle = 2.0d0*pi*real(it, dp)/real(nt, dp)
      hole_pts(:, it + 1) = [c(1) + r_hole*cos(angle), c(2) + r_hole*sin(angle), c(3)]
      call ray_to_rectangle( &
        c(1), c(2), cos(angle), sin(angle), x_min, x_max, y_min, y_max, c(3), outer_pts(:, it + 1), edge_ids(it + 1) &
        )
    end do

    nelem = 2*nt*nr0
    do it = 1, nt
      nelem = nelem + transition_corner_count(edge_ids(it), edge_ids(it + 1))
    end do
    allocate (v0(3, nelem), v1(3, nelem), v2(3, nelem))

    itri = 0
    do it = 1, nt
      do ir = 0, nr0 - 1
        f0 = real(ir, dp)/real(nr0, dp)
        f1 = real(ir + 1, dp)/real(nr0, dp)
        p00 = hole_pts(:, it) + f0*(outer_pts(:, it) - hole_pts(:, it))
        p10 = hole_pts(:, it) + f1*(outer_pts(:, it) - hole_pts(:, it))
        p01 = hole_pts(:, it + 1) + f0*(outer_pts(:, it + 1) - hole_pts(:, it + 1))
        p11 = hole_pts(:, it + 1) + f1*(outer_pts(:, it + 1) - hole_pts(:, it + 1))
        call push_tri(v0, v1, v2, itri, p00, p10, p11)
        call push_tri(v0, v1, v2, itri, p00, p11, p01)
      end do

      call transition_corners( &
        edge_ids(it), edge_ids(it + 1), x_min, x_max, y_min, y_max, c(3), corners, n_corner &
        )
      if (n_corner > 0) then
        if (n_corner == 1) then
          call push_tri(v0, v1, v2, itri, outer_pts(:, it), corners(:, 1), outer_pts(:, it + 1))
        else
          call push_tri(v0, v1, v2, itri, outer_pts(:, it), corners(:, 1), corners(:, 2))
          do k = 2, n_corner - 1
            call push_tri(v0, v1, v2, itri, outer_pts(:, it), corners(:, k), corners(:, k + 1))
          end do
          call push_tri(v0, v1, v2, itri, outer_pts(:, it), corners(:, n_corner), outer_pts(:, it + 1))
        end if
      end if
    end do

    if (itri /= nelem) error stop "plate_hole triangle bookkeeping mismatch"
    call init_mesh(mesh, v0, v1, v2)
  end subroutine make_plate_hole