program f90_FEM_FRAME
    !*******************************************************
    !2D frame analysis
    !*******************************************************
    implicit none
    integer::i,j,k,l,m,kk,ne,n,ia,ja,iii
    character::strcom*50                !Comment
    integer::NODT                       !Number of nodes
    integer::NELT                       !Number of elements
    integer::MATEL                      !Number of material sets
    integer::KOX                        !Number of restricted nodes in x-direction
    integer::KOY                        !Number of restricted nodes in y-direction
    integer::KOZ                        !Number of restricted nodes in rotation
    integer::NF                         !Number of loaded nodes
    integer,allocatable::kakom(:,:)     !Element connectivity
    integer,allocatable::matno(:)       !Material set number
    integer,allocatable::noten(:)       !Flag for No-tensio
    real(8),allocatable::wm(:,:)        !work for material properties
    real(8),allocatable::Em(:)          !Elastic modulus of element
    real(8),allocatable::Er(:)          !Elastic modulus of element
    real(8),allocatable::AA(:)          !Section area of element
    real(8),allocatable::AI(:)          !Moment of inertia
    real(8),allocatable::gamma(:)       !Unit weight of element
    real(8),allocatable::gkh(:)         !Horizontal acceleration for element in the ratio to 'g'
    real(8),allocatable::gkv(:)         !Vertical acceleration for element in the ratio to 'g'
    real(8),allocatable::alpha(:)       !Coefficient of thermal expansion of element
    real(8),allocatable::ts(:)          !Tensile strength
    real(8),allocatable::x(:)           !x-coordinate of node
    real(8),allocatable::y(:)           !y-coordinate of node
    real(8),allocatable::deltaT(:)      !Temperature change of node (+: temperature zise)
    integer,allocatable::nokx(:)        !Restricted node number in x-direction
    integer,allocatable::noky(:)        !Restricted node number in y-direction
    integer,allocatable::nokz(:)        !Restricted node number in rotation direction
    real(8),allocatable::f(:)           !External force vector
    integer,allocatable::mindex(:)      !Index for treatment of restricted nodes
    real(8),allocatable::ftvec(:)       !Load vector
    real(8),allocatable::ftemp(:)       !Load vector due to temperature change
    real(8),allocatable::fmass(:)       !Load vector due to body force
    real(8),allocatable::fdis(:)        !Load vector caused by restricted nodal displacements
    real(8),allocatable::rdis(:)        !Displacement of restricted nodes
    real(8),allocatable::tsm(:,:)       !Stiffness matrix
    real(8),allocatable::dis(:)         !Nodal displacement vector
    real(8),allocatable::disr(:)        !Nodal displacement vector
    real(8),allocatable::reac(:)        !work vector
    real(8),allocatable::sm(:,:)        !Element stiffness matrix
    real(8),allocatable::hen(:,:)       !Coordinate transform matrix
    real(8),allocatable::fevec(:)       !Element nodal force matrix
    integer::nt                         !Number of degrees of freedom of all nodes (NODT x nhen)
    integer::nod=2                      !Number of nodes per element
    integer::nhen=3                     !Number of degrees of freedom per node
    integer::mm                         !Number of degrees of freedom of reduced FE equation (NODT x nhen)
    integer::ib                         !Band width of reduced matrix
    real(8)::fact0=1.0D-30              !zero judgement
    character::fnameR*50,fnameW*50      !Input file name, output file name
    integer,parameter::nnn=10
    integer::int

    character :: linebuf*1000
    character :: fmt1*200,fmt2*200,fmt3*200,fmt4*200
    real(4) :: t1,t2

    fmt1="(i5,2(',',e15.7),3(',',e15.7),3(',',i2),3(',',e15.7),',',e15.7)"    !Nodes
    fmt2="(i5,2(',',i5),8(',',e15.7),',',i5)"                                 !Elements
    fmt3="(i5,2(',',e15.7),3(',',e15.7),3(',',e15.7),3(',',e15.7))"           !Displacement & reaction
    fmt4="(i5,3(',',e15.7),3(',',e15.7),',',i5)"                              !Stress resultant

    !To input file names
    call getarg(1,fnameR) !Input file name
    call getarg(2,fnameW) !Output file name

    !To start the measurement of calculation time
    t1=DIFT()
    !***************************
    !data input
    !***************************
    open(11,file=fnameR,status='old')
    !/*--------------------------------------------------------------------------------------*/
    !/*Comment*/
    !/*--------------------------------------------------------------------------------------*/
    read(11,'(a)') strcom
    !------------------------------------------------------------------------------------------
    !Basic values for analysis
    !------------------------------------------------------------------------------------------
    read(11,*) NODT,NELT,MATEL,KOX,KOY,KOZ,NF
    !------------------------------------------------------------------------------------------
    !To declare array size
    !------------------------------------------------------------------------------------------
    nt=NODT*nhen
    allocate(kakom(1:NELT,1:nod))
    allocate(matno(1:NELT))
    allocate(noten(1:NELT))
    allocate(wm(1:NELT,1:8))
    allocate(Em(1:NELT))
    allocate(Er(1:NELT))
    allocate(AA(1:NELT))
    allocate(AI(1:NELT))
    allocate(gamma(1:NELT))
    allocate(gkh(1:NELT))
    allocate(gkv(1:NELT))
    allocate(alpha(1:NELT))
    allocate(ts(1:NELT))
    allocate(x(1:NODT))
    allocate(y(1:NODT))
    allocate(deltaT(1:NODT))
    if(1<=KOX)allocate(nokx(1:KOX))
    if(1<=KOY)allocate(noky(1:KOY))
    if(1<=KOZ)allocate(nokz(1:KOZ))
    allocate(f(1:nt))
    allocate(mindex(1:nt))
    allocate(ftvec(1:nt))
    allocate(ftemp(1:nt))
    allocate(fmass(1:nt))
    allocate(fdis(1:nt))
    allocate(rdis(1:nt))
    allocate(tsm(1:nt,1:nt))
    allocate(dis(1:nt))
    allocate(disr(1:nt))
    allocate(reac(1:nt))
    allocate(sm(1:nod*nhen,1:nod*nhen))
    allocate(hen(1:nod*nhen,1:nod*nhen))
    allocate(fevec(1:nod*nhen))
    !------------------------------------------------------------------------------------------
    !Material properties (Em,AA,AI,gamma,gkh,gkv,alpha,ts)
    !------------------------------------------------------------------------------------------
    do i=1,MATEL
        read(11,*) wm(i,1),wm(i,2),wm(i,3),wm(i,4),wm(i,5),wm(i,6),wm(i,7),wm(i,8)
    end do
    !------------------------------------------------------------------------------------------
    !Element-nodes relationship, material set No.
    !------------------------------------------------------------------------------------------
    do ne=1,NELT
        read(11,*) kakom(ne,1),kakom(ne,2),matno(ne)
        do i=1,MATEL
            if(i==matno(ne))then
                Em(ne)   =wm(i,1)
                AA(ne)   =wm(i,2)
                AI(ne)   =wm(i,3)
                gamma(ne)=wm(i,4)
                gkh(ne)  =wm(i,5)
                gkv(ne)  =wm(i,6)
                alpha(ne)=wm(i,7)
                ts(ne)   =wm(i,8)
                Er(ne)   =wm(i,1)
            end if
        end do
    end do
    deallocate(wm)
    !------------------------------------------------------------------------------------------
    !(x,y) coordinates of node, temperature change of node
    !------------------------------------------------------------------------------------------
    do i=1,NODT
        read(11,*) x(i),y(i),deltaT(i)
    end do
    !------------------------------------------------------------------------------------------
    !Restricted node number, displacement of restricted node
    !------------------------------------------------------------------------------------------
    do i=1,nt
        rdis(i)=0.0D0
    end do
    if(0<KOX)then
        do i=1,KOX
            read(11,*) nokx(i),rdis(3*nokx(i)-2)
        end do
    end if
    if(0<KOY)then
        do i=1,KOY
            read(11,*) noky(i),rdis(3*noky(i)-1)
        end do
    end if
    if(0<KOZ)then
        do i=1,KOZ
            read(11,*) nokz(i),rdis(3*nokz(i))
        end do
    end if
    !------------------------------------------------------------------------------------------
    !Loaded node number, load in x-direction, load in y-direction, moment
    !------------------------------------------------------------------------------------------
    do i=1,nt
        f(i)=0.0D0
        disr(i)=0.0D0
    end do
    if(0<NF)then
        do i=1,NF
            read(11,*) n,f(3*n-2),f(3*n-1),f(3*n)
        end do
    end if
    close(11)

    !*****************************************************
    !To print input data
    !*****************************************************
    open(12, file=fnameW, status='replace')
    write(12,'(a)') strcom
    write(12,'(a)') 'NODT,NELT,MATEL,KOX,KOY,KOZ,NF'
        write(linebuf,*) NODT,',',NELT,',',MATEL,',',KOX,',',KOY,',',KOZ,',',NF
        call del_spaces(linebuf)
    write (12,'(a)') trim(linebuf)
    write(12,'(a)') '*node characteristics'
    write(12,'(a)') 'node,x,y,fx,fy,fz,fix-x,fix-y,fix-z,rdis-x,rdis-y,rdis-z,deltaT'
    do i=1,NODT
        k=0
        l=0
        m=0
        if(0<KOX)then
            do j=1,KOX
                if(i==nokx(j))k=1
            end do
        end if
        if(0<KOY)then
            do j=1,KOY
                if(i==noky(j))l=1
            end do
        end if
        if(0<KOZ)then
            do j=1,KOZ
                if(i==nokz(j))m=1
            end do
        end if
            write(linebuf,FMT=fmt1) i,x(i),y(i),f(3*i-2),f(3*i-1),f(3*i),&
                k,l,m,rdis(3*i-2),rdis(3*i-1),rdis(3*i),deltaT(i)
            call del_spaces(linebuf)
        write (12,'(a)') trim(linebuf)
    end do
    write(12,'(a)') '*element characteristics'
    write(12,'(a)') 'element,node-1,node-2,E,A,I,gamma,kh,kv,alpha,ts,matno'
    do ne=1,NELT
            write(linebuf,FMT=fmt2) ne,kakom(ne,1),kakom(ne,2),Em(ne),AA(ne),AI(ne),&
                gamma(ne),gkh(ne),gkv(ne),alpha(ne),ts(ne),matno(ne)
            call del_spaces(linebuf)
        write (12,'(a)') trim(linebuf)
    end do
    close(12)
    !*****************************************************
    !Main calculation
    !*****************************************************
    do iii=1,nnn
        !-----------------------------------------------------
        !Initialization of matrix and vector
        !-----------------------------------------------------
        do i=1,nt
            ftemp(i)=0.D00
            fmass(i)=0.0D0
            ftvec(i)=0.0D0
            reac(i)=0.0D0
            do j=1,nt
                tsm(i,j)=0.0D0
            end do
        end do
        !-----------------------------------------------------
        !Assembling stiffness matrix and load vector
        !-----------------------------------------------------
        do ne=1,NELT
            !Stiffness matrix
            call SM_FRM(ne,kakom,x,y,Em,AA,AI,sm,hen,NELT,NODT)
            call ASMAT(ne,nod,nhen,kakom,sm,tsm,NELT,NODT)
            !Load vector due to temperature change
            call TV_FRM(ne,kakom,deltaT,Em,AA,alpha,fevec,hen,NELT,NODT)
            call ASVEC(ne,nod,nhen,kakom,fevec,ftemp,NELT,NODT)
            !Load vector due to body force
            call MV_FRM(ne,kakom,x,y,AA,gamma,gkh,gkv,fevec,NELT,NODT)
            call ASVEC(ne,nod,nhen,kakom,fevec,fmass,NELT,NODT)
        end do
        !-----------------------------------------------------
        !Load vector due to displacements of restricted nodes
        !-----------------------------------------------------
        do i=1,nt
            fdis(i)=0.0D0
            do j=1,nt
                fdis(i)=fdis(i)+rdis(j)*tsm(i,j)
            end do
        end do
        !-----------------------------------------------------
        !To set load vector
        !-----------------------------------------------------
        do i=1,nt
            ftvec(i)=f(i)+fmass(i)+ftemp(i)-fdis(i)
        end do
        !-----------------------------------------------------
        !Treatment of restricted nodes
        !-----------------------------------------------------
        do i=1,nt
            mindex(i)=i
            reac(i)=ftvec(i)
        end do
        if(0<KOX)then
            do i=1,KOX
                n=3*nokx(i)-2
                mindex(n)=0
            end do
        end if
        if(0<KOY)then
            do i=1,KOY
                n=3*noky(i)-1
                mindex(n)=0
            end do
        end if
        if(0<KOZ)then
            do i=1,KOZ
                n=3*nokz(i)
                mindex(n)=0
            end do
        end if
        mm=0
        do i=1,nt
            if(mindex(i)>0)then
                mm=mm+1
                mindex(mm)=i
            end if
        end do
        do i=1,mm
            ia=mindex(i)
            reac(i)=reac(ia)
            do j=1,mm
                ja=mindex(j)
                tsm(i,j)=tsm(ia,ja)
            end do
        end do
        !-----------------------------------------------------
        !Calculation of band width and memory of band matrix
        !-----------------------------------------------------
        ib=IBAND(mm,tsm,fact0,nt)
        call BAND(mm,ib,tsm,nt)
        !-----------------------------------------------------
        !To verify diagonal element & to stop if necessary
        !-----------------------------------------------------
        do i=1,mm
            if(abs(tsm(i,1))<fact0)stop
        end do
        !-----------------------------------------------------
        !Cholesky method
        !-----------------------------------------------------
        call CHBAND10(mm,ib,tsm,nt)!Triangle matrix
        call CHBAND11(mm,ib,tsm,reac,nt)!Forward elimination & backward substitution
        !*****************************************************
        !Calculation of stress resultants
        !*****************************************************
        do i=1,nt
            dis(i)=0.0D0
        end do
        do i=1,mm
            ia=mindex(i)
            dis(ia)=reac(i)
        end do
        do i=1,nt
            reac(i)=0.0D0
            dis(i)=dis(i)+rdis(i)
        end do
        do ne=1,NELT
            call SM_FRM(ne,kakom,x,y,Em,AA,AI,sm,hen,NELT,NODT)
            call CALST_FRM(ne,kakom,dis,sm,hen,reac,tsm,Em,AA,alpha,deltaT,NELT,NODT,nt)
        end do
        !-----------------------------------------------------
        !Judgement of No-tension
        !-----------------------------------------------------
        int=0
        do i=1,nt
            if(1.0D-6<abs(disr(i)-dis(i)))int=int+1
        end do
        write(6,*) iii,int
        do ne=1,NELT
            if(ts(ne)*AA(ne)<-tsm(ne,1))then
                Em(ne)=1.0D-6
                noten(ne)=1
            else
                Em(ne)=Er(ne)
                noten(ne)=0
            end if
        end do
        do i=1,nt
            disr(i)=dis(i)
        end do
        if(int==0)exit

    end do
    !*****************************************************
    !To print out results
    !*****************************************************
    open(12, file=fnameW, access='append')
    !Displacements of nodes
    write(12,'(a)') '*displacements and forces'
    write(12,'(a)') 'node,coord-x,coord-y,dis-x,dis-y,dis-z,reac-x,reac-y,reac-z,ftvec-x,ftvec-y,ftvec-z'
    do i=1,NODT
        write(linebuf,FMT=fmt3) i,x(i),y(i),dis(3*i-2),dis(3*i-1),dis(3*i),&
            reac(3*i-2),reac(3*i-1),reac(3*i),ftvec(3*i-2),ftvec(3*i-1),ftvec(3*i)
        call del_spaces(linebuf)
        write (12,'(a)') trim(linebuf)
    end do
    !Stress resultants
    write(12,'(a)') '*stress resultants'
    write(12,'(a)') 'element,Ni,Si,Mi,Nj,Sj,Mj,noten'
    do ne=1,NELT
        write(linebuf,FMT=fmt4) ne,tsm(ne,1),tsm(ne,2),tsm(ne,3),tsm(ne,4),tsm(ne,5),tsm(ne,6),noten(ne)
        call del_spaces(linebuf)
        write (12,'(a)') trim(linebuf)
    end do

    !To finish the measurement of calculation time
    t2=DIFT()
    write(12,'("NODT=",i0," nt=",i0," mm=",i0," ib=",i0," nnn=",i0)') ,NODT,nt,mm,ib,iii
    write(12,'("Calculation time=",f8.3,"(sec)")') t2-t1
    write(linebuf,*) 'Date_time='//trim(CALLDATE())//' (gfortran)'
    write (12,'(a)') trim(adjustl(linebuf))
    close(12)

