!
!     CalculiX - A 3-dimensional finite element program
!              Copyright (C) 1998-2005 Guido Dhondt
!
!     This program is free software; you can redistribute it and/or
!     modify it under the terms of the GNU General Public License as
!     published by the Free Software Foundation(version 2);
!     
!
!     This program is distributed in the hope that it will be useful,
!     but WITHOUT ANY WARRANTY; without even the implied warranty of 
!     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
!     GNU General Public License for more details.
!
!     You should have received a copy of the GNU General Public License
!     along with this program; if not, write to the Free Software
!     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
      subroutine linkdissimilar(co,nk,ics,csab,xn,yn,zn,ncsnodes,
     &  rcscg,rcs0cg,zcscg,zcs0cg,nrcg,nzcg,jcs,kontri,straight,
     &  lcs,node1,node2,node3,ratio1,ratio2,ratio3,rp,zp,netri,
     &  nodesonaxis)
!
!     links dissimilar meshes for cyclic symmetry
!
      implicit none
!
      logical convergence,nodesonaxis
!
      integer nneigh,jcs(*),l,j,nk,ics(*),nodef(8),noder,
     &  nrcg(*),node,ncsnodes,id,nodelem(20),nnodelem,nzcg(*),
     &  ineigh(20),itrimax,lcs(*),iout(3),k,kflag,i,indexe,nope,nface,
     &  nodface,jface,netri,ntrifac,kontri(3,*),itri,node1,node2,node3
!
      real*8 co(3,*),csab(7),xn,yn,zn,xap,yap,zap,rp,zp,
     &  straight(9,*),zcscg(*),rcscg(*),zcs0cg(*),rcs0cg(*),distmax,
     &  dist,xl1,xl2,xl3,area,area1,area2,area3,dist1,dist2,
     &  dist3,ratio1,ratio2,ratio3,cgl(3),rpp,zpp
!
!     finding for each node on the right side a corresponding
!     triangle
!
      nneigh=10
!
      call near2d(rcs0cg,zcs0cg,rcscg,zcscg,nrcg,nzcg,rp,zp,
     &     netri,ineigh,nneigh)
!     
      distmax=1.d30
!     
      do j=1,nneigh
         itri=ineigh(j)
         dist=max(rp*straight(1,itri)+zp*straight(2,itri)+
     &        straight(3,itri),0.d0)+
     &        max(rp*straight(4,itri)+zp*straight(5,itri)+
     &        straight(6,itri),0.d0)+
     &        max(rp*straight(7,itri)+zp*straight(8,itri)+
     &        straight(9,itri),0.d0)
         if(dist.le.0.d0) then
            distmax=0.d0
            itrimax=itri
            exit
         endif
         if(dist.lt.distmax) then
            itrimax=itri
            distmax=dist
         endif
      enddo
!     
!     if check=0, noder lies in triangle itri, else no
!     triangle was found and the closest one is taken
!     
      if(distmax.gt.0.d0) then
!     
!     projection of the right node on the triangle
!     
         itri=itrimax
         convergence=.true.
         do j=1,3
            iout(j)=0
         enddo
!     
         do j=1,3
            dist=rp*straight(3*j-2,itri)+zp*straight(3*j-1,itri)+
     &           straight(3*j,itri)
            if(dist.gt.1.d-5) then
               convergence=.true.
               rpp=rp-dist*straight(3*j-2,itri)
               zpp=zp-dist*straight(3*j-1,itri)
               iout(j)=1
               do k=1,3
                  dist=rpp*straight(3*k-2,itri)
     &                 +zpp*straight(3*k-1,itri)
     &                 +straight(3*k,itri)
                  if(dist.gt.1.d-5) then
                     convergence=.false.
                     iout(k)=1
                  endif
               enddo
               if(convergence) then
                  rp=rpp
                  zp=zpp
                  exit
               endif
            endif
         enddo
!     
         if(.not.convergence) then
            do j=1,3
               if(iout(j).eq.0) then
                  node=kontri(j,itri)
                  xap=co(1,node)-csab(1)
                  yap=co(2,node)-csab(2)
                  zap=co(3,node)-csab(3)
!     
                  zp=xap*xn+yap*yn+zap*zn
                  rp=dsqrt((xap-zp*xn)**2+(yap-zp*yn)**2+
     &                 (zap-zp*zn)**2)
               endif
            enddo
         endif
      endif
!     
!     nodes belonging to the triangle
!     
      node1=kontri(1,itri)
      node2=kontri(2,itri)
      node3=kontri(3,itri)
!     
!     length of the edges of the triangle
!     
      xl1=dsqrt((co(1,node3)-co(1,node2))**2+
     &     (co(2,node3)-co(2,node2))**2+
     &     (co(3,node3)-co(3,node2))**2)
      xl2=dsqrt((co(1,node1)-co(1,node3))**2+
     &     (co(2,node1)-co(2,node3))**2+
     &     (co(3,node1)-co(3,node3))**2)
      xl3=dsqrt((co(1,node2)-co(1,node1))**2+
     &     (co(2,node2)-co(2,node1))**2+
     &     (co(3,node2)-co(3,node1))**2)
!     
!     distance from noder to the edges
!     
      dist1=max(0.d0,-(rp*straight(1,itri)+zp*straight(2,itri)+
     &     straight(3,itri)))
      dist2=max(0.d0,-(rp*straight(4,itri)+zp*straight(5,itri)+
     &     straight(6,itri)))
      dist3=max(0.d0,-(rp*straight(7,itri)+zp*straight(8,itri)+
     &     straight(9,itri)))
!     
!     area of triangle parts (apart from factor of 2)
!     different treatment if node on axis belongs to triangle
!     
      if(nodesonaxis) then
         call nident(jcs,node1,ncsnodes,id)
         if(ics(lcs(id)).lt.0) then
            area1=0.d0
         else
            area1=dist1*xl1
         endif
         call nident(jcs,node2,ncsnodes,id)
         if(ics(lcs(id)).lt.0) then
            area2=0.d0
         else
            area2=dist2*xl2
         endif
         call nident(jcs,node3,ncsnodes,id)
         if(ics(lcs(id)).lt.0) then
            area3=0.d0
         else
            area3=dist3*xl3
         endif
      else
         area1=dist1*xl1
         area2=dist2*xl2
         area3=dist3*xl3
      endif
      area=area1+area2+area3
!     
!     coefficients of the mpc's
!     
      ratio1=area1/area
      ratio2=area2/area
      ratio3=area3/area
!     
      return
      end
      
