angle_between Function

private elemental function angle_between(va_x, va_y, vb_x, vb_y) result(angle)

Compute the angle between to vectors (they should not both be the 0 vector).

This function uses the crossproduct and arctan to find the angle between two 2D vectors. It takes the four components of the vectors as scalar arguments to allow vectorized evaluation of multiple vector pairs at once. If one of the vectors is zero, the returned angle is also zero. Also multiplicities of Pi are ignored and a 0 angle will be returned for them.

Arguments

Type IntentOptional Attributes Name
real(kind=rk), intent(in) :: va_x

The first vector va

real(kind=rk), intent(in) :: va_y

The first vector va

real(kind=rk), intent(in) :: vb_x

The second vector vb

real(kind=rk), intent(in) :: vb_y

The second vector vb

Return Value real(kind=rk)

The angle betweend va and vb


Called by

proc~~angle_between~~CalledByGraph proc~angle_between angle_between proc~tem_polygon_material_test_angle tem_polygon_material_test_angle proc~tem_polygon_material_test_angle->proc~angle_between proc~tem_polygon_material_value tem_polygon_material_value proc~tem_polygon_material_value->proc~angle_between proc~tem_eval_polygon_material tem_eval_polygon_material proc~tem_eval_polygon_material->proc~tem_polygon_material_value proc~tem_eval_polygon_material_3d tem_eval_polygon_material_3d proc~tem_eval_polygon_material_3d->proc~tem_polygon_material_value proc~tem_eval_polygon_material_scal tem_eval_polygon_material_scal proc~tem_eval_polygon_material_scal->proc~tem_polygon_material_value proc~tem_eval_polygon_material_scal_3d tem_eval_polygon_material_scal_3d proc~tem_eval_polygon_material_scal_3d->proc~tem_polygon_material_value proc~tem_polygon_material_movement_multi tem_polygon_material_movement_multi proc~tem_polygon_material_movement_multi->proc~tem_polygon_material_value proc~tem_polygon_material_movement_single tem_polygon_material_movement_single proc~tem_polygon_material_movement_single->proc~tem_polygon_material_value proc~tem_polygon_material_test_value tem_polygon_material_test_value proc~tem_polygon_material_test_value->proc~tem_polygon_material_value proc~tem_spacetime_for_coord tem_spacetime_for_coord proc~tem_spacetime_for_coord->proc~tem_polygon_material_movement_multi proc~tem_spacetime_for_coord->proc~tem_polygon_material_movement_single proc~tem_spatial_for_coord tem_spatial_for_coord proc~tem_spatial_for_coord->proc~tem_eval_polygon_material_scal proc~tem_spatial_for_coord->proc~tem_eval_polygon_material_scal_3d proc~tem_spatial_vector_for_coord tem_spatial_vector_for_coord proc~tem_spatial_vector_for_coord->proc~tem_eval_polygon_material proc~tem_spatial_vector_for_coord->proc~tem_eval_polygon_material_3d interface~tem_spacetime_for tem_spacetime_for interface~tem_spacetime_for->proc~tem_spacetime_for_coord interface~tem_spatial_for tem_spatial_for interface~tem_spatial_for->proc~tem_spatial_for_coord interface~tem_spatial_for->proc~tem_spatial_vector_for_coord proc~tem_spacetime_for_stcoord tem_spacetime_for_stcoord proc~tem_spacetime_for_stcoord->proc~tem_spacetime_for_coord proc~tem_spacetime_scalar_for_index tem_spacetime_scalar_for_index proc~tem_spacetime_scalar_for_index->proc~tem_spacetime_for_coord proc~tem_spatial_scalar_for_index tem_spatial_scalar_for_index proc~tem_spatial_scalar_for_index->proc~tem_spatial_for_coord proc~tem_spatial_vector_for_index tem_spatial_vector_for_index proc~tem_spatial_vector_for_index->proc~tem_spatial_vector_for_coord

Source Code

  elemental function angle_between(va_x, va_y, vb_x, vb_y) result(angle)
    ! ----------------------------------------------------------------------
    !> The first vector va
    real(kind=rk), intent(in) :: va_x, va_y

    !> The second vector vb
    real(kind=rk), intent(in) :: vb_x, vb_y

    !> The angle betweend va and vb
    real(kind=rk) :: angle
    ! ----------------------------------------------------------------------

    angle = 0.0_rk

    ! Only proceed if both vectors are non-zero.
    ! If one of the vectors is 0, we assume a zero angle.
    if (      (abs(va_x)+abs(va_y) > 2*tiny(va_x)) &
      & .and. (abs(vb_x)+abs(vb_y) > 2*tiny(vb_x)) ) then
      ! The angle is arctan( (va X vb)/(va*vb) ):
      ! Using atan2 here for numerical stability and correct signs.
      angle = atan2( (va_x*vb_y - va_y*vb_x), &
        &            (va_x*vb_x + va_y*vb_y)  )

      ! If the angle is close enough to Pi, consider this as a colinear
      ! 0 angle (avoid multiplicities of Pi in the summed angle).
      if (abs(angle) > tolm*Pi) angle = 0.0_rk
    end if

  end function angle_between