bem_panel_geometry.f90 Source File


This file depends on

sourcefile~~bem_panel_geometry.f90~~EfferentGraph sourcefile~bem_panel_geometry.f90 bem_panel_geometry.f90 sourcefile~bem_kinds.f90 bem_kinds.f90 sourcefile~bem_panel_geometry.f90->sourcefile~bem_kinds.f90

Files dependent on this one

sourcefile~~bem_panel_geometry.f90~~AfferentGraph sourcefile~bem_panel_geometry.f90 bem_panel_geometry.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90 bem_coulomb_fmm_eval_ops.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_coulomb_fmm_types.f90 bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_panel_kernel.f90 bem_panel_kernel.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90->sourcefile~bem_panel_kernel.f90 sourcefile~bem_coulomb_fmm_basis.f90 bem_coulomb_fmm_basis.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90->sourcefile~bem_coulomb_fmm_basis.f90 sourcefile~bem_coulomb_fmm_periodic.f90 bem_coulomb_fmm_periodic.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90->sourcefile~bem_coulomb_fmm_periodic.f90 sourcefile~bem_coulomb_fmm_tree_utils.f90 bem_coulomb_fmm_tree_utils.f90 sourcefile~bem_coulomb_fmm_eval_ops.f90->sourcefile~bem_coulomb_fmm_tree_utils.f90 sourcefile~bem_coulomb_fmm_periodic_nonzero_reference.f90 bem_coulomb_fmm_periodic_nonzero_reference.f90 sourcefile~bem_coulomb_fmm_periodic_nonzero_reference.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_triangle_quadrature.f90 bem_triangle_quadrature.f90 sourcefile~bem_coulomb_fmm_periodic_nonzero_reference.f90->sourcefile~bem_triangle_quadrature.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90 bem_coulomb_fmm_plan_ops.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_coulomb_fmm_basis.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_coulomb_fmm_periodic.f90 sourcefile~bem_coulomb_fmm_periodic_ewald.f90 bem_coulomb_fmm_periodic_ewald.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_coulomb_fmm_periodic_ewald.f90 sourcefile~bem_coulomb_fmm_periodic_root_ops.f90 bem_coulomb_fmm_periodic_root_ops.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_coulomb_fmm_periodic_root_ops.f90 sourcefile~bem_coulomb_fmm_plan_ops.f90->sourcefile~bem_coulomb_fmm_tree_utils.f90 sourcefile~bem_coulomb_fmm_types.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_electrostatic_snapshot.f90 bem_electrostatic_snapshot.f90 sourcefile~bem_electrostatic_snapshot.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_electrostatic_snapshot.f90->sourcefile~bem_coulomb_fmm_periodic_nonzero_reference.f90 sourcefile~bem_electrostatic_snapshot.f90->sourcefile~bem_panel_kernel.f90 sourcefile~bem_field_solver.f90 bem_field_solver.f90 sourcefile~bem_electrostatic_snapshot.f90->sourcefile~bem_field_solver.f90 sourcefile~bem_field_kernel_c.f90 bem_field_kernel_c.f90 sourcefile~bem_field_kernel_c.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_coulomb_fmm_core.f90 bem_coulomb_fmm_core.f90 sourcefile~bem_field_kernel_c.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_field_solver_eval.f90 bem_field_solver_eval.f90 sourcefile~bem_field_solver_eval.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_field_solver_eval.f90->sourcefile~bem_panel_kernel.f90 sourcefile~bem_field_solver_eval.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_field_solver_eval.f90->sourcefile~bem_field_solver.f90 sourcefile~bem_mesh.f90 bem_mesh.f90 sourcefile~bem_mesh.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_mesh.f90->sourcefile~bem_triangle_quadrature.f90 sourcefile~bem_panel_kernel.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_panel_self_terms.f90 bem_panel_self_terms.f90 sourcefile~bem_panel_kernel.f90->sourcefile~bem_panel_self_terms.f90 sourcefile~bem_panel_quadrature.f90 bem_panel_quadrature.f90 sourcefile~bem_panel_quadrature.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_panel_quadrature.f90->sourcefile~bem_triangle_quadrature.f90 sourcefile~bem_panel_self_terms.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_surface_models_conductor.f90 bem_surface_models_conductor.f90 sourcefile~bem_surface_models_conductor.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_surface_models_conductor.f90->sourcefile~bem_panel_kernel.f90 sourcefile~bem_triangle_quadrature.f90->sourcefile~bem_panel_geometry.f90 sourcefile~bem_app_config_mesh_runtime.f90 bem_app_config_mesh_runtime.f90 sourcefile~bem_app_config_mesh_runtime.f90->sourcefile~bem_mesh.f90 sourcefile~bem_importers.f90 bem_importers.f90 sourcefile~bem_app_config_mesh_runtime.f90->sourcefile~bem_importers.f90 sourcefile~bem_templates.f90 bem_templates.f90 sourcefile~bem_app_config_mesh_runtime.f90->sourcefile~bem_templates.f90 sourcefile~bem_app_config_particle_runtime.f90 bem_app_config_particle_runtime.f90 sourcefile~bem_app_config_particle_runtime.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_app_config_potential_runtime.f90 bem_app_config_potential_runtime.f90 sourcefile~bem_app_config_particle_runtime.f90->sourcefile~bem_app_config_potential_runtime.f90 sourcefile~bem_app_config_potential_runtime.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_coulomb_fmm_basis.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_core.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_core_build.f90 bem_coulomb_fmm_core_build.f90 sourcefile~bem_coulomb_fmm_core_build.f90->sourcefile~bem_coulomb_fmm_plan_ops.f90 sourcefile~bem_coulomb_fmm_core_build.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_coulomb_fmm_core_eval.f90 bem_coulomb_fmm_core_eval.f90 sourcefile~bem_coulomb_fmm_core_eval.f90->sourcefile~bem_coulomb_fmm_eval_ops.f90 sourcefile~bem_coulomb_fmm_core_eval.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_coulomb_fmm_periodic.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_periodic_ewald.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_periodic_ewald.f90->sourcefile~bem_coulomb_fmm_periodic.f90 sourcefile~bem_coulomb_fmm_periodic_root_ops.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_periodic_root_ops.f90->sourcefile~bem_coulomb_fmm_basis.f90 sourcefile~bem_coulomb_fmm_periodic_root_ops.f90->sourcefile~bem_coulomb_fmm_periodic.f90 sourcefile~bem_coulomb_fmm_periodic_root_ops.f90->sourcefile~bem_coulomb_fmm_periodic_ewald.f90 sourcefile~bem_coulomb_fmm_periodic_root_ops.f90->sourcefile~bem_coulomb_fmm_tree_utils.f90 sourcefile~bem_coulomb_fmm_state_ops.f90 bem_coulomb_fmm_state_ops.f90 sourcefile~bem_coulomb_fmm_state_ops.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_state_ops.f90->sourcefile~bem_coulomb_fmm_tree_utils.f90 sourcefile~bem_coulomb_fmm_tree_utils.f90->sourcefile~bem_coulomb_fmm_types.f90 sourcefile~bem_coulomb_fmm_tree_utils.f90->sourcefile~bem_coulomb_fmm_periodic.f90 sourcefile~bem_electrostatic_snapshot_eval.f90 bem_electrostatic_snapshot_eval.f90 sourcefile~bem_electrostatic_snapshot_eval.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_importers.f90->sourcefile~bem_mesh.f90 sourcefile~bem_matching_plane_coupling.f90 bem_matching_plane_coupling.f90 sourcefile~bem_matching_plane_coupling.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_app_config.f90 bem_app_config.f90 sourcefile~bem_matching_plane_coupling.f90->sourcefile~bem_app_config.f90 sourcefile~bem_output_writer.f90 bem_output_writer.f90 sourcefile~bem_output_writer.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_particle_stepper.f90 bem_particle_stepper.f90 sourcefile~bem_particle_stepper.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_simulator.f90 bem_simulator.f90 sourcefile~bem_simulator.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~bem_simulator.f90->sourcefile~bem_output_writer.f90 sourcefile~bem_simulator.f90->sourcefile~bem_particle_stepper.f90 sourcefile~bem_app_config_runtime.f90 bem_app_config_runtime.f90 sourcefile~bem_simulator.f90->sourcefile~bem_app_config_runtime.f90 sourcefile~bem_simulator.f90->sourcefile~bem_app_config.f90 sourcefile~bem_templates.f90->sourcefile~bem_mesh.f90 sourcefile~main.f90 main.f90 sourcefile~main.f90->sourcefile~bem_electrostatic_snapshot.f90 sourcefile~main.f90->sourcefile~bem_mesh.f90 sourcefile~main.f90->sourcefile~bem_output_writer.f90 sourcefile~main.f90->sourcefile~bem_simulator.f90 sourcefile~bem_periodic_checkpoint.f90 bem_periodic_checkpoint.f90 sourcefile~main.f90->sourcefile~bem_periodic_checkpoint.f90 sourcefile~main.f90->sourcefile~bem_app_config.f90 sourcefile~bem_app_config_particle_runtime_batch.f90 bem_app_config_particle_runtime_batch.f90 sourcefile~bem_app_config_particle_runtime_batch.f90->sourcefile~bem_app_config_particle_runtime.f90 sourcefile~bem_app_config_particle_runtime_sampling.f90 bem_app_config_particle_runtime_sampling.f90 sourcefile~bem_app_config_particle_runtime_sampling.f90->sourcefile~bem_app_config_particle_runtime.f90 sourcefile~bem_app_config_runtime.f90->sourcefile~bem_app_config_mesh_runtime.f90 sourcefile~bem_app_config_runtime.f90->sourcefile~bem_app_config_particle_runtime.f90 sourcefile~bem_app_config_runtime.f90->sourcefile~bem_app_config_potential_runtime.f90 sourcefile~bem_coulomb_fmm_core_state.f90 bem_coulomb_fmm_core_state.f90 sourcefile~bem_coulomb_fmm_core_state.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_coulomb_fmm_core_state.f90->sourcefile~bem_coulomb_fmm_state_ops.f90 sourcefile~bem_field_solver.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_field_solver_config.f90 bem_field_solver_config.f90 sourcefile~bem_field_solver_config.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_field_solver_config.f90->sourcefile~bem_field_solver.f90 sourcefile~bem_field_solver_fmm.f90 bem_field_solver_fmm.f90 sourcefile~bem_field_solver_fmm.f90->sourcefile~bem_coulomb_fmm_core.f90 sourcefile~bem_field_solver_fmm.f90->sourcefile~bem_field_solver.f90 sourcefile~bem_output_writer_files.f90 bem_output_writer_files.f90 sourcefile~bem_output_writer_files.f90->sourcefile~bem_output_writer.f90 sourcefile~bem_output_writer_history.f90 bem_output_writer_history.f90 sourcefile~bem_output_writer_history.f90->sourcefile~bem_output_writer.f90 sourcefile~bem_output_writer_summary.f90 bem_output_writer_summary.f90 sourcefile~bem_output_writer_summary.f90->sourcefile~bem_output_writer.f90 sourcefile~bem_output_writer_summary.f90->sourcefile~bem_field_solver.f90 sourcefile~bem_periodic_checkpoint.f90->sourcefile~bem_output_writer.f90 sourcefile~bem_simulator_charge.f90 bem_simulator_charge.f90 sourcefile~bem_simulator_charge.f90->sourcefile~bem_simulator.f90 sourcefile~bem_simulator_io.f90 bem_simulator_io.f90 sourcefile~bem_simulator_io.f90->sourcefile~bem_output_writer.f90 sourcefile~bem_simulator_io.f90->sourcefile~bem_simulator.f90 sourcefile~bem_simulator_io.f90->sourcefile~bem_app_config_runtime.f90 sourcefile~bem_simulator_loop.f90 bem_simulator_loop.f90 sourcefile~bem_simulator_loop.f90->sourcefile~bem_matching_plane_coupling.f90 sourcefile~bem_simulator_loop.f90->sourcefile~bem_simulator.f90 sourcefile~bem_simulator_loop.f90->sourcefile~bem_app_config_runtime.f90 sourcefile~bem_simulator_loop.f90->sourcefile~bem_periodic_checkpoint.f90 sourcefile~bem_simulator_particles.f90 bem_simulator_particles.f90 sourcefile~bem_simulator_particles.f90->sourcefile~bem_simulator.f90 sourcefile~bem_simulator_stats.f90 bem_simulator_stats.f90 sourcefile~bem_simulator_stats.f90->sourcefile~bem_simulator.f90 sourcefile~bem_app_config.f90->sourcefile~bem_app_config_runtime.f90 sourcefile~bem_field_solver_tree.f90 bem_field_solver_tree.f90 sourcefile~bem_field_solver_tree.f90->sourcefile~bem_field_solver.f90 sourcefile~zhao_atlas_main.f90 zhao_atlas_main.f90 sourcefile~zhao_atlas_main.f90->sourcefile~bem_app_config.f90 sourcefile~zhao_response_main.f90 zhao_response_main.f90 sourcefile~zhao_response_main.f90->sourcefile~bem_app_config.f90

