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