!> Módulo de fuerzas primitivas de tipo neumático.
MODULE fuerzas_neumatico

IMPLICIT NONE

PRIVATE

!CCCCCCCCCCCCCCCCCCCCCCCCCC TIPOS DERIVADOS CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
    !> Tipo derivado de punto o vector local perteneciente a un sólido.
    TYPE,ABSTRACT::PUNTO_VECTOR
	    INTEGER idpt
    END TYPE PUNTO_VECTOR

    !> Tipo vector local perteneciente a un sólido. Puesto que es un vector local tiene CCL constantes.
    TYPE VECTOR
        !En el caso de que el vector también pertenezca a GROUND, se almacena el puntero al vector del suelo.
        !El puntero se utiliza principalmente en los cálculos de sensibilidad.
        CLASS(PUNTO_VECTOR),POINTER::GR_vc=>null()
    END TYPE VECTOR

    !Tipo base de ángulo y distancia
    TYPE,ABSTRACT:: type_dist_ang
        LOGICAL:: used=.FALSE. !Boolean que indica si true que esta variable es usada en un par.
        REAL(8),POINTER::r=>null(),rp=>null(),rs=>null() !Valores de posición, velocidad y aceleración del ángulo o la distancia.
        INTEGER,POINTER::iq=>null()
        LOGICAL:: iscalc_dq_dz=.FALSE.
    CONTAINS 
        PROCEDURE,PASS,NON_OVERRIDABLE::isANGULO=>dist_ang_isANGULO
        PROCEDURE,PASS,NON_OVERRIDABLE::toANGULO=>dist_ang_toANGULO
    END TYPE type_dist_ang

    ! Tipo derivado de ángulo y tipos extendidos.
    TYPE,EXTENDS(type_dist_ang)::typeANGULO
        TYPE(VECTOR),POINTER::eje
    END TYPE typeANGULO
    

    TYPE handle_DISTANCIA_ANGULO
        CLASS(type_dist_ang),POINTER,PRIVATE::dist_ang
    CONTAINS
        PROCEDURE,NON_OVERRIDABLE::getANGULO=>hDAgetANGULO
    END TYPE handle_DISTANCIA_ANGULO


    !> Tipo derivado fuerza de neumático en un contacto: modelo TMeasy con curvas linealizadas, con modelización con vectores fijos y ángulo
    TYPE::typeforce_tireTmeasyLin2
        REAL(8),ALLOCATABLE,DIMENSION(:,:)::CCL0
        TYPE(typeANGULO)::ang
        INTEGER,dimension(13)::ind
    END TYPE typeforce_tireTmeasyLin2

CONTAINS
    
!> Función para consultar si una type_dist_ang es un ángulo y en caso afirmativo devolver opcionalmente un puntero a la misma.
    FUNCTION dist_ang_isANGULO(dist_ang,pang)
        CLASS(type_dist_ang),TARGET::dist_ang
        CLASS(typeANGULO),POINTER,INTENT(OUT),OPTIONAL::pang
        LOGICAL dist_ang_isANGULO
        
        SELECT TYPE(dist_ang)
        CLASS IS(typeANGULO)
            if(present(pang)) pang=>dist_ang
            dist_ang_isANGULO=.true.
        CLASS DEFAULT
            if(present(pang)) NULLIFY(pang)
            dist_ang_isANGULO=.false.
        END SELECT
    END FUNCTION dist_ang_isANGULO

    !> Función para convertir un type_dist_ang a typeANGULO
    FUNCTION dist_ang_toANGULO(dist_ang)
        CLASS(type_dist_ang),INTENT(IN)::dist_ang
        CLASS(typeANGULO),POINTER::dist_ang_toANGULO
        
        if(.not.dist_ang%isANGULO(dist_ang_toANGULO)) THEN
            PRINT *,"solidos::dist_ang_toANGULO: tipo de type_dist_ang invalido. La entidad no es una typeANGULO."
            STOP -1
        endif
    END FUNCTION dist_ang_toANGULO

    FUNCTION hDAgetANGULO(hda)
        CLASS(handle_DISTANCIA_ANGULO)::hda
        CLASS(typeANGULO),POINTER::hDAgetANGULO
        
        hDAgetANGULO=>hda%dist_ang%toANGULO()
    END FUNCTION hDAgetANGULO


SUBROUTINE ADDforce_tireTmeasyLin2(ang)
    TYPE(handle_DISTANCIA_ANGULO),intent(in)::ang
	TYPE(typeforce_tireTmeasyLin2)::force_tireTmeasyLin2

    force_tireTmeasyLin2%ang=ang%getANGULO()
END SUBROUTINE ADDforce_tireTmeasyLin2

END MODULE fuerzas_neumatico
