Skip to content
Stefano Zaghi edited this page Nov 6, 2015 · 2 revisions

To start using VecFor for your vector calculus algebra, you must import its main module:

use vecfor

This module exposes the following objects:

  • Vector: the main vector class, it being a derived type fully-overloaded and ready for vectorial algebra;
  • Vector_Ptr: a derived type wrapping Vector for allowing array of vector pointers;
  • ex, ey, ez: the Cartesian versors (unit vectors);
  • sq_norm: function for computing the square norm of a vector (also provided as a method of the vector type);
  • normL2: function for computing the norm L2 of a vector (also provided as a method of the vector type);
  • normalize: function for normalizing a vector (also provided as a method of the vector type);
  • face_normal3, face_normal4: function for computing the face normal once provided 3 or 4 points-vectors (also provided as a method of the vector type);

To start using VecFor you must obviously define a Vector object:

type(Vector):: vector1

Now that you have your vector declared you can start using it. The API to handle it follows.

API

The vector components are defined as real with parametrized kind; the default kind parameter is set to be 64-bit-like finite precision (defined by means of the portable select_real_kind intrinsic function), but it can be easily changed at compile time. Vector class is fully-overloaded with a far complete set of operators. The main Vector API definition is the following:

type, public :: Vector
  real(R8P) :: x = 0._R8P ! Cartesian component in x direction.
  real(R8P) :: y = 0._R8P ! Cartesian component in y direction.
  real(R8P) :: z = 0._R8P ! Cartesian component in z direction.
  contains
    procedure :: init
    procedure :: set
    procedure :: iolen
    procedure :: load
    procedure :: save
    procedure :: print
    procedure :: sq_norm
    procedure :: normL2
    procedure :: normalize
    procedure :: normalized
    procedure :: face_normal4
    procedure :: face_normal3
    generic   :: operator(.cross.)
    generic   :: operator(.dot.)
    generic   :: operator(.paral.)
    generic   :: operator(.ortho.)
    generic   :: assignment(=)
    generic   :: operator(*)
    generic   :: operator(/)
    generic   :: operator(+)
    generic   :: operator(-)
    generic   :: operator(/=)
    generic   :: operator(<)
    generic   :: operator(<=)
    generic   :: operator(==)
    generic   :: operator(>=)
    generic   :: operator(>)
endtype Vector

In the above API the private procedures have been omitted and the real kind parameter R8P is defined as R8P=selected_real_kind(15,307). All the operators are generic: automatic dynamic dispatch (efficiently resolved at compile time) allows to mix vector objects with integer and real numbers of any supported kinds. The supported kinds are:

  • R16P = selected_real_kind(33,4931): 33 digits, 128 bits.
  • R8P = selected_real_kind(15,307): 15 digits, 64 bits.
  • R4P = selected_real_kind(6,37): 6 digits, 32 bits.
  • I8P = selected_int_kind(18): 19 digits plus sign; 64 bits.
  • I4P = selected_int_kind(9): 10 digits plus sign; 32 bits.
  • I2P = selected_int_kind(4): 5 digits plus sign; 16 bits.
  • I1P = selected_int_kind(2): 3 digits plus sign; 8 bits.

Essentially, you can use vector objects as you usually do with intrinsic number variables

standard algebra
type(Vector) :: v1, v2

v1 = ex ! X versor [1, 0, 0] is assigned to v1
v2 = v1 + 2 ! v2 = [3, 2, 2]
v2 = v1 - 2 ! v2 = [-1, -2, -2]
v2 = v1 / 2 ! v2 = [0.5, 0, 0]
v2 = v1 * 2 ! v2 = [2, 0, 0]
v2 = ey + ez ! Y+Z versors [0, 1, 1] is assigned to v2
v1 = v1 + v2 ! [1, 1, 1]

However, with vector objects you can obviously perform vectorial calculus algebra

vectorial calculus algebra
type(Vector) :: v1, v2, cross
real(R8P)    :: dot

v1 = ex
v2 = ex + 2 * ey
cross = v1.cross.v2 ! [0, 0, 2]
dot = v1.dot.v2 ! ||ex|| = 1

Besides the canonical vectorial operators a bunch of others are also provided

operators // and _|_
type(Vector) :: v1, v2, parallel, orthogonal

v1 = 2 * ex
v2 = ex + ey
parallel = v1.paral.v2 ! ||v1||*v2/||v2|| => [1, 1, 0]
orthogonal = v1.ortho.v2 ! v1 - ||v1||*v2/||v2|| => [1, -1, 0]
normals (and areas)

Considering the 3 points face (general triangle in 3D) like

 1.----.2
   \   |
    \  |
     \ |
      \|
       .3

or the 4 points face (general parallelogram in 3D) like

 1.----------.2
  |          |
  |          |
  |          |
  |          |
 4.----------.3

VecFor allows you to easily compute the normal to such a faces

type(Vector) :: p1, p2, p3, p4, normal

p1 = -ex + ey  ! [-1, 1, 0]
p2 = ey ! [0, 1, 0]
p3 = -ey ! [0, -1, 0]
p4 = -ex - ey ! [-1, -1, 0]
call normal%face_normal3(pt1=p1, pt2=p2, pt3=p3) ! [0, 0, -1]
call normal%face_normal4(pt1=p1, pt2=p2, pt3=p3, pt4=p4) ! [0, 0, -2]

Note that the norm of the normal is equal to the area of the surfaces. In case you want the normal versor to the faces, i.e. the normal with unit norm, you can pass the optional norm dummy argument to the above showed methods like the following

type(Vector) :: p1, p2, p3, p4, normal

p1 = -ex + ey  ! [-1, 1, 0]
p2 = ey ! [0, 1, 0]
p3 = -ey ! [0, -1, 0]
p4 = -ex - ey ! [-1, -1, 0]
call normal%face_normal3(norm='y', pt1=p1, pt2=p2, pt3=p3) ! [0, 0, -1]
call normal%face_normal4(norm='y', pt1=p1, pt2=p2, pt3=p3, pt4=p4) ! [0, 0, -1]

Clone this wiki locally