build_periodic_zero_mode_height_plan Subroutine

public subroutine build_periodic_zero_mode_height_plan(source_heights, area_xy, plan, status, message)

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(in) :: source_heights(:,:)
real(kind=dp), intent(in) :: area_xy
type(periodic_zero_mode_plan_type), intent(out) :: plan
integer(kind=i32), intent(out) :: status
character(len=*), intent(out) :: message

Called by

proc~~build_periodic_zero_mode_height_plan~~CalledByGraph proc~build_periodic_zero_mode_height_plan build_periodic_zero_mode_height_plan proc~beach_zero_mode_build beach_zero_mode_build proc~beach_zero_mode_build->proc~build_periodic_zero_mode_height_plan proc~build_periodic_zero_mode_plan build_periodic_zero_mode_plan proc~build_periodic_zero_mode_plan->proc~build_periodic_zero_mode_height_plan proc~core_build_panel_plan_impl core_build_panel_plan_impl proc~core_build_panel_plan_impl->proc~build_periodic_zero_mode_height_plan proc~core_build_plan_impl core_build_plan_impl proc~core_build_plan_impl->proc~build_periodic_zero_mode_height_plan

Source Code

  subroutine build_periodic_zero_mode_height_plan(source_heights, area_xy, plan, status, message)
    real(dp), intent(in) :: source_heights(:, :)
    real(dp), intent(in) :: area_xy
    type(periodic_zero_mode_plan_type), intent(out) :: plan
    integer(i32), intent(out) :: status
    character(len=*), intent(out) :: message
    real(dp), allocatable :: heights(:), unique_heights(:)
    real(dp) :: scale, tolerance
    integer(i32) :: elem, vertex, count, nelem

    status = periodic_zero_mode_invalid
    message = ''
    if (.not. ieee_is_finite(area_xy) .or. area_xy <= 0.0_dp) then
      message = 'periodic zero-mode area_xy must be finite and positive'
      return
    end if
    if (size(source_heights, 1) /= 3 .or. size(source_heights, 2) <= 0) then
      message = 'periodic zero-mode heights must have shape (3, nsource)'
      return
    end if
    if (any(.not. ieee_is_finite(source_heights))) then
      message = 'periodic zero-mode panel heights must be finite'
      return
    end if
    nelem = int(size(source_heights, 2), i32)
    allocate (heights(3*nelem))
    do elem = 1_i32, nelem
      heights(3*elem - 2:3*elem) = source_heights(:, elem)
    end do
    call sort_real(heights)
    scale = max(1.0_dp, maxval(abs(heights)))
    tolerance = 128.0_dp*epsilon(1.0_dp)*scale
    allocate (unique_heights(size(heights)))
    count = 1_i32
    unique_heights(1) = heights(1)
    do vertex = 2, size(heights)
      if (abs(heights(vertex) - unique_heights(count)) > tolerance) then
        count = count + 1_i32
        unique_heights(count) = heights(vertex)
      end if
    end do

    plan%nelem = nelem
    plan%nbreak = count
    plan%area_xy = area_xy
    allocate (plan%break_z(count), plan%panel(nelem))
    plan%break_z = unique_heights(1:count)
    do elem = 1, nelem
      plan%panel(elem)%z = source_heights(:, elem)
      call sort_three(plan%panel(elem)%z)
      plan%panel(elem)%horizontal = &
        abs(plan%panel(elem)%z(3) - plan%panel(elem)%z(1)) <= tolerance
      do vertex = 1, 3
        plan%panel(elem)%break_index(vertex) = nearest_break(plan%break_z, plan%panel(elem)%z(vertex))
      end do
    end do
    status = periodic_zero_mode_ok
  end subroutine build_periodic_zero_mode_height_plan