stop

contains

    subroutine SM_FRM(ne,kakom,x,y,Em,AA,AI,sm,hen,NELT,NODT)
        !*******************************************************
        !Element stiffness matrix
        !*******************************************************
        integer,intent(in)::NELT,NODT
        integer,intent(in)::ne,kakom(1:NELT,1:2)
        real(8),intent(in)::x(1:NODT),y(1:NODT)
        real(8),intent(in)::Em(1:NELT),AA(1:NELT),AI(1:NELT)
        real(8),intent(out)::sm(1:6,1:6),hen(1:6,1:6)
        integer :: i,j
        real(8) :: AL,EA,EI,cs,sn,w(1:6,1:6)

        !Initialize of matrix
        do i=1,6
            do j=1,6
                hen(i,j)=0.0D0
                sm(i,j)=0.0D0
            end do
        end do

        !Coordinate transform matrix
        i=kakom(ne,1)
        j=kakom(ne,2)
        AL=sqrt((x(j)-x(i))**2.0D0+(y(j)-y(i))**2.0D0)
        cs=(x(j)-x(i))/AL
        sn=(y(j)-y(i))/AL
        hen(1,1)= cs
        hen(1,2)= sn
        hen(2,1)=-sn
        hen(2,2)= cs
        hen(3,3)=1.0D0
        do i=1,3
            do j=1,3
                hen(i+3,j+3)=hen(i,j)
            end do
        end do

        !Element stiffness matrix
        EA=Em(ne)*AA(ne)
        EI=Em(ne)*AI(ne)
        sm(1,1)=EA/AL
        sm(2,1)=0.0D0
        sm(3,1)=0.0D0
        sm(4,1)=-EA/AL
        sm(5,1)=0.0D0
        sm(6,1)=0.0D0
        sm(2,2)=12.0D0*EI/AL/AL/AL
        sm(3,2)=6.0D0*EI/AL/AL
        sm(4,2)=0.0D0
        sm(5,2)=-12.0D0*EI/AL/AL/AL
        sm(6,2)=6.0D0*EI/AL/AL
        sm(3,3)=4.0D0*EI/AL
        sm(4,3)=0.0D0
        sm(5,3)=-6.0D0*EI/AL/AL
        sm(6,3)=2.0D0*EI/AL
        sm(4,4)=EA/AL
        sm(5,4)=0.0D0
        sm(6,4)=0.0D0
        sm(5,5)=12.0D0*EI/AL/AL/AL
        sm(6,5)=-6.0D0*EI/AL/AL
        sm(6,6)=4.0D0*EI/AL
        do i=1,5
            do j=i+1,6
                sm(i,j)=sm(j,i)
            end do
        end do

        !Transformation to global coordinate system
        do i=1,6
            do j=1,6
                w(i,j)=0.0D0
                do k=1,6
                    w(i,j)=w(i,j)+hen(k,i)*sm(k,j)
                end do
            end do
        end do
        do i=1,6
            do j=1,6
                sm(i,j)=0.0D0
                do k=1,6
                    sm(i,j)=sm(i,j)+w(i,k)*hen(k,j)
                end do
            end do
        end do

    end subroutine SM_FRM


    subroutine MV_FRM(ne,kakom,x,y,AA,gamma,gkh,gkv,fevec,NELT,NODT)
        !*******************************************************
        !Body force vector
        !*******************************************************
        integer,intent(in)::NELT,NODT
        integer,intent(in)::ne,kakom(1:NELT,1:2)
        real(8),intent(in)::x(1:NODT),y(1:NODT)
        real(8),intent(in)::AA(1:NELT),gamma(1:NELT),gkh(1:NELT),gkv(1:NELT)
        real(8),intent(out)::fevec(1:6)
        integer :: i,j
        real(8) :: AL

        !Element length
        i=kakom(ne,1)
        j=kakom(ne,2)
        AL=sqrt((x(j)-x(i))**2.0D0+(y(j)-y(i))**2.0D0)

        !Body force vector in global coordinate system
        fevec(1)=0.5*gamma(ne)*AA(ne)*AL*gkh(ne)
        fevec(2)=0.5*gamma(ne)*AA(ne)*AL*gkv(ne)
        fevec(3)=0.0D0
        fevec(4)=0.5*gamma(ne)*AA(ne)*AL*gkh(ne)
        fevec(5)=0.5*gamma(ne)*AA(ne)*AL*gkv(ne)
        fevec(6)=0.0D0
    end subroutine MV_FRM


    subroutine TV_FRM(ne,kakom,deltaT,Em,AA,alpha,fevec,hen,NELT,NODT)
        !*******************************************************
        !Load vector due to temperature change
        !*******************************************************
        integer,intent(in)::NELT,NODT
        integer,intent(in)::ne,kakom(1:NELT,1:2)
        real(8),intent(in)::deltaT(1:NODT)
        real(8),intent(in)::Em(1:NELT),AA(1:NELT),alpha(1:NELT)
        real(8),intent(in)::hen(1:6,1:6)
        real(8),intent(out)::fevec(1:6)
        integer :: i,j
        real(8) :: tempe,work(1:6)

        i=kakom(ne,1)
        j=kakom(ne,2)
        tempe=0.5D0*(deltaT(i)+deltaT(j))
        !Load vector in local coordinate system
        work(1)=-1.0D0*Em(ne)*AA(ne)*alpha(ne)*tempe
        work(2)=0.0D0
        work(3)=0.0D0
        work(4)=1.0D0*Em(ne)*AA(ne)*alpha(ne)*tempe
        work(5)=0.0D0
        work(6)=0.0D0
        !Load vector in global coordinate system
        do i=1,6
            fevec(i)=0.0D0
            do j=1,6
                fevec(i)=fevec(i)+hen(j,i)*work(j)
            end do
        end do
    end subroutine TV_FRM


    subroutine CALST_FRM(ne,kakom,dis,sm,hen,reac,tsm,Em,AA,alpha,deltaT,NELT,NODT,nt)
        !*******************************************************
        !Calculation of stress resultant
        !*******************************************************
        integer,intent(in)::NELT,NODT,nt
        integer,intent(in)::ne,kakom(1:NELT,1:2)
        real(8),intent(in)::dis(1:nt),sm(1:6,1:6),hen(1:6,1:6)
        real(8),intent(in)::Em(1:NELT),AA(1:NELT),alpha(1:NELT),deltaT(1:NODT)
        real(8),intent(inout)::reac(1:nt)
        real(8),intent(out)::tsm(1:nt,1:nt)
        integer :: i,j,k,ia,ir,iw
        real(8) :: wd(1:6),ws(1:6),tempe

        !Nodal displacement of element in global coordinate system
        do i=1,2
            ia=kakom(ne,i)
            wd(3*i-2)=dis(3*ia-2)
            wd(3*i-1)=dis(3*ia-1)
            wd(3*i)=dis(3*ia)
        end do
        !Nodal force vector in global coordinate system
        do i=1,6
            ws(i)=0.0D0
            do k=1,6
                ws(i)=ws(i)+sm(i,k)*wd(k)
            end do
        end do
        !Stress resultant: coordinate transform matrix x nodal force vector in global coordinate system
        !(to store the suress resultants to array [tsm])
        do i=1,6
            tsm(ne,i)=0.0D0
            do k=1,6
                tsm(ne,i)=tsm(ne,i)+hen(i,k)*ws(k)
            end do
        end do
        !Correction of axial force caused by temperature change
        i=kakom(ne,1)
        j=kakom(ne,2)
        tempe=0.5D0*(deltaT(i)+deltaT(j))
        tsm(ne,1)=tsm(ne,1)+Em(ne)*AA(ne)*alpha(ne)*tempe
        tsm(ne,4)=tsm(ne,4)-Em(ne)*AA(ne)*alpha(ne)*tempe
        !Stress resultants in global coordinate system
        do i=1,6
            ws(i)=0.0D0
            do j=1,6
                ws(i)=ws(i)+hen(j,i)*tsm(ne,j)
            end do
        end do
        !To set stress resultants to global FE equation
        do i=1,2
            ia=kakom(ne,i)
            do j=1,3
                ir=3*(ia-1)+j
                iw=3*(i-1)+j
                reac(ir)=reac(ir)+ws(iw)
            end do
        end do
    end subroutine CALST_FRM


    subroutine ASVEC(ne,nod,nhen,kakom,fevec,ftvec,NELT,NODT)
        !*******************************************************
        !Assembly of vector
        !*******************************************************
        !(nod: number of nodes for 1 element, nhen: degrees of freedom of 1 node)
        integer,intent(in)::NELT,NODT
        integer,intent(in)::ne,nod,nhen
        integer,intent(in)::kakom(1:NELT,1:nod)
        real(8),intent(in)::fevec(1:nod*nhen)
        real(8),intent(inout)::ftvec(1:NODT*nhen)

        integer :: i,k,ki,ks,kik,ksk

        do i=1,nod
            ki=(kakom(ne,i)-1)*nhen
            ks=(i-1)*nhen
            do k=1,nhen
                kik=ki+k
                ksk=ks+k
                ftvec(kik)=ftvec(kik)+fevec(ksk)
            end do
        end do
    end subroutine ASVEC


    subroutine ASMAT(ne,nod,nhen,kakom,sm,tsm,NELT,NODT)
        !*******************************************************
        !Assembly of matrix
        !*******************************************************
        !(nod: number of nodes for 1 element, nhen: degrees of freedom of 1 node)
        integer,intent(in)::NELT,NODT
        integer,intent(in)::ne,nod,nhen
        integer,intent(in)::kakom(1:NELT,1:nod)
        real(8),intent(in)::sm(1:nod*nhen,1:nod*nhen)
        real(8),intent(inout)::tsm(1:NODT*nhen,1:NODT*nhen)

        integer :: i,j,k,l,ki,kj,ks,js,kik,kjl,ksk,jsl

        do i=1,nod
            do j=1,nod
                ki=(kakom(ne,i)-1)*nhen
                kj=(kakom(ne,j)-1)*nhen
                ks=(i-1)*nhen
                js=(j-1)*nhen
                do k=1,nhen
                    do l=1,nhen
                        kik=ki+k
                        kjl=kj+l
                        ksk=ks+k
                        jsl=js+l
                        tsm(kik,kjl)=tsm(kik,kjl)+sm(ksk,jsl)
                    end do
                end do
            end do
        end do
    end subroutine ASMAT


    subroutine CHBAND10(n1,m1,array,nt)
        integer,intent(in)::n1,m1,nt
        real(8),intent(inout)::array(1:nt,1:nt)
        integer :: i,j,k,mm,mn
        real(8) :: z

        array(1,1)=sqrt(array(1,1))
        do j=2,m1
            array(1,j)=array(1,j)/array(1,1)
        end do
        do i=2,n1
            if(n1-i+1>m1)then
                mm=m1
            else
                mm=n1-i+1
            end if
            do j=1,mm
                z=array(i,j)
                if(j/=m1)then
                    if(m1-j+1<i)then
                        mn=m1-j+1
                    else
                        mn=i
                    end if
                    do k=2,mn
                        z=z-array(i-k+1,k)*array(i-k+1,j+k-1)
                    end do
                    if(j>1)then
                        array(i,j)=z/array(i,1)
                    else
                        array(i,1)=sqrt(z)
                    end if
                else
                    array(i,j)=z/array(i,1)
                end if
            end do
        end do
    end subroutine CHBAND10


    subroutine CHBAND11(n1,m1,array,vector,nt)
        integer,intent(in)::n1,m1,nt
        real(8),intent(in)::array(1:nt,1:nt)
        real(8),intent(out)::vector(nt)
        integer :: i,j,mm
        real(8) :: z

        vector(1)=vector(1)/array(1,1)
        do i=2,n1
            z=vector(i)
            if(i>m1)then
                mm=m1
            else
                mm=i
            end if
            do j=2,mm
                z=z-array(i-j+1,j)*vector(i-j+1)
            end do
            vector(i)=z/array(i,1)
        end do

        vector(n1)=vector(n1)/array(n1,1)
        do i=n1-1,1,-1
            z=vector(i)
            do j=2,m1
                if(i+j-1>n1)exit
                z=z-array(i,j)*vector(i+j-1)
            end do
            vector(i)=z/array(i,1)
        end do
    end subroutine CHBAND11


    integer function IBAND(mm,array,fact0,nt)
        integer,intent(in)::mm,nt
        real(8),intent(in)::array(1:nt,1:nt),fact0
        integer :: i,j
        !-----------------------------------------------------
        !calculation of band width
        !-----------------------------------------------------
        IBAND=1
        do i=1,mm-1
            do j=mm,i+1,-1
                if(fact0<=abs(array(i,j)))exit
            end do
            if(IBAND<=j-i+1)IBAND=j-i+1
        end do
        if(mm<IBAND)IBAND=mm
    end function IBAND


    subroutine BAND(mm,ib,array,nt)
        integer,intent(in)::mm,ib,nt
        real(8),intent(inout)::array(1:nt,1:nt)
        integer :: i,j,k,mn
        real(8) :: work(1:nt)
        !-----------------------------------------------------
        !Memory of band matrix
        !-----------------------------------------------------
        do i=2,mm
            if(i+ib-1<mm)then
                mn=ib
            else
                mn=mm-i+1
            end if
            do j=1,ib
                work(j)=0.0D0
            end do
            do k=1,mn
                work(k)=array(i,i+k-1)
            end do
            do j=1,ib
                array(i,j)=work(j)
            end do
        end do
    end subroutine BAND


    subroutine del_spaces(s)
        character (*), intent (inout) :: s
        character (len=len(s)) tmp
        integer i, j
        j = 1
        do i = 1, len(s)
            if (s(i:i)==' ') cycle
            tmp(j:j) = s(i:i)
            j = j + 1
        end do
        s = tmp(1:j-1)
    end subroutine del_spaces


    real(4) function DIFT()
        integer::count,count_rate,count_max
        call system_clock(count,count_rate,count_max)
        DIFT=real(count)/real(count_rate)
    end function DIFT


    character(len=50) function CALLDATE()
        character(len=8)::date
        character(len=10)::time
        character(len=5)::zone
        integer::values(1:8)
        integer::i
        character(len=4)::ye
        character(len=4)::da
        character(len=10)::mo
        character(len=5)::ti
        character(len=10)::str
        character(len=50)::datime

        call DATE_AND_TIME(date,time,zone,values)
        ye=date(1:4)
        mo=date(5:6)
        da=date(7:8)
        ti=time(1:2)//':'//time(3:4)

        if(trim(adjustl(mo))=='01')mo='January'
        if(trim(adjustl(mo))=='02')mo='February'
        if(trim(adjustl(mo))=='03')mo='March'
        if(trim(adjustl(mo))=='04')mo='April'
        if(trim(adjustl(mo))=='05')mo='May'
        if(trim(adjustl(mo))=='06')mo='June'
        if(trim(adjustl(mo))=='07')mo='July'
        if(trim(adjustl(mo))=='08')mo='August'
        if(trim(adjustl(mo))=='09')mo='September'
        if(trim(adjustl(mo))=='10')mo='October'
        if(trim(adjustl(mo))=='11')mo='November'
        if(trim(adjustl(mo))=='12')mo='December'

        CALLDATE=trim(adjustl(da))//' '//trim(adjustl(mo))//' '//trim(adjustl(ye))//' at '//trim(adjustl(ti))
    end function CALLDATE


end program f90_FEM_FRAME
