Skip to content
Snippets Groups Projects
SubductionGeometry.f90 8.69 KiB
Newer Older
  • Learn to ignore specific revisions
  •       program SubductionGeometry
    
          implicit none
    
          integer level,nx,ny,i,j,nx1,nxs,ny1,ny2
          integer i1,i2,i3,ij,k
          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
          double precision xl1,yl1,yl2,xs,dip,length,thick,pi,zfree
          double precision x,y,z,xsp,dist,depth
          double precision, dimension(:),allocatable::xp,yp,zp,xn,yn,zn
          integer,dimension(:,:),allocatable::icon
    
          pi=atan(1.)*4.
    
    ! xl1 is where the plate starts in the x-direction;
    ! xs is where the subduction starts; dip is the dip of the subducting
    ! slab; length is it length (along the dipping plane); thick is the
    ! plate thickness; yl1 is where the plate starts in the y direction and
    ! yl2 is where it ends
    
          xl1=.4376d0
          xs=.5624d0
          dip=60.d0
          dip=dip*pi/180.d0
          thick=.01d0
          depth=.1d0
          length=(depth-thick-.0001)/sin(dip)
          yl1=.4376d0
          yl2=.5624d0
          xsp=xs-thick*tan(dip/2.d0)
          zfree=1.d0
    
          level=8
    
          nx=2**level+1
          ny=2**level+1
          nnodemax=nx*ny*2
          nelemmax=nnodemax*3
    
          allocate (xp(nnodemax),yp(nnodemax),zp(nnodemax))
          allocate (xn(nnodemax),yn(nnodemax),zn(nnodemax))
          allocate (icon(3,nelemmax))
    
          nx1=int(xl1*nx)
          ny1=int(yl1*ny)
          ny2=int(yl2*ny)
          nxs=int(nx*xs)
          nxb=int(length*nx)
          nxt=nxb+1
    
          nnode=0
          nelem=0
    
          do j=1,ny1
    ! no plate
          y=float(j-1)/float(ny1-1)*yl1
          do i=1,nx1
          x=float(i-1)/float(nx1-1)*xl1
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny1) call add_element (nelem,icon,nnode,nnode+1,nnode+2+nx,nnode+1+nx,nelemmax)
          enddo
          do i=nx1+1,nxs
          x=xl1+(xsp-xl1)*float(i-nx1)/float(nxs-nx1)
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny1) call add_element (nelem,icon,nnode,nnode+1,nnode+2+nx,nnode+1+nx,nelemmax)
          enddo
          do i=nxs,nx
          x=xs+(1.-xs)*float(i-nxs)/float(nx-nxs)
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (i.ne.nx.and.j.ne.ny1) call add_element (nelem,icon,nnode,nnode+1,nnode+2+nx,nnode+1+nx,nelemmax)
          enddo
          enddo
    
          do j=ny1,ny2
    ! no plate
          do i=1,nx1
          x=float(i-1)/float(nx1-1)*xl1
          y=yl1+float(j-ny1)/float(ny2-ny1)*(yl2-yl1)
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny2) call add_element (nelem,icon,nnode,nnode+1,nnode+5+nx+nxb+nxt,nnode+4+nx+nxb+nxt,nelemmax)
          enddo
    ! horizontal plate
          do i=nx1,nxs+1
          x=xl1+(xsp-xl1)*float(i-nx1)/float(nxs+1-nx1)
          y=yl1+float(j-ny1)/float(ny2-ny1)*(yl2-yl1)
          z=zfree-thick
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny2) call add_element (nelem,icon,nnode,nnode+1,nnode+5+nx+nxb+nxt,nnode+4+nx+nxb+nxt,nelemmax)
          if (i.ne.nxs+1.and.j.eq.ny1) call add_element (nelem,icon,nnode-2-nx,nnode-1-nx,nnode+1,nnode,nelemmax)
          if (i.ne.nxs+1.and.j.eq.ny2) call add_element (nelem,icon,nnode,nnode+1,nnode+4+nx+nxb+nxt,nnode+3+nx+nxb+nxt,nelemmax)
          enddo
    ! bottom dipping plate
          do i=1,nxb+1
          x=xsp+length*cos(dip)*float(i)/float(nxb+1)
          y=yl1+float(j-ny1)/float(ny2-ny1)*(yl2-yl1)
          z=zfree-thick-length*sin(dip)*float(i)/float(nxb+1)
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny2) call add_element (nelem,icon,nnode,nnode+1,nnode+5+nx+nxb+nxt,nnode+4+nx+nxb+nxt,nelemmax)
          if (j.eq.ny1) call add_element (nelem,icon,nnode+nxb+nxt-2*i+3,nnode+nxb+nxt-2*i+2,nnode,nnode-1,nelemmax)
          if (j.eq.ny2) call add_element (nelem,icon,nnode-1,nnode,nnode+nxb+nxt-2*i+2,nnode+nxb+nxt-2*i+3,nelemmax)
          enddo
    ! top of dipping plate
          do i=1,nxt
          x=xs+length*cos(dip)-length*cos(dip)*float(i-1)/float(nxt)
          y=yl1+float(j-ny1)/float(ny2-ny1)*(yl2-yl1)
          z=zfree-length*sin(dip)+length*sin(dip)*float(i-1)/float(nxt)
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny2) call add_element (nelem,icon,nnode,nnode+1,nnode+5+nx+nxb+nxt,nnode+4+nx+nxb+nxt,nelemmax)
          enddo
    ! no plate
          do i=nxs,nx
          x=xs+(1.-xs)*float(i-nxs)/float(nx-nxs)
          y=yl1+float(j-ny1)/float(ny2-ny1)*(yl2-yl1)
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (i.ne.nx.and.j.ne.ny2) call add_element (nelem,icon,nnode,nnode+1,nnode+5+nx+nxb+nxt,nnode+4+nx+nxb+nxt,nelemmax)
          enddo
          enddo
    
          do j=ny2,ny
    ! no plate
          y=yl2+float(j-ny2)/float(ny-ny2)*(1.-yl2)
          do i=1,nx1
          x=float(i-1)/float(nx1-1)*xl1
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny) call add_element (nelem,icon,nnode,nnode+1,nnode+2+nx,nnode+1+nx,nelemmax)
          enddo
          do i=nx1+1,nxs
          x=xl1+(xsp-xl1)*float(i-nx1)/float(nxs-nx1)
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (j.ne.ny) call add_element (nelem,icon,nnode,nnode+1,nnode+2+nx,nnode+1+nx,nelemmax)
          enddo
          do i=nxs,nx
          x=xs+(1.-xs)*float(i-nxs)/float(nx-nxs)
          z=zfree
          call add_point (nnode,x,y,z,xp,yp,zp,nnodemax)
          if (i.ne.nx.and.j.ne.ny) call add_element (nelem,icon,nnode,nnode+1,nnode+2+nx,nnode+1+nx,nelemmax)
          enddo
          enddo
    
          print*,nnode,nelem
    
          i1=1
      111 continue
          do i=i1,nnode
          do j=i+1,nnode
          dist=(xp(i)-xp(j))**2+(yp(i)-yp(j))**2+(zp(i)-zp(j))**2
          if (dist.lt.1.d-10) then
                  print*,'removing ',j
            do ij=j+1,nnode
            xp(ij-1)=xp(ij)
            yp(ij-1)=yp(ij)
            zp(ij-1)=zp(ij)
            enddo
            do ij=1,nelem
            do k=1,3
            if (icon(k,ij).eq.j) icon(k,ij)=i
            enddo
            enddo
            do ij=1,nelem
            do k=1,3
            if (icon(k,ij).gt.j) icon(k,ij)=icon(k,ij)-1
            enddo
            enddo
          nnode=nnode-1
          i1=i
          goto 111
          endif
          enddo
          enddo
    
          print*,nnode,nelem
          print*,minval(icon(:,1:nelem)),maxval(icon(:,1:nelem))
    
    !add normals
    
          do i=1,nelem
          i1=icon(1,i)
          i2=icon(2,i)
          i3=icon(3,i)
          if (i1.eq.i2 .and. i2.eq.i3) print*,'element ',i,' collapsed: ',icon(:,i)
          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
    
          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,i4,nelemmax)
    
          integer nelem,nelemmax,icon(3,nelemmax),i1,i2,i3,i4
    
          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
    
          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)=i3
          icon(3,nelem)=i4
    
          return
          end