Source Code

!> Ordered triangle geometry and exact Cartesian surface moments.
module bem_panel_geometry
  use, intrinsic :: ieee_arithmetic, only: ieee_is_finite
  use bem_kinds, only: dp, i32
  implicit none
  private

  integer(i32), parameter, public :: panel_geometry_ok = 0_i32
  integer(i32), parameter, public :: panel_geometry_nonfinite = 1_i32
  integer(i32), parameter, public :: panel_geometry_degenerate = 2_i32

  type, public :: panel_geometry_type
    real(dp) :: vertex(3, 3) = 0.0_dp
    real(dp) :: centroid(3) = 0.0_dp
    real(dp) :: normal(3) = 0.0_dp
    real(dp) :: area = 0.0_dp
    real(dp) :: edge_length(3) = 0.0_dp
    real(dp) :: edge_outward(3, 3) = 0.0_dp
    real(dp) :: moment0 = 0.0_dp
    real(dp) :: moment1(3) = 0.0_dp
    real(dp) :: moment2(3, 3) = 0.0_dp
  end type panel_geometry_type

  public :: init_panel_geometry
  public :: point_triangle_distance

contains

  subroutine init_panel_geometry(v0, v1, v2, geometry, status)
    real(dp), intent(in) :: v0(3), v1(3), v2(3)
    type(panel_geometry_type), intent(out) :: geometry
    integer(i32), intent(out) :: status
    real(dp) :: edge1(3), edge2(3), cross12(3), norm_cross, lref
    real(dp) :: vertex_sum(3)
    integer :: edge, next_edge

    geometry = panel_geometry_type()
    status = panel_geometry_nonfinite
    if (.not. all(ieee_is_finite(v0)) .or. .not. all(ieee_is_finite(v1)) .or. &
        .not. all(ieee_is_finite(v2))) return

    geometry%vertex(:, 1) = v0
    geometry%vertex(:, 2) = v1
    geometry%vertex(:, 3) = v2
    edge1 = v1 - v0
    edge2 = v2 - v0
    cross12 = cross_product(edge1, edge2)
    norm_cross = sqrt(sum(cross12*cross12))
    lref = max(norm2(edge1), norm2(edge2), norm2(v2 - v1))
    status = panel_geometry_degenerate
    if (lref <= 0.0_dp) return
    if (norm_cross <= 128.0_dp*epsilon(1.0_dp)*lref*lref) return

    geometry%area = 0.5_dp*norm_cross
    geometry%normal = cross12/norm_cross
    geometry%centroid = (v0 + v1 + v2)/3.0_dp
    do edge = 1, 3
      next_edge = merge(edge + 1, 1, edge < 3)
      edge1 = geometry%vertex(:, next_edge) - geometry%vertex(:, edge)
      geometry%edge_length(edge) = sqrt(sum(edge1*edge1))
      geometry%edge_outward(:, edge) = cross_product(edge1, geometry%normal)/geometry%edge_length(edge)
    end do

    geometry%moment0 = geometry%area
    geometry%moment1 = geometry%area*geometry%centroid
    vertex_sum = v0 + v1 + v2
    geometry%moment2 = geometry%area/12.0_dp*( &
                       outer_product(v0, v0) + outer_product(v1, v1) + outer_product(v2, v2) + &
                       outer_product(vertex_sum, vertex_sum) &
                       )
    status = panel_geometry_ok
  end subroutine init_panel_geometry

  pure real(dp) function point_triangle_distance(geometry, point) result(distance)
    type(panel_geometry_type), intent(in) :: geometry
    real(dp), intent(in) :: point(3)
    real(dp) :: ab(3), ac(3), ap(3), bp(3), cp(3), closest(3)
    real(dp) :: d1, d2, d3, d4, d5, d6, va, vb, vc, denom, v, w

    ab = geometry%vertex(:, 2) - geometry%vertex(:, 1)
    ac = geometry%vertex(:, 3) - geometry%vertex(:, 1)
    ap = point - geometry%vertex(:, 1)
    d1 = dot_product(ab, ap)
    d2 = dot_product(ac, ap)
    if (d1 <= 0.0_dp .and. d2 <= 0.0_dp) then
      closest = geometry%vertex(:, 1)
    else
      bp = point - geometry%vertex(:, 2)
      d3 = dot_product(ab, bp)
      d4 = dot_product(ac, bp)
      if (d3 >= 0.0_dp .and. d4 <= d3) then
        closest = geometry%vertex(:, 2)
      else
        vc = d1*d4 - d3*d2
        if (vc <= 0.0_dp .and. d1 >= 0.0_dp .and. d3 <= 0.0_dp) then
          v = d1/(d1 - d3)
          closest = geometry%vertex(:, 1) + v*ab
        else
          cp = point - geometry%vertex(:, 3)
          d5 = dot_product(ab, cp)
          d6 = dot_product(ac, cp)
          if (d6 >= 0.0_dp .and. d5 <= d6) then
            closest = geometry%vertex(:, 3)
          else
            vb = d5*d2 - d1*d6
            if (vb <= 0.0_dp .and. d2 >= 0.0_dp .and. d6 <= 0.0_dp) then
              w = d2/(d2 - d6)
              closest = geometry%vertex(:, 1) + w*ac
            else
              va = d3*d6 - d5*d4
              if (va <= 0.0_dp .and. (d4 - d3) >= 0.0_dp .and. (d5 - d6) >= 0.0_dp) then
                w = (d4 - d3)/((d4 - d3) + (d5 - d6))
                closest = geometry%vertex(:, 2) + w*(geometry%vertex(:, 3) - geometry%vertex(:, 2))
              else
                denom = 1.0_dp/(va + vb + vc)
                v = vb*denom
                w = vc*denom
                closest = geometry%vertex(:, 1) + v*ab + w*ac
              end if
            end if
          end if
        end if
      end if
    end if
    distance = sqrt(sum((point - closest)**2))
  end function point_triangle_distance

  pure function cross_product(a, b) result(c)
    real(dp), intent(in) :: a(3), b(3)
    real(dp) :: c(3)

    c = [a(2)*b(3) - a(3)*b(2), a(3)*b(1) - a(1)*b(3), a(1)*b(2) - a(2)*b(1)]
  end function cross_product

  pure real(dp) function norm2(vector) result(norm)
    real(dp), intent(in) :: vector(3)

    norm = sqrt(sum(vector*vector))
  end function norm2

  pure function outer_product(a, b) result(product)
    real(dp), intent(in) :: a(3), b(3)
    real(dp) :: product(3, 3)
    integer :: i, j

    do j = 1, 3
      do i = 1, 3
        product(i, j) = a(i)*b(j)
      end do
    end do
  end function outer_product

end module bem_panel_geometry