Skip to content
Snippets Groups Projects
BallGeometry.f90 5.31 KiB
Newer Older
  • Learn to ignore specific revisions
  •       program BallGeometry
    
          implicit none
    
          integer level,i,j,nrad,nz,nradp,ip
          integer i1,i2,i3,i4,ij,k,np
          double precision x1,x2,x3,y1,y2,y3,z1,z2,z3
          double precision xne,yne,zne,xyzn
          integer nnode,nnode0,nxt,nxb,nnodemax,nelem,nelemmax,nnodep
          double precision xc,yc,zc,rad,radp,phi,theta
          double precision x,y,z,xsp,dist,pi
          double precision, dimension(:),allocatable::xp,yp,zp,xn,yn,zn
          integer,dimension(:,:),allocatable::icon
    
          pi=atan(1.)*4.
    
    ! xc yc zc is the centre of the ball
    ! rad is radius
    
          xc=.501d0
          yc=.501d0
          zc=.495d0
          xc=.5d0
          yc=.5d0
    !      zc=.9d0
          rad=.025d0
    ! reference size
          rad=.05d0
    
          level=9
    
          nz=int(2.d0**level*rad*pi)+1
          if ((nz/2)*2.eq.nz) nz=nz+1
          nnodemax=nz*nz*2
          nelemmax=nnodemax*3
    
          allocate (xp(nnodemax),yp(nnodemax),zp(nnodemax))
          allocate (xn(nnodemax),yn(nnodemax),zn(nnodemax))
          allocate (icon(3,nelemmax))
    
          nnode=0
          nelem=0
    
          ip=1
          do j=1,nz
          theta=-pi/2.+pi*float(j-1)/float(nz-1)
          radp=rad*cos(theta)
          z=rad*sin(theta)
          nrad=1+int(radp*pi*2.d0*2.d0**level)
          print*,nz,nrad
          do i=1,nrad
          phi=2.d0*pi*float(i-1)/float(nrad)
          x=radp*sin(phi)
          y=radp*cos(phi)
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
    ! bottom half
            if (j.ne.1.and.j.le.nz/2+1) then
            i1=nnode
            i2=nnode+1
            if (i.eq.nrad) i2=nnodep+nradp+1
            i3=nnodep+int((i*nradp)/nrad)+1
            ip=nnodep+int(((i-1)*nradp)/nrad)+1
            if (i3.ge.nnodep+nradp+1) i3=nnodep+1
            call add_element (nelem,icon,i1,i2,i3,nelemmax)
            if (i3.ne.ip) call add_element (nelem,icon,i1,i3,ip,nelemmax)
            ip=i3
    ! top half (minus very top)
            elseif (j.ne.1.and.j.ne.nz) then
            i1=nnode
            i2=nnode+1
            if (i.eq.nrad) i2=nnode-nrad+1
            i3=nnodep+int((i*nradp)/nrad)+1
            if (i.eq.1) i3=nnodep+2
            np=1
            if (i.ne.1) np=i3-ip
            do k=1,np
            call add_element (nelem,icon,i3-k,i1,i3-k+1,nelemmax)
            enddo
            if (i.eq.nrad) call add_element (nelem,icon,i2,nnodep+1,nnode-nrad,nelemmax)
            call add_element (nelem,icon,i1,i2,i3,nelemmax)
            ip=i3
    ! very top
            elseif (j.eq.nz) then
            do k=1,nradp
            i1=nnodep+k
            i2=i1+1
            if (i2.eq.nnode) i2=nnodep+1
            i3=nnode
            call add_element (nelem,icon,i1,i3,i2,nelemmax)
            enddo
            endif
          enddo
          nradp=nrad
          nnodep=nnode-nrad
          enddo
    
          print*,nnode,nelem
    
    !add normals
    
    112   continue
          do i=1,nelem
          i1=icon(1,i)
          i2=icon(2,i)
          i3=icon(3,i)
          if (i1.eq.i2 .or. i2.eq.i3 .or. i3.eq.i1)then
          print*,'element ',i,' collapsed: ',icon(:,i)
            do j=i+1,nelem
            icon(:,j-1)=icon(:,j)
            enddo
          nelem=nelem-1
          goto 112
          endif
          x1=xp(i1)
          x2=xp(i2)
          x3=xp(i3)
          y1=yp(i1)
          y2=yp(i2)
          y3=yp(i3)
          z1=zp(i1) 
          z2=zp(i2) 
          z3=zp(i3) 
          xne=(y2-y1)*(z3-z1)-(y3-y1)*(z2-z1)
          yne=(z2-z1)*(x3-x1)-(z3-z1)*(x2-x1)
          zne=(x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)
          xyzn=sqrt(xne**2+yne**2+zne**2)
          xne=xne/xyzn
          yne=yne/xyzn
          zne=zne/xyzn
            do j=1,3
            ij=icon(j,i)
            xn(ij)=xn(ij)+xne
            yn(ij)=yn(ij)+yne
            zn(ij)=zn(ij)+zne
            enddo
          enddo
    
          do i=1,nnode
          xyzn=sqrt(xn(i)**2+yn(i)**2+zn(i)**2)
          xn(i)=xn(i)/xyzn
          yn(i)=yn(i)/xyzn
          zn(i)=zn(i)/xyzn
          enddo
    
          xp=xp+xc
          yp=yp+yc
          zp=zp+zc
    
          open (71,file='surface-1.txt',status='unknown')
          write (71,*) nnode,nelem
            do i=1,nnode
            write (71,*) xp(i),yp(i),zp(i),xn(i),yn(i),zn(i)
            enddo
            do i=1,nelem
            write (71,*) (icon(j,i),j=1,3)
            enddo
          close (71)
    
          open(unit=30,file='Mesh.vtk')
          write(30,'(a)')'# vtk DataFile Version 3.0'
          write(30,'(a)')'surface'
          write(30,'(a)')'ASCII'
          write(30,'(a)')'DATASET UNSTRUCTURED_GRID'
          write(30,'(a7,i10,a6)')'POINTS ',nnode,' float'
          do i=1,nnode
          write(30,'(3f16.11)') xp(i),yp(i),zp(i)
          enddo
          write(30,'(A6, 2I10)') 'CELLS ',nelem,4*nelem
          do i=1,nelem
          write(30,'(9I10)')3,icon(1:3,i)-1
          enddo
          write(30,'(A11, I10)') 'CELL_TYPES ',nelem
          do i=1,nelem
          write(30,'(I2)')5 ! octree  (8 nodes)
          enddo
          write(30,'(a11,i10)')'POINT_DATA ',nnode
          write(30,'(a)')'VECTORS norm float'
          do i=1,nnode
          write(30,'(3f18.13)')xn(i),yn(i),zn(i)
          enddo
          close(30)
    
          deallocate (xp,yp,zp,icon)
    
          end
    
          !--------
    
          subroutine add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
    
          double precision xp(nnodemax),yp(nnodemax),zp(nnodemax)
          double precision x,y,z
    
          nnode=nnode+1
          if (nnode.gt.nnodemax) then
          print*,nnode,nnodemax
          stop 'needs to increase nnodemax'
          endif
    
          xp(nnode)=x
          yp(nnode)=y
          zp(nnode)=z
    
          return
          end
    
          !----------
    
          subroutine add_element (nelem,icon,i1,i2,i3,nelemmax)
    
          integer nelem,nelemmax,icon(3,nelemmax),i1,i2,i3
    
          nelem=nelem+1
          if (nelem.gt.nelemmax) then
          print*,nelem,nelemmax
          stop 'nelemmax needs to be increased'
          endif
          icon(1,nelem)=i1
          icon(2,nelem)=i2
          icon(3,nelem)=i3
    
          return
          end