Add scripts and inp files.

This commit is contained in:
James Grogan 2024-05-13 20:50:21 +01:00
parent ad937f2602
commit e19f869a1e
390 changed files with 6580687 additions and 10 deletions

View file

@ -0,0 +1,31 @@
# Python Preprocessor Script for Abaqus Corrosion Model
# J. Grogan, D. Gastaldi - Created. 19-07-11
# Import abaqus modules
from abaqusConstants import *
from abaqus import *
import random
# Create Model, Assembly and Instance objects
modelNames=mdb.models.keys()
corModel=mdb.models[modelNames[0]]
corAssembly=corModel.rootAssembly
corSurf=corAssembly.surfaces['Corrode']
surfFaces=corSurf.faces
incFile=open('CorSurf.dat','w')
for i in range(0,len(surfFaces)):
eachFace=surfFaces[i]
elemFaces=eachFace.getElementFaces()
for j in range(0,len(elemFaces)):
eachElemFace=elemFaces[j]
faceNodes=eachElemFace.getNodes()
centx=0.
centy=0.
centz=0.
for k in range(0,len(faceNodes)):
centx=centx+faceNodes[k].coordinates[0]
centy=centy+faceNodes[k].coordinates[1]
centz=centz+faceNodes[k].coordinates[2]
centx=centx/float(len(faceNodes))
centy=centy/float(len(faceNodes))
centz=centz/float(len(faceNodes))
incFile.write ("%f %f %f \n"%(centx,centy,centz))
incFile.close()

View file

@ -0,0 +1,193 @@
! This program generates a micro-strucutre mask and applies it to
! an existing mesh.
! J.Grogan 05/08/11
program Voronoi3DPost
!
! Parameters
parameter(max_elements=100000,max_cells=20000,max_fc=100)
parameter(max_elem_in_cell=50000,max_neigh_per_elem=6,max_neighbours=50)
!
! Variables
character(len=256)input
character(len=256)input2(2)
integer num_neighbours(100000),neighbour(100000,max_neighbours)
real nbr_dist(100000,max_neighbours)
real cor_faces(100000,3),cor_dist(100000)
double precision,allocatable,dimension(:,:)::ele_centroid
!
allocate(ele_centroid(max_elements,3))
mesh_type=3
call elem_centroids(num_elements,ele_centroid,mesh_type)
rmax_dist=0.020
neighbour=0
!
! Get neighbouring elements
do i=1,num_elements
icount=1
do j=1,num_elements
if(icount>max_neighbours)then
rmaxdist=0.
do k=1,max_neighbours
if(nbr_dist(i,k)>rmaxdist)then
rmaxdist=nbr_dist(i,k)
index_max_dist=k
endif
enddo
endif
cent1x=ele_centroid(i,1)
cent1y=ele_centroid(i,2)
cent1z=ele_centroid(i,3)
cent2x=ele_centroid(j,1)
cent2y=ele_centroid(j,2)
cent2z=ele_centroid(j,3)
dist=sqrt((cent1x-cent2x)*(cent1x-cent2x)+(cent1y-cent2y)*(cent1y-cent2y)&
&+(cent1z-cent2z)*(cent1z-cent2z))
if(icount>max_neighbours)then
if(dist<rmaxdist)then
nbr_dist(i,index_max_dist)=dist
neighbour(i,index_max_dist)=j
endif
else
nbr_dist(i,j)=dist
neighbour(i,j)=j
endif
icount=icount+1
enddo
! print *,float(i)/float(num_elements)
enddo
!
! Get corrosion surface distances
open(unit=20,file='CorSurf.dat',status='unknown')
read(20,*)num_faces
ierr=0
num_faces=1
do while (ierr==0)
read(20,*,iostat=ierr)cor_faces(num_faces,1),cor_faces(num_faces,2),&
&cor_faces(num_faces,3)
if(ierr==0)num_faces=num_faces+1
enddo
close(unit=20)
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
distmin=1000.
do j=1,num_faces-1
facex=cor_faces(j,1)
facey=cor_faces(j,2)
facez=cor_faces(j,3)
dist=sqrt((centx-facex)*(centx-facex)+(centy-facey)*(centy-facey)&
&+(centz-facez)*(centz-facez))
if(dist<distmin)distmin=dist
enddo
cor_dist(i)=distmin
enddo
! Write New Input File
rewind(10)
open(unit=13,file='Corrosion.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(13,'(a)')'*End Assembly'
write(13,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
do i=1,num_elements
write(13,'(3(a,i6),2(a,f18.6),3(i6,a))')'Assembly.CorPart.',i,',',i,',',&
& max_neighbours,',',0.,',',cor_dist(i),0,',',0,',',0,','
write(13,'(8(i6,a))')0,',',0,',',0,',',0,',',0,',',0,',',0,',',1,','
do j=1, max_neighbours
if(mod(j,8)/=0)then
if(j/=max_neighbours)then
write(13,'(i6,a)',advance='no')neighbour(i,j),','
else
write(13,'(i6)')neighbour(i,j)
endif
else
if(j/=max_neighbours)then
write(13,'(i6,a)')neighbour(i,j),','
else
write(13,'(i6)')neighbour(i,j)
endif
endif
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(13,'(a)')input2(1)
enddo
end program
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Get Element Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine elem_centroids(ne,ele_centroid,mesh_type)
!
! Parameters
parameter(max_nodes=1000000,max_elements=100000,max_node_in_elem=8)
!
! Variables
character(len=256)input
integer,dimension(max_elements,max_node_in_elem)::elements
double precision,dimension(max_nodes,3)::nodes
double precision,dimension(max_elements,3)::ele_centroid
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='Corrosion_Temp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
if(mesh_type==3)then
read(10,*)dummy,nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
read(10,*)dummy,nodes(nn,1),nodes(nn,2)
endif
else
if(mesh_type==2)then
nele_type=4
else
if(index(input,'C3D8')/=0)nele_type=8
if(index(input,'C3D4')/=0)nele_type=4
endif
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
if(nele_type==8)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
elseif(nele_type==4)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)
endif
else
exit
endif
end do
!
! Get element centroid
do i=1,ne
centroidx=0.d0
centroidy=0.d0
centroidz=0.d0
do j=1,nele_type
centroidx=centroidx+nodes(elements(i,j),1)
centroidy=centroidy+nodes(elements(i,j),2)
if(mesh_type==3)centroidz=centroidz+nodes(elements(i,j),3)
enddo
ele_centroid(i,1)=centroidx/float(nele_type)
ele_centroid(i,2)=centroidy/float(nele_type)
if(mesh_type==3)ele_centroid(i,3)=centroidz/float(nele_type)
enddo
end subroutine

View file

@ -0,0 +1,164 @@
# GrainGen V2.0
# This script generates idealised and representative meshed micro-structure geometries
# in 2-D and 3-D through the Abaqus geometry kernel. - J. Grogan, 09/06/2011
#
# Import Abaqus and External Modules
from abaqusConstants import *
from abaqus import *
import random
import subprocess
import regionToolset
import mesh
import step
import part
import interaction
import GeomModules
#
# Create Model Database
VerFile=Mdb(pathName="MStructure")
VerModel=VerFile.models['Model-1']
VerAssembly=VerModel.rootAssembly
#
# Assign Model Parameters
shape=4 # 1 - Square, 2- Hex, 3 -Dodec, 4- Voronoi
part_type=2 # 2 - Shell, 3 - Solid
dimension=2 # 2 - 2D, 3 - 3D
rad=0.00595 # Characteristic Dimension (except Voronoi)
meshsize=0.0005 # Global Mesh Seed Size
num_high=16 # Number of Grains in X-Dir
num_wide=6 # Number of Grains in Y-Dir
num_thick=1 # Number of Grains in Z-Dir
num_grains=25 # Target Number of Grains (Voronoi Only)
scalex=1. # Voronoi Part Scale X-Dir (Voronoi Only)
scaley=3.5 # Voronoi Part Scale Y-Dir (Voronoi Only)
scalez=1. # Voronoi Part Scale Z-Dir (Voronoi Only)
ana_type=1 # 1 - Crystal Plasticity, 2 - Corrosion
hard_rad=0.0 # Hardcore voronoi min. radius (Voronoi Only)
random_seed=92271 # Random seed for voronoi grain generation or random vector generation
#
# Choose Script Function - Set to 1 to activate
assemble_grains = 1 # Assemble Multiple Grains and Merge Them
boolean_cut = 1 # Perform Boolean Cut Operation
mesh_part = 1 # Mesh the Final Geometry
mat_props = 1 # Assign Material Properties
bound_conds = 1 # Generate steps and apply BCs
write_output =1 # Write Output File
post_proc = 0 # Postprocess INP file (Corrosion Only)
#
# For 2-D Solids thickness is set equal to one element
if dimension==3:
extrude_depth=rad
else:
extrude_depth=meshsize
num_thick=1
#
# Draw a Square Grain
if shape==1:
GeomModules.DrawSquare(VerModel,part_type,rad,extrude_depth)
#
# Draw a Hexagonal Grain
if shape==2:
GeomModules.DrawHexagon(VerModel,part_type,rad,extrude_depth)
#
# Draw a Dodecahedral Grain
if shape==3:
GeomModules.DrawDodec(VerModel,rad)
#
# Draw a Voronoi Tessellation
if shape==4:
if dimension==2:
maxsize=max(scalex,scaley)
GeomModules.Voronoi2D(VerModel,part_type,extrude_depth,num_grains,maxsize,hard_rad,random_seed)
else:
maxsize=max(scalex,scaley,scalez)
GeomModules.Voronoi3D(VerModel,num_grains,maxsize,hard_rad,random_seed)
#
# Assemble Base Parts
if assemble_grains==1:
if shape<=3:
VerPart=VerModel.parts['Base']
GeomModules.PatternParts(num_high,num_wide,num_thick,VerPart,rad,shape,VerModel)
#
# Make a Boolean Template
if boolean_cut==1:
if shape>1:
GeomModules.BooleanPart(VerModel,part_type,rad,extrude_depth,num_high,
num_wide,num_thick,shape,dimension,scalex,scaley,scalez)
BoolPart=VerModel.parts['Template']
#
#Perform Boolean Cut
if shape==1:
VerPart=VerModel.parts['Merged']
del VerAssembly.instances['Merged-1']
else:
VerAssembly.InstanceFromBooleanCut(name='FinalPart',
instanceToBeCut=VerAssembly.instances['Merged-1'],
cuttingInstances=(VerAssembly.instances['Template-1'], ),
originalInstances=DELETE)
del VerAssembly.instances['FinalPart-1']
VerPart=VerModel.parts['FinalPart']
#
# Mesh Part
if mesh_part==1:
if shape<3:
VerPart.setMeshControls(regions=VerPart.cells, elemShape=HEX, technique=STRUCTURED)
if shape==3:
VerPart.setMeshControls(regions=VerPart.cells, elemShape=TET, technique=FREE)
if shape==4:
if dimension==2:
VerPart.setMeshControls(regions=VerPart.cells, elemShape=HEX, technique=SWEEP,
algorithm=ADVANCING_FRONT)
else:
VerPart.setMeshControls(regions=VerPart.cells, elemShape=TET, technique=FREE)
VerPart.seedPart(size=meshsize)
VerPart.generateMesh()
#
# For Corrosion Analysis Output Part Vertices and Element Connectivity
if ana_type==2:
GeomModules.VertsConn(VerPart,dimension)
ecor=open('ecor.dat','w')
for eachface in VerPart.faces:
if len(eachface.getAdjacentFaces())<7.:
xnor=eachface.getNormal()[0]
ynor=eachface.getNormal()[1]
znor=eachface.getNormal()[2]
if (xnor==0.)and(znor==0.):
# if (ynor==1.)or(ynor==-1.):
if (ynor==1.):
ecor.write("%6.4f %6.4f %6.4f\n"%(xnor,ynor,znor))
ecor.close()
#
#Generate Materials and Sections
if mat_props==1:
GeomModules.MatGen(ana_type,VerPart,VerModel,part_type,meshsize,random_seed)
#
#Steps and Boundary Conditions
if bound_conds==1:
VerModel.ExplicitDynamicsStep(name='Corrode', previous='Initial',
massScaling=((SEMI_AUTOMATIC, MODEL, AT_BEGINNING, 0.0, 1e-06,
BELOW_MIN, 0, 0, 0.0, 0.0, 0, None), ))
VerModel.ExplicitDynamicsStep(name='Load', previous='Corrode',
timePeriod=1.)
VerModel.steps['Corrode'].Restart(numberIntervals=2,overlay=OFF,timeMarks=OFF)
VerModel.steps['Load'].Restart(numberIntervals=2,overlay=OFF, timeMarks=OFF)
VerModel.FieldOutputRequest(name='F-Output-1',
createStepName='Corrode', variables=('A', 'CSTRESS', 'LE', 'PE',
'PEEQ', 'RF', 'S', 'SDV', 'STATUS', 'U','V'), numIntervals=100)
#
#Loads and BCs
VerAssembly.Instance(name='CorPart',part=VerPart, dependent=ON)
iNodes=VerAssembly.instances['CorPart'].nodes
# GeomModules.S1BCs(iNodes,VerModel,num_high,num_wide,num_thick,shape,
# dimension,extrude_depth,rad,scalex,scaley,scalez)
#
#VerAssembly.Instance(name='CorPart',part=VerPart, dependent=ON)
#Create Job and write input file
if write_output ==1:
VerFile.Job(name='GeomGenTemp', model='Model-1', type=ANALYSIS,
explicitPrecision=SINGLE, nodalOutputPrecision=SINGLE,userSubroutine='',
parallelizationMethodExplicit=DOMAIN,numDomains=1,multiprocessingMode=DEFAULT, numCpus=1)
VerFile.jobs['GeomGenTemp'].writeInput(consistencyChecking=OFF)
#
# Perform Postprocessing for corrosion analysis
if post_proc ==1:
retcode=subprocess.call("GeomGenPost2.exe")

View file

@ -0,0 +1,173 @@
!This program calculates the distance from each element
!to its nearest grain boundary
Program GeomConnectivity
!
! Parameters
parameter(max_nodes=1000000,max_elements=1000000,max_node_in_elem=8)
parameter(max_cells=1000,max_elem_in_cell=10000,max_neigh_per_elem=6)
parameter(max_faces_in_cell=100)
!
! Declare Variables
character*256 input,input2(2)
integer elements(max_elements,max_node_in_element)
integer active(max_elements)
integer num_elements(max_cells)
integer elem_label=(max_cells,max_elem_in_cell)
integer num_neighbours=(max_cells,max_elem_in_cell)
integer elem_neighbours=(max_cells,max_elem_in_cell,max_neigh_per_elem)
integer num_faces(max_cells)
real nodes(max_nodes,3)
real face_coords(max_cells,max_faces_in_cell,9)
real dotprod(max_node_in_element,max_faces_in_cell)
real average(max_faces_in_cell)
real distance(max_cells,max_elem_in_cell)
!
! Initialise Variables
nodes=0.
face_coords=0.
dotprod=0.
average=0.
distance=0.
elements=0
active=0
num_elements=0
elem_label=0
num_neighbours=0
elem_neighbours=0
num_faces=0
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='GeomGenTemp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
read(10,*)nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
else
exit
endif
end do
!
! Open GeomGen output file and read element connectivity, cell, face and
! vertice data.
open(unit=11,file='vertout.dat',status='old')
read(11,*)idimension
read(11,*)num_cells
do i=1,num_cells
read(11,*)num_elements(i)
do j=1,num_elements(i)
read(11,*)elem_label(i,j)
read(11,*)num_neighbours(i,j)
do k=1,num_neighbours(i,j)
read(11,*)elem_neighbours(i,j,k)
enddo
enddo
read(11,*)num_faces(i)
do j=1,num_faces(i)
read(11,*)face_coords(i,j,1),face_coords(i,j,2),face_coords(i,j,3)
read(11,*)face_coords(i,j,4),face_coords(i,j,5),face_coords(i,j,6)
read(11,*)face_coords(i,j,7),face_coords(i,j,8),face_coords(i,j,9)
enddo
enddo
!
! Determine normal distance between element centroid and closest face
do i=1,num_cells
do j=1,num_elements(i)
do k=1,8
nodex=nodes(elements(elem_label(i,j),k),1)
nodey=nodes(elements(elem_label(i,j),k),2)
nodez=nodes(elements(elem_label(i,j),k),3)
do m=1,num_faces(i)
vert1x=face_coords(i,m,1)
vert1y=face_coords(i,m,1)
vert1z=face_coords(i,m,1)
vert2x=face_coords(i,m,2)
vert2y=face_coords(i,m,2)
vert2z=face_coords(i,m,2)
vert3x=face_coords(i,m,3)
vert3y=face_coords(i,m,3)
vert3z=face_coords(i,m,3)
v1v2i=vert1x-vert2x
v1v2j=vert1y-vert2y
v1v2k=vert1z-vert2z
v1v3i=vert1x-vert3x
v1v3j=vert1y-vert3y
v1v3k=vert1z-vert3z
v1ni=vert1x-nodex
v1nj=vert1y-nodey
v1nk=vert1z-nodez
crossi=v1v2j*v1v3k-v1v2k*v1v3j
crossj=v1v2k*v1v3i-v1v2i*v1v3k
crossk=v1v2i*v1v3j-v1v2j*v1v3i
dotprod(k,m)=v1ni*crossi+v1nj*crossj+v1nk*crossk
enddo
enddo
min_average=1000.
do m=1,num_faces(i)
average(m)=0.
do k=1,8
average(m)=average(m)+dotprod(k,m)
enddo
average(m)=average(m)/8.
if(average(m)<min_average)min_average=average(m)
enddo
distance(i,j)=min_average
enddo
enddo
!
! Copy new data into updated input file
rewind(unit=10)
open(unit=12,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(12,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(12,'(a)')'*End Assembly'
write(12,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
open(unit=13,file='ecor.dat',status='old')
active=0
ierr=0
do while (ierr==0)
read(13,*,iostat=ierr)ielnum
if(ierr==0)active(ielnum)=1
enddo
do i=1,num_cells
do j=1,num_elements(i)
write(12,'(a,8(i6,a))')'Assembly.CorPart.',elem_label(i,j),',',elem_neighbours(i,j,1),&
& ',',elem_neighbours(i,j,2),',',elem_neighbours(i,j,3),',',elem_neighbours(i,j,4),&
& ',',elem_neighbours(i,j,5),',',elem_neighbours(i,j,6),',',0,','
write(12,'(2(i6,a),f18.6,a,5(i6,a))')elem_label(i,j),',',active(elem_label(i,j)),',',&
& distance(i,j),',',0,',',0,',',0,',',0,',',0,','
write(12,'(8(i6,a))')0,',',0,',',0,',',0,',',1,',',0,',',0,',',0,','
write(12,'(6(i6,a),f18.6)')0,',',0,',',0,',',0,',',0,',',0,',',0.
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(12,'(a)')input2(1)
enddo
close(unit=10)
close(unit=11)
close(unit=12)
close(unit=13)
End Program

View file

@ -0,0 +1,190 @@
!This program calculates the distance from each element
!to its nearest grain boundary
Program GeomGenPost
!
! Parameters
parameter(max_nodes=1000000,max_elements=1000000,max_node_in_elem=8)
parameter(max_cells=1000,max_elem_in_cell=10000,max_neigh_per_elem=6)
parameter(max_faces_in_cell=100)
!
! Declare Variables
character*256 input,input2(2)
integer elements(max_elements,max_node_in_elem)
integer active(max_elements)
integer num_elements(max_cells)
integer elem_label(max_cells,max_elem_in_cell)
integer num_neighbours(max_cells,max_elem_in_cell)
integer elem_neighbours(max_cells,max_elem_in_cell,max_neigh_per_elem)
integer num_faces(max_cells)
integer fstatus(max_cells,max_faces_in_cell)
real nodes(max_nodes,3)
real fnorm(max_cells,max_faces_in_cell,3)
real fpoint(max_cells,max_faces_in_cell,3)
real dotprod(max_node_in_elem,max_faces_in_cell)
real average(max_faces_in_cell)
real distance(max_cells,max_elem_in_cell)
!
! Initialise Variables
nodes=0.
fnorm=0.
fpoint=0.
dotprod=0.
average=0.
distance=0.
elements=0
active=0
num_elements=0
elem_label=0
num_neighbours=0
elem_neighbours=0
num_faces=0
fstatus=0
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='GeomGenTemp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
read(10,*)dummy,nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
if(index(input,'C3D8')/=0)nele_type=8
if(index(input,'C3D4')/=0)nele_type=4
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
if(nele_type==8)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
elseif(nele_type==4)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)
endif
else
exit
endif
end do
!
! Open GeomGen output file and read element connectivity, cell, face and
! vertice data.
open(unit=11,file='vertout.dat',status='old')
read(11,*)idimension
read(11,*)num_cells
do i=1,num_cells
read(11,*)num_elements(i)
do j=1,num_elements(i)
read(11,*)elem_label(i,j)
read(11,*)num_neighbours(i,j)
do k=1,num_neighbours(i,j)
read(11,*)elem_neighbours(i,j,k)
enddo
enddo
read(11,*)num_faces(i)
do j=1,num_faces(i)
read(11,*)vert1x,vert1y,vert1z
read(11,*)vert2x,vert2y,vert2z
read(11,*)vert3x,vert3y,vert3z
v1v2i=vert1x-vert2x
v1v2j=vert1y-vert2y
v1v2k=vert1z-vert2z
v1v3i=vert1x-vert3x
v1v3j=vert1y-vert3y
v1v3k=vert1z-vert3z
crossi=v1v2j*v1v3k-v1v2k*v1v3j
crossj=v1v2k*v1v3i-v1v2i*v1v3k
crossk=v1v2i*v1v3j-v1v2j*v1v3i
cmag=sqrt(crossi*crossi+crossj*crossj+crossk*crossk)
fnorm(i,j,1)=crossi/cmag
fnorm(i,j,2)=crossj/cmag
fnorm(i,j,3)=crossk/cmag
fpoint(i,j,1)=vert1x
fpoint(i,j,2)=vert1y
fpoint(i,j,3)=vert1z
if(idimension==2)then
if(int(fnorm(i,j,1))==0.and.int(fnorm(i,j,2))==0.and.int(abs(fnorm(i,j,3)))==1)then
fstatus(i,j)=1
endif
endif
enddo
enddo
!
! Determine normal distance between element centroid and closest face
do i=1,num_cells
do j=1,num_elements(i)
do k=1,nele_type
rnodex=nodes(elements(elem_label(i,j),k),1)
rnodey=nodes(elements(elem_label(i,j),k),2)
rnodez=nodes(elements(elem_label(i,j),k),3)
do m=1,num_faces(i)
if(fstatus(i,m)/=1)then
v1ni=fpoint(i,m,1)-rnodex
v1nj=fpoint(i,m,2)-rnodey
v1nk=fpoint(i,m,3)-rnodez
dotprod(k,m)=v1ni*fnorm(i,m,1)+v1nj*fnorm(i,m,2)+v1nk*fnorm(i,m,3)
endif
enddo
enddo
rmin_average=1000.
do m=1,num_faces(i)
if(fstatus(i,m)/=1)then
average(m)=0.
do k=1,nele_type
average(m)=average(m)+abs(dotprod(k,m))
enddo
average(m)=average(m)/float(nele_type)
if(average(m)<rmin_average)rmin_average=average(m)
endif
enddo
distance(i,j)=rmin_average
enddo
enddo
!
! Copy new data into updated input file
rewind(unit=10)
open(unit=12,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(12,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(12,'(a)')'*End Assembly'
write(12,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
open(unit=13,file='ecor.dat',status='old')
active=0
ierr=0
do while (ierr==0)
read(13,*,iostat=ierr)ielnum
if(ierr==0)active(ielnum)=1
enddo
do i=1,num_cells
do j=1,num_elements(i)
write(12,'(a,8(i6,a))')'Assembly.CorPart.',elem_label(i,j),',',elem_neighbours(i,j,1),&
& ',',elem_neighbours(i,j,2),',',elem_neighbours(i,j,3),',',elem_neighbours(i,j,4),&
& ',',elem_neighbours(i,j,5),',',elem_neighbours(i,j,6),',',0,','
write(12,'(2(i6,a),f18.6,a,5(i6,a))')elem_label(i,j),',',active(elem_label(i,j)),',',&
& distance(i,j),',',0,',',0,',',0,',',0,',',0,','
write(12,'(8(i6,a))')0,',',0,',',0,',',0,',',1,',',0,',',0,',',0,','
write(12,'(6(i6,a),f18.6)')0,',',0,',',0,',',0,',',0,',',0,',',0.
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(12,'(a)')input2(1)
enddo
close(unit=10)
close(unit=11)
close(unit=12)
close(unit=13)
End Program

View file

@ -0,0 +1,74 @@
!This program calculates the distance from each element
!to its nearest grain boundary
Program GeomGenPost
!
! Parameters
parameter(max_elements=1000000)
parameter(max_neigh_per_elem=6)
!
! Declare Variables
character*256 input,input2(2)
integer active(max_elements)
integer cellstat(max_elements)
integer elem_neighbours(max_neigh_per_elem)
!
! Initialise Variables
active=0
elem_neighbours=0
!
! Copy new data into updated input file
open(unit=10,file='GeomGenTemp.inp',status='unknown')
open(unit=12,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(12,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(12,'(a)')'*End Assembly'
write(12,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
open(unit=13,file='ecor.dat',status='old')
active=0
ierr=0
do while (ierr==0)
read(13,*,iostat=ierr)ielnum
if(ierr==0)active(ielnum)=1
enddo
open(unit=14,file='testout.dat',status='old')
ierr=0
do while (ierr==0)
read(13,*,iostat=ierr)ielnum,icell
if(ierr==0)cellstat(ielnum)=icell
enddo
! Open GeomGen output file and read element connectivity, cell, face and
! vertice data.
open(unit=11,file='vertout.dat',status='old')
read(11,*)num_cells
do i=1,num_cells
read(11,*)num_elements
do j=1,num_elements
read(11,*)ielem_label
read(11,*)num_neighbours
do k=1,num_neighbours
read(11,*)elem_neighbours(k)
enddo
read(11,*)distance
write(12,'(a,8(i6,a))')'Assembly.CorPart.',ielem_label,',',elem_neighbours(1),&
& ',',elem_neighbours(2),',',elem_neighbours(3),',',elem_neighbours(4),&
& ',',elem_neighbours(5),',',elem_neighbours(6),',',0,','
write(12,'(2(i6,a),f18.6,a,5(i6,a))')ielem_label,',',active(elem_label),',',&
& distance,',',cellstat(ielem_label),',',0,',',0,',',0,',',0,','
write(12,'(8(i6,a))')0,',',0,',',0,',',0,',',1,',',0,',',0,',',0,','
write(12,'(6(i6,a),f18.6)')0,',',0,',',0,',',0,',',0,',',0,',',0.
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(12,'(a)')input2(1)
enddo
close(unit=10)
close(unit=11)
close(unit=12)
close(unit=13)
End Program

View file

@ -0,0 +1,847 @@
# Draw a Square Grain
#
def DrawSquare(VerModel,part_type,rad,extrude_depth):
from abaqusConstants import *
from abaqus import *
label='Base'
if part_type==3:
VerPart=VerModel.Part(name=label, dimensionality=THREE_D,type=DEFORMABLE_BODY)
else:
VerPart=VerModel.Part(name=label, dimensionality=TWO_D_PLANAR,type=DEFORMABLE_BODY)
VerPart.DatumPointByCoordinate((0,0,0))
VerPart.DatumPointByCoordinate((1,0,0))
VerPart.DatumPointByCoordinate((0,1,0))
pdatums=VerPart.datums
VerPart.DatumPlaneByThreePoints(point1=pdatums[1], point2=pdatums[2], point3=pdatums[3])
VerPart.DatumAxisByTwoPoint(point1=pdatums[1],point2=pdatums[2])
partTransform = VerPart.MakeSketchTransform(sketchPlane=pdatums[4], sketchUpEdge=pdatums[5],
sketchPlaneSide=SIDE1, sketchOrientation=BOTTOM, origin=(0,0,0))
VerSketch = VerModel.ConstrainedSketch(name=label,sheetSize=200, transform=partTransform)
VerSketch.Line(point1=(0.,0.),point2=(rad,0.))
VerSketch.Line(point1=(rad,0.),point2=(rad,rad))
VerSketch.Line(point1=(rad,rad),point2=(0.,rad))
VerSketch.Line(point1=(0.,rad),point2=(0.,0.))
if part_type==3:
VerPart.BaseSolidExtrude(sketch=VerSketch,depth=extrude_depth)
else:
VerPart.BaseShell(sketch=VerSketch)
# Draw a Hexagonal Grain
#
def DrawHexagon(VerModel,part_type,rad,extrude_depth):
from abaqusConstants import *
from abaqus import *
label='Base'
VerAssembly=VerModel.rootAssembly
if part_type==3:
VerPart=VerModel.Part(name=label, dimensionality=THREE_D,type=DEFORMABLE_BODY)
else:
VerPart=VerModel.Part(name=label, dimensionality=TWO_D_PLANAR,type=DEFORMABLE_BODY)
VerPart.DatumPointByCoordinate((0,0,0))
VerPart.DatumPointByCoordinate((1,0,0))
VerPart.DatumPointByCoordinate((0,1,0))
pdatums=VerPart.datums
VerPart.DatumPlaneByThreePoints(point1=pdatums[1], point2=pdatums[2], point3=pdatums[3])
VerPart.DatumAxisByTwoPoint(point1=pdatums[1],point2=pdatums[2])
partTransform = VerPart.MakeSketchTransform(sketchPlane=pdatums[4], sketchUpEdge=pdatums[5],
sketchPlaneSide=SIDE1, sketchOrientation=BOTTOM, origin=(0,0,0))
VerSketch = VerModel.ConstrainedSketch(name=label,sheetSize=200, transform=partTransform)
yheight=sin(radians(30.))
xheight=cos(radians(30.))
VerSketch.Line(point1=(0.,0.),point2=(rad*xheight,rad*yheight))
VerSketch.Line(point1=(rad*xheight,rad*yheight),point2=(rad*xheight,rad*yheight+rad))
VerSketch.Line(point1=(rad*xheight,rad*yheight+rad),point2=(0.,2.*rad*yheight+rad))
VerSketch.Line(point1=(0.,2.*rad*yheight+rad),point2=(-rad*xheight,rad*yheight+rad))
VerSketch.Line(point1=(-rad*xheight,rad*yheight+rad),point2=(-rad*xheight,rad*yheight))
VerSketch.Line(point1=(-rad*xheight,rad*yheight),point2=(0.,0.))
if part_type==3:
VerPart.BaseSolidExtrude(sketch=VerSketch,depth=extrude_depth)
else:
VerPart.BaseShell(sketch=VerSketch)
BasePart=VerModel.parts['Base']
BasePartCells = BasePart.cells
BasePartFaces = BasePart.faces
BasePartVerts = BasePart.vertices
if part_type==3:
BasePart.PartitionCellByPlaneThreePoints(point1=BasePartVerts[4], point2=BasePartVerts[10],
point3=BasePartVerts[11], cells=BasePartCells)
else:
BasePart.PartitionFaceByShortestPath(point1=BasePartVerts[4], point2=BasePartVerts[1],
faces=BasePartFaces)
# Draw a Dodecahedral Grain
#
def DrawDodec(VerModel,rad):
from abaqusConstants import *
from abaqus import *
label='BaseTemp'
VerAssembly=VerModel.rootAssembly
VerPart=VerModel.Part(name=label, dimensionality=THREE_D,type=DEFORMABLE_BODY)
VerPart.DatumPointByCoordinate((0,0,0))
VerPart.DatumPointByCoordinate((1,0,0))
VerPart.DatumPointByCoordinate((0,1,0))
pdatums=VerPart.datums
VerPart.DatumPlaneByThreePoints(point1=pdatums[1], point2=pdatums[2], point3=pdatums[3])
VerPart.DatumAxisByTwoPoint(point1=pdatums[1],point2=pdatums[2])
partTransform = VerPart.MakeSketchTransform(sketchPlane=pdatums[4], sketchUpEdge=pdatums[5],
sketchPlaneSide=SIDE1, sketchOrientation=BOTTOM, origin=(0,0,0))
VerSketch = VerModel.ConstrainedSketch(name=label,sheetSize=200, transform=partTransform)
VerSketch.Line(point1=(0.,0.),point2=(sqrt(2.)*rad,rad))
VerSketch.Line(point1=(sqrt(2.)*rad,rad),point2=(0.,2.*rad))
VerSketch.Line(point1=(0.,2.*rad),point2=(-sqrt(2.)*rad,rad))
VerSketch.Line(point1=(-sqrt(2.)*rad,rad),point2=(0.,0.))
VerPart.BaseShell(sketch=VerSketch)
for i in range (1,13):
dodecname='dodec'+str(i)
VerAssembly.Instance(name=dodecname,part=VerPart, dependent=ON)
VerAssembly.translate(instanceList=('dodec2', ), vector=(0.,0.,-2.*sqrt(2.)*rad))
VerAssembly.rotate(instanceList=('dodec3','dodec4', ), axisPoint=(0.0, 0.0, 0.0),
axisDirection=(0.0, 1., 0.0), angle=90.0)
VerAssembly.translate(instanceList=('dodec3', ), vector=(sqrt(2.)*rad,0.,0.))
VerAssembly.translate(instanceList=('dodec4', ), vector=(-sqrt(2.)*rad,0.,0.))
VerAssembly.translate(instanceList=('dodec3','dodec4', ), vector=(0.,0.,-sqrt(2.)*rad))
VerAssembly.rotate(instanceList=('dodec5','dodec6','dodec7','dodec8',),
axisPoint=(-sqrt(2.)*rad, rad, 0.0), axisDirection=(0., 0., 1.), angle=90.0)
VerAssembly.rotate(instanceList=('dodec5','dodec6','dodec7','dodec8',),
axisPoint=(-sqrt(2.)*rad, rad, 0.0), axisDirection=(0., 1., 0.), angle=-45.0)
VerAssembly.rotate(instanceList=('dodec5','dodec6','dodec7','dodec8',),
axisPoint=(-sqrt(2.)*rad, rad, 0.0), axisDirection=(1., 0., 1.), angle=-45.0)
VerAssembly.rotate(instanceList=('dodec6',),
axisPoint=(0., rad, -sqrt(2.)*rad), axisDirection=(0., 1., 0.), angle=90.0)
VerAssembly.rotate(instanceList=('dodec7',),
axisPoint=(0., rad, -sqrt(2.)*rad), axisDirection=(0., 1., 0.), angle=180.0)
VerAssembly.rotate(instanceList=('dodec8',),
axisPoint=(0., rad, -sqrt(2.)*rad), axisDirection=(0., 1., 0.), angle=270.0)
VerAssembly.rotate(instanceList=('dodec9','dodec10','dodec11','dodec12',),
axisPoint=(-sqrt(2.)*rad, rad, 0.0), axisDirection=(0., 0., 1.), angle=-90.0)
VerAssembly.rotate(instanceList=('dodec9','dodec10','dodec11','dodec12',),
axisPoint=(-sqrt(2.)*rad, rad, 0.0), axisDirection=(0., 1., 0.), angle=-45.0)
VerAssembly.rotate(instanceList=('dodec9','dodec10','dodec11','dodec12',),
axisPoint=(-sqrt(2.)*rad, rad, 0.0), axisDirection=(1., 0., 1.), angle=45.0)
VerAssembly.rotate(instanceList=('dodec10',),
axisPoint=(0., rad, -sqrt(2.)*rad), axisDirection=(0., -1., 0.), angle=90.0)
VerAssembly.rotate(instanceList=('dodec11',),
axisPoint=(0., rad, -sqrt(2.)*rad), axisDirection=(0., -1., 0.), angle=180.0)
VerAssembly.rotate(instanceList=('dodec12',),
axisPoint=(0., rad, -sqrt(2.)*rad), axisDirection=(0., -1., 0.), angle=270.0)
VerAssembly.InstanceFromBooleanMerge(name='Base', instances=(
VerAssembly.instances['dodec1'],
VerAssembly.instances['dodec2'], VerAssembly.instances['dodec3'],
VerAssembly.instances['dodec4'], VerAssembly.instances['dodec5'],
VerAssembly.instances['dodec6'], VerAssembly.instances['dodec7'],
VerAssembly.instances['dodec8'], VerAssembly.instances['dodec9'],
VerAssembly.instances['dodec10'],VerAssembly.instances['dodec11'],
VerAssembly.instances['dodec12'], ),
keepIntersections=ON, originalInstances=SUPPRESS, domain=GEOMETRY)
VerPart=VerModel.parts['Base']
VerPart.AddCells(faceList = VerPart.faces)
for i in range (1,12):
dodecname='dodec'+str(i)
del VerAssembly.instances[dodecname]
del VerAssembly.instances['Base-1']
# Draw a 2D Voronoi Tessellation
#
def Voronoi2D(VerModel,part_type,extrude_depth,num_grains,maxsize,hard_rad,random_seed):
from abaqusConstants import *
from abaqus import *
import random
import subprocess
xlist=[0.]
ylist=[0.]
VerAssembly=VerModel.rootAssembly
random.seed(random_seed)
qhullin=open('qhullin.dat','w')
qhullin.write("%i \n"%(2))
qhullin.write("%i \n"%(num_grains*9))
for i in range(0,num_grains):
outside=False
while outside==False:
xcor=random.random()*maxsize
ycor=random.random()*maxsize
if hard_rad==0.:
outside=True
break
if len(xlist)>1:
distold=1000.
for i in range(1,len(xlist)):
distnew=(xcor-xlist[i])*(xcor-xlist[i])+(ycor-ylist[i])*(ycor-ylist[i])
distnew=sqrt(distnew)
if distnew<distold:
distold=distnew
if distold>=hard_rad:
outside=True
else:
outside=True
xlist.append(xcor)
ylist.append(ycor)
qhullin.write("%18.6f %18.6f \n"%(xcor,ycor))
qhullin.write("%18.6f %18.6f \n"%(xcor+maxsize,ycor))
qhullin.write("%18.6f %18.6f \n"%(xcor-maxsize,ycor))
qhullin.write("%18.6f %18.6f \n"%(xcor,ycor+maxsize))
qhullin.write("%18.6f %18.6f \n"%(xcor,ycor-maxsize))
qhullin.write("%18.6f %18.6f \n"%(xcor+maxsize,ycor+maxsize))
qhullin.write("%18.6f %18.6f \n"%(xcor-maxsize,ycor-maxsize))
qhullin.write("%18.6f %18.6f \n"%(xcor+maxsize,ycor-maxsize))
qhullin.write("%18.6f %18.6f \n"%(xcor-maxsize,ycor+maxsize))
qhullin.close()
scales=open('scales.dat','w')
scales.write("%18.6f \n"%(maxsize))
scales.close()
# retcode=subprocess.call("qhull.exe v Qbb TI qhullin.dat o TO qhullout.dat")
retcode=subprocess.call("Voronoi2DPost.exe")
FortranFile=open('fortranout.dat')
num_cells=int(FortranFile.readline())
cordx=[]
cordy=[]
x1=[]
y1=[]
x2=[]
y2=[]
k=0
for i in range(0,num_cells):
label='Cell'+str(i)
if part_type==3:
VerPart=VerModel.Part(name=label, dimensionality=THREE_D,type=DEFORMABLE_BODY)
else:
VerPart=VerModel.Part(name=label, dimensionality=TWO_D_PLANAR,type=DEFORMABLE_BODY)
# Constuct Datum Point At Each Node
VerPart.DatumPointByCoordinate((0,0,0))
VerPart.DatumPointByCoordinate((1,0,0))
VerPart.DatumPointByCoordinate((0,1,0))
pdatums=VerPart.datums
# Constuct Datum Plane on Element Face and Datum Axis Along Element Base
VerPart.DatumPlaneByThreePoints(point1=pdatums[1],
point2=pdatums[2], point3=pdatums[3])
VerPart.DatumAxisByTwoPoint(point1=pdatums[1],point2=pdatums[2])
# Sketch New Part Geometry Over Original Element
partTransform = VerPart.MakeSketchTransform(sketchPlane=pdatums[4],
sketchUpEdge=pdatums[5],
sketchPlaneSide=SIDE1, sketchOrientation=BOTTOM, origin=(0,0,0))
VerSketch = VerModel.ConstrainedSketch(name=label,sheetSize=200,
transform=partTransform)
num_verts=int(FortranFile.readline())
for j in range(0,num_verts):
coords=FortranFile.readline().split(',')
cordx.append([])
cordy.append([])
cordx[j]=float(coords[0])
cordy[j]=float(coords[1])
print i,num_verts
for j in range(0,num_verts-1):
VerSketch.Line(point1=(cordx[j],cordy[j]),point2=(cordx[j+1],cordy[j+1]))
x1.append([])
y1.append([])
x1[k]=cordx[j]
y1[k]=cordy[j]
x2.append([])
y2.append([])
x2[k]=cordx[j+1]
y2[k]=cordy[j+1]
k=k+1
VerSketch.Line(point1=(cordx[num_verts-1],cordy[num_verts-1]),
point2=(cordx[0],cordy[0]))
x1.append([])
y1.append([])
x1[k]=cordx[num_verts-1]
y1[k]=cordy[num_verts-1]
x2.append([])
y2.append([])
x2[k]=cordx[0]
y2[k]=cordy[0]
k=k+1
print i,num_verts,k
if part_type==3:
VerPart.BaseSolidExtrude(sketch=VerSketch, depth=extrude_depth)
else:
VerPart.Shell(sketchPlane=pdatums[4], sketchUpEdge=pdatums[5], sketchPlaneSide=SIDE1,
sketchOrientation=BOTTOM, sketch=VerSketch)
VerAssembly.Instance(name=label,part=VerPart)
inst=[]
inst.append([])
for i in range(0,num_cells):
inst[i]=VerAssembly.instances['Cell'+str(i)]
if i<num_cells-1:
inst.append([])
VerAssembly.InstanceFromBooleanMerge(name='Merged',
instances=inst,originalInstances=DELETE, keepIntersections=ON,domain=GEOMETRY)
# Draw a 3D Voronoi Tessellation
#
def Voronoi3D(VerModel,num_grains,maxsize,hard_rad,random_seed):
from abaqusConstants import *
from abaqus import *
import random
import subprocess
xlist=[0.]
ylist=[0.]
zlist=[0.]
VerAssembly=VerModel.rootAssembly
random.seed(random_seed)
qhullin=open('qhullin.dat','w')
qhullin.write("%i \n"%(3))
qhullin.write("%i \n"%(num_grains*27))
for i in range(0,num_grains):
outside=False
while outside==False:
xcor=random.random()*maxsize
ycor=random.random()*maxsize
zcor=random.random()*maxsize
if hard_rad==0.:
outside=True
break
if len(xlist)>1:
distold=1000.
for i in range(1,len(xlist)):
distnew=(xcor-xlist[i])*(xcor-xlist[i])+(ycor-ylist[i])*(ycor-ylist[i])
distnew=distnew+(zcor-zlist[i])*(zcor-zlist[i])
distnew=sqrt(distnew)
if distnew<distold:
distold=distnew
if distold>=hard_rad:
outside=True
else:
outside=True
xlist.append(xcor)
ylist.append(ycor)
zlist.append(zcor)
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor+maxsize,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor-maxsize,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor+maxsize,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor-maxsize,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor-maxsize,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor+maxsize,zcor))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor+maxsize,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor-maxsize,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor+maxsize,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor-maxsize,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor-maxsize,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor+maxsize,zcor+maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor+maxsize,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor,ycor-maxsize,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor+maxsize,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor-maxsize,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor+maxsize,ycor-maxsize,zcor-maxsize))
qhullin.write("%18.6f %18.6f %18.6f \n"%(xcor-maxsize,ycor+maxsize,zcor-maxsize))
qhullin.close()
scales=open('scales.dat','w')
scales.write("%18.6f \n"%(maxsize))
scales.close()
# retcode=subprocess.call("qvoronoi.exe TI qhullin.dat o Fi TO qhullout.dat")
retcode=subprocess.call("Voronoi3DPost.exe")
FortranFile=open('fortranout.dat')
num_cells=int(FortranFile.readline())
cordx=[]
cordy=[]
cordz=[]
x1=[]
y1=[]
x2=[]
y2=[]
k=0
for k in range(0,num_cells):
num_hyp=int(FortranFile.readline())
for i in range(0,num_hyp):
label='C'+str(k)+'H'+str(i)
VerPart=VerModel.Part(name=label, dimensionality=THREE_D,type=DEFORMABLE_BODY)
# Constuct Datum Point At Each Node
num_verts=int(FortranFile.readline())
for j in range(0,num_verts):
coords=FortranFile.readline().split(',')
cordx.append([])
cordy.append([])
cordz.append([])
cordx[j]=float(coords[0])
cordy[j]=float(coords[1])
cordz[j]=float(coords[2])
VerPart.DatumPointByCoordinate((cordx[j],cordy[j],cordz[j]))
pdatums=VerPart.datums
p1x=pdatums[1].pointOn[0]
p1y=pdatums[1].pointOn[1]
p1z=pdatums[1].pointOn[2]
tol=1.e-4
for m in range(2,num_verts+1):
px=pdatums[m].pointOn[0]
py=pdatums[m].pointOn[1]
pz=pdatums[m].pointOn[2]
p1pk=sqrt((p1x-px)*(p1x-px)+(p1y-py)*(p1y-py)+(p1z-pz)*(p1z-pz))
if p1pk>tol:
index1=m
p2x=px
p2y=py
p2z=pz
break
for m in range(2,num_verts+1):
if m!=index1:
px=pdatums[m].pointOn[0]
py=pdatums[m].pointOn[1]
pz=pdatums[m].pointOn[2]
p1pk=sqrt((p1x-px)*(p1x-px)+(p1y-py)*(p1y-py)+(p1z-pz)*(p1z-pz))
p2pk=sqrt((p2x-px)*(p2x-px)+(p2y-py)*(p2y-py)+(p2z-pz)*(p2z-pz))
if p1pk>tol:
if p2pk>tol:
index2=m
break
VerPart.DatumPlaneByThreePoints(point1=pdatums[1], point2=pdatums[index1], point3=pdatums[index2])
VerPart.DatumAxisByTwoPoint(point1=pdatums[1],point2=pdatums[index1])
partTransform = VerPart.MakeSketchTransform(sketchPlane=pdatums[num_verts+1],
sketchUpEdge=pdatums[num_verts+2], sketchPlaneSide=SIDE1, sketchOrientation=BOTTOM, origin=(0.,0.,0.))
sklabel='Skbase'+'C'+str(k)+'H'+str(i)
VerSketch=VerModel.ConstrainedSketch(name=sklabel,sheetSize=200, transform=partTransform)
VerPart.projectReferencesOntoSketch(sketch=VerSketch, filter=COPLANAR_EDGES)
verts=VerSketch.vertices
centroidx=0.
centroidy=0.
angle=[]
jnum=[]
for j in range(0,num_verts):
centroidx=centroidx+verts[j].coords[0]
centroidy=centroidy+verts[j].coords[1]
centroidx=centroidx/float(num_verts)
centroidy=centroidy/float(num_verts)
for j in range(0,num_verts):
pointx=verts[j].coords[0]-centroidx
pointy=verts[j].coords[1]-centroidy
vertangle=atan2(pointy,pointx)
if vertangle<0.:
vertangle=2*pi+vertangle
angle.append(vertangle)
jnum.append(j)
icheck=0
while icheck==0:
icheck=1
for j in range(1,num_verts):
if angle[j]<angle[j-1]:
temp1=angle[j-1]
temp2=jnum[j-1]
angle[j-1]=angle[j]
angle[j]=temp1
jnum[j-1]=jnum[j]
jnum[j]=temp2
icheck=0
for j in range(1,num_verts):
x1=verts[jnum[j]].coords[0]
x2=verts[jnum[j-1]].coords[0]
y1=verts[jnum[j]].coords[1]
y2=verts[jnum[j-1]].coords[1]
VerSketch.Line(point1=(x1,y1),point2=(x2,y2))
VerSketch.Line(point1=(verts[jnum[num_verts-1]].coords[0],
verts[jnum[num_verts-1]].coords[1]),
point2=(verts[jnum[0]].coords[0],verts[jnum[0]].coords[1]))
VerPart.Shell(sketchPlane=pdatums[num_verts+1], sketchPlaneSide=SIDE1,
sketchUpEdge=pdatums[num_verts+2],sketchOrientation=BOTTOM,sketch=VerSketch)
label='Part'+'C'+str(k)+'H'+str(i)
VerAssembly.Instance(name=label,part=VerPart)
inst=[]
inst.append([])
for i in range(0,num_hyp):
inst[i]=VerAssembly.instances['Part'+'C'+str(k)+'H'+str(i)]
if i<num_hyp-1:
inst.append([])
VerAssembly.InstanceFromBooleanMerge(name='Merged'+str(k),
instances=inst,originalInstances=DELETE, keepIntersections=ON,domain=GEOMETRY)
shellpart=VerModel.parts['Merged'+str(k)]
shellpart.AddCells(faceList = shellpart.faces)
VerAssembly.Instance(name='Part'+str(k),part=shellpart, dependent=ON)
del VerAssembly.instances['Merged'+str(k)+'-1']
for i in range(0,num_hyp):
del VerModel.sketches['Skbase'+'C'+str(k)+'H'+str(i)]
del VerModel.parts['C'+str(k)+'H'+str(i)]
print float(k)/float(num_cells)
inst=[]
inst.append([])
for i in range(0,num_cells):
inst[i]=VerAssembly.instances['Part'+str(i)]
if i<num_cells-1:
inst.append([])
VerAssembly.InstanceFromBooleanMerge(name='Merged',
instances=inst,originalInstances=DELETE, keepIntersections=ON,domain=GEOMETRY)
# Make a Boolean Template Part
#
def BooleanPart(VerModel,part_type,rad,extrude_depth,
num_high,num_wide,num_thick,shape,dimension,scalex,scaley,scalez):
from abaqusConstants import *
from abaqus import *
VerAssembly=VerModel.rootAssembly
booSketch=VerModel.ConstrainedSketch(name='BSmall', sheetSize=20.0)
if shape==1:
vert1x=0.
vert1y=0.
vert2x=rad*num_high
vert2y=0.
vert3x=rad*num_high
vert3y=rad*num_wide
vert4x=0.
vert4y=rad*num_wide
edepth=extrude_depth*num_thick
if shape==2:
yheight=sin(radians(30.))
xheight=cos(radians(30.))
vert1x=0.
vert1y=rad*yheight+rad/2.
vert2x=rad*xheight*(float(num_high)-1.)*2.
vert2y=rad*yheight+rad/2.
vert3x=rad*xheight*(float(num_high)-1.)*2.
vert3y=rad*yheight+rad/2.+(float(num_wide)-1.)*(rad+rad*yheight)
vert4x=0.
vert4y=rad*yheight+rad/2.+(float(num_wide)-1.)*(rad+rad*yheight)
edepth=extrude_depth*num_thick
if shape==3:
vert1x=0.
vert1y=rad
vert2x=sqrt(2.)*rad*(2.*float(num_high)-1.)
vert2y=rad
vert3x=sqrt(2.)*rad*(2.*float(num_high)-1.)
vert3y=rad*(2.*float(num_wide)-1.)
vert4x=0.
vert4y=rad*(2.*float(num_wide)-1.)
edepth=sqrt(2.)*rad*(2.*float(num_thick)-1.)
if shape==4:
vert1x=0.
vert1y=0.
vert2x=scalex
vert2y=0.
vert3x=scalex
vert3y=scaley
vert4x=0.
vert4y=scaley
if dimension==2:
edepth=extrude_depth
else:
edepth=scalez
booSketch.Line(point1=(vert1x,vert1y), point2=(vert2x, vert2y))
booSketch.Line(point1=(vert2x, vert2y), point2=(vert3x, vert3y))
booSketch.Line(point1=(vert3x, vert3y), point2=(vert4x, vert4y))
booSketch.Line(point1=(vert4x, vert4y), point2=(vert1x, vert1y))
if part_type==3:
booPart=VerModel.Part(name='BSmall', dimensionality=THREE_D,type=DEFORMABLE_BODY)
booPart.BaseSolidExtrude(sketch=booSketch, depth=edepth)
else:
booPart=VerModel.Part(name='BSmall', dimensionality=TWO_D_PLANAR,type=DEFORMABLE_BODY)
booPart.BaseShell(sketch=booSketch)
booSketchB=VerModel.ConstrainedSketch(name='BBig', sheetSize=20.0)
booSketchB.Line(point1=(vert1x-10.,vert1y-10.), point2=(vert2x+10., vert2y-10.))
booSketchB.Line(point1=(vert2x+10., vert2y-10.), point2=(vert3x+10., vert3y+10.))
booSketchB.Line(point1=(vert3x+10., vert3y+10.), point2=(vert4x-10., vert4y+10.))
booSketchB.Line(point1=(vert4x-10., vert4y+10.), point2=(vert1x-10., vert1y-10.))
if part_type==3:
booPartb=VerModel.Part(name='BBig', dimensionality=THREE_D,type=DEFORMABLE_BODY)
booPartb.BaseSolidExtrude(sketch=booSketchB, depth=edepth*10.)
else:
booPartb=VerModel.Part(name='BBig', dimensionality=TWO_D_PLANAR,type=DEFORMABLE_BODY)
booPartb.BaseShell(sketch=booSketchB)
VerAssembly.Instance(name='BSmall',part=booPart, dependent=ON)
VerAssembly.Instance(name='BBig',part=booPartb, dependent=ON)
if shape==3:
if part_type==3:
VerAssembly.translate(instanceList=('BSmall', ),
vector=(0.,0.,-sqrt(2.)*rad))
VerAssembly.translate(instanceList=('BBig', ),
vector=(0.,0.,-sqrt(2.)*rad*5.))
if shape==4:
if part_type==3:
VerAssembly.translate(instanceList=('BBig', ),
vector=(0.,0.,-edepth*5.))
VerAssembly.InstanceFromBooleanCut(name='Template',
instanceToBeCut=VerAssembly.instances['BBig'],
cuttingInstances=(VerAssembly.instances['BSmall'], ),
originalInstances=DELETE)
# Pattern base parts for multilpe grains
#
def PatternParts(num_high,num_wide,num_thick,VerPart,rad,shape,VerModel):
from abaqusConstants import *
from abaqus import *
VerAssembly=VerModel.rootAssembly
yheight=sin(radians(30.))
xheight=cos(radians(30.))
icount=0
for i in range(0,num_high):
for j in range(0,num_wide):
for k in range(0,num_thick):
label='Part'+str(icount)
VerAssembly.Instance(name=label,part=VerPart, dependent=ON)
# Square
if shape==1:
VerAssembly.translate(instanceList=(label, ),
vector=(i*rad,j*rad,k*rad))
# Hexagon
if shape==2:
if j%2==0:
VerAssembly.translate(instanceList=(label, ),
vector=(i*xheight*rad*2.,j*rad*(1.+yheight),k*rad))
else:
VerAssembly.translate(instanceList=(label, ),
vector=(i*xheight*rad*2.+xheight*rad,j*rad*(1.+yheight),k*rad))
# Dodecahedron
if shape==3:
if j%2==0:
VerAssembly.translate(instanceList=(label, ),
vector=(i*rad*2.*sqrt(2.),j*2.*rad,2.*k*rad*sqrt(2.)))
else:
VerAssembly.translate(instanceList=(label, ),
vector=(i*rad*2.*sqrt(2.)+sqrt(2.)*rad,j*2.*rad,2.*k*rad*sqrt(2.)+sqrt(2.)*rad))
icount=icount+1
inst=[]
inst.append([])
for i in range(0,icount):
inst[i]=VerAssembly.instances['Part'+str(i)]
if i<icount-1:
inst.append([])
VerAssembly.InstanceFromBooleanMerge(name='Merged',
instances=inst,originalInstances=DELETE, keepIntersections=ON,domain=GEOMETRY)
# Output vertices and element connectivity for corrosion analysis
#
def VertsConn(VerPart,dimension):
from abaqusConstants import *
from abaqus import *
vertout=open('vertout.dat','w')
vertout.write("%i\n"%(len(VerPart.cells)))
k=1.
for eachcell in VerPart.cells:
print k/float(len(VerPart.cells))
cellElements=eachcell.getElements()
vertout.write("%i\n"%(len(cellElements)))
cellFaces=eachcell.getFaces()
for eachElement in cellElements:
vertout.write("%i\n"%(eachElement.label))
Adj_Elem=eachElement.getAdjacentElements()
vertout.write("%i\n"%(len(Adj_Elem)))
for i in range(0,len(Adj_Elem)):
vertout.write("%i\n"%(Adj_Elem[i].label))
centroidx=0.
centroidy=0.
centroidz=0.
dmin=1000.
for eachNode in eachElement.getNodes():
centroidx=centroidx+eachNode.coordinates[0]
centroidy=centroidy+eachNode.coordinates[1]
centroidz=centroidz+eachNode.coordinates[2]
num_nodes=float(len(eachElement.getNodes()))
centroidx=centroidx/num_nodes
centroidy=centroidy/num_nodes
centroidz=centroidz/num_nodes
for i in range(0,len(cellFaces)):
eachFace=VerPart.faces[cellFaces[i]]
facex=eachFace.pointOn[0][0]
facey=eachFace.pointOn[0][1]
facez=eachFace.pointOn[0][2]
normalx=eachFace.getNormal()[0]
normaly=eachFace.getNormal()[1]
normalz=eachFace.getNormal()[2]
if dimension==2:
if normalx==0.:
if normaly==0.:
if abs(normalz)==1:
continue
else:
if len(Adj_Elem)<6:
if normalx==0.:
if normaly==0.:
if abs(normalz)==1:
continue
dfcx=facex-centroidx
dfcy=facey-centroidy
dfcz=facez-centroidz
distance=abs(dfcx*normalx+dfcy*normaly+dfcz*normalz)
if distance<dmin:
dmin=distance
vertout.write("%18.6f\n"%(dmin))
k=k+1
vertout.close()
# Generate Materials and Sections
#
def MatGen(ana_type,VerPart,VerModel,part_type,meshsize,random_seed):
from abaqusConstants import *
from abaqus import *
import random
if ana_type==2:
VerModel.Material(name='Magnesium')
VerModel.materials['Magnesium'].Density(table=((1e-05, ), ))
VerModel.materials['Magnesium'].Depvar(deleteVar=20, n=30)
VerModel.materials['Magnesium'].UserMaterial(
mechanicalConstants=(44000.0, 0.35, 138.7, 16.0, 165.0,0.5))
if part_type==3:
regions=VerPart.cells
else:
regions=VerPart.faces
VerModel.HomogeneousSolidSection(name='Magnesium',
material='Magnesium', thickness=meshsize)
VerPart.SectionAssignment(region=(regions,),
sectionName='Magnesium', offset=0.0, offsetField='')
else:
labelcount=1
if part_type==3:
regions=VerPart.cells
else:
regions=VerPart.faces
random.seed(random_seed)
for eachregion in regions:
rand1=(random.random()-0.5)*2.
rand2=(random.random()-0.5)*2.
rand3=(random.random()-0.5)*2.
rand4=(random.random()-0.5)*2.
rand5=(random.random()-0.5)*2.
rand6=(rand1*rand4+rand2*rand5)/(-rand3)
mlabel='Mat'+str(labelcount)
VerModel.Material(name=mlabel)
VerModel.materials[mlabel].Density(table=((1e-05, ), ))
VerModel.materials[mlabel].Depvar(deleteVar=124, n=124)
VerModel.materials[mlabel].UserMaterial(
mechanicalConstants=(200000.0, 0.3,
rand1, rand2, rand3,1.,0.,0.,rand4,rand5,rand6,0.,0.,1.,
10.,0.001,541.5,109.5,60.8,1.,1.,0.5,1.))
VerModel.HomogeneousSolidSection(name=mlabel,
material=mlabel, thickness=meshsize)
VerPart.SectionAssignment(region=(eachregion,),
sectionName=mlabel, offset=0.0, offsetField='')
labelcount=labelcount+1
# Shape 1 BCs and Constraints - Uniaxial Tension
#
def S1BCs(iNodes,VerModel,num_high,num_wide,num_thick,shape,
dimension,extrude_depth,rad,scalex,scaley,scalez):
from abaqusConstants import *
from abaqus import *
import regionToolset
VerAssembly=VerModel.rootAssembly
Min=-0.001
Max=0.001
fwide=float(num_wide)
fhigh=float(num_high)
fthick=float(num_thick)
if shape==1:
# BC LEFT
XMnBL=Min
XMxBL=Max
YMnBL=Min
YMxBL=fwide*rad+Max
ZMnBL=Min
ZMxBL=Max+extrude_depth
# BC BACK
XMnBBK=Min
XMxBBK=fhigh*rad+Max
YMnBBK=Min
YMxBBK=fwide*rad+Max
ZMnBBK=Min
ZMxBBK=Max
# BC Bottom
XMnBBT=Min
XMxBBT=fhigh*rad+Max
YMnBBT=Min
YMxBBT=Max
ZMnBBT=Min
ZMxBBT=Max+extrude_depth
# BC Right
XMnBR=fhigh*rad+Min
XMxBR=fhigh*rad+Max
YMnBR=Min
YMxBR=fwide*rad+Max
ZMnBR=Min
ZMxBR=Max+extrude_depth
# RP
XRP=fhigh*rad
YRP=fwide*rad*0.5
ZRP=extrude_depth*0.5
if shape==2:
yheight=sin(radians(30.))
xheight=cos(radians(30.))
# BC LEFT
XMnBL=Min
XMxBL=Max
YMnBL=rad*yheight+rad/2.+Min
YMxBL=rad*yheight+rad/2.+(fwide-1.)*(rad+rad*yheight)+Max
ZMnBL=Min
ZMxBL=Max+extrude_depth
# BC BACK
XMnBBK=Min
XMxBBK=rad*xheight*(fhigh-1.)*2.+Max
YMnBBK=rad*yheight+rad/2.+Min
YMxBBK=rad*yheight+rad/2.+(fwide-1.)*(rad+rad*yheight)+Max
ZMnBBK=Min
ZMxBBK=Max
# BC Bottom
XMnBBT=Min
XMxBBT=rad*xheight*(fhigh-1.)*2.+Max
YMnBBT=rad*yheight+rad/2.+Min
YMxBBT=rad*yheight+rad/2.+Max
ZMnBBT=Min
ZMxBBT=Max+extrude_depth
# BC Right
XMnBR=rad*xheight*(fhigh-1.)*2.+Min
XMxBR=rad*xheight*(fhigh-1.)*2.+Max
YMnBR=rad*yheight+rad/2.+Min
YMxBR=rad*yheight+rad/2.+(fwide-1.)*(rad+rad*yheight)+Max
ZMnBR=Min
ZMxBR=Max+extrude_depth
# RP
XRP=rad*xheight*(fhigh-1.)*2.
YRP=rad*yheight+rad/2.+(fwide-1.)*(rad+rad*yheight)*0.5
ZRP=extrude_depth*0.5
if shape==4:
# BC LEFT
XMnBL=Min
XMxBL=Max
YMnBL=Min
YMxBL=scaley+Max
ZMnBL=Min
ZMxBL=Max+extrude_depth
# BC BACK
XMnBBK=Min
XMxBBK=scalex+Max
YMnBBK=Min
YMxBBK=scaley+Max
ZMnBBK=Min
ZMxBBK=Max
# BC Bottom
XMnBBT=Min
XMxBBT=scalex+Max
YMnBBT=Min
YMxBBT=Max
ZMnBBT=Min
ZMxBBT=Max+extrude_depth
# BC Right
XMnBR=scalex+Min
XMxBR=scalex+Max
YMnBR=Min
YMxBR=scaley+Max
ZMnBR=Min
ZMxBR=Max+extrude_depth
# RP
XRP=scalex
YRP=scaley*0.5
ZRP=extrude_depth*0.5
#
total_length=(XMxBR-Max)-(XMnBL-Min)
BLeft=iNodes.getByBoundingBox(xMin=XMnBL,xMax=XMxBL,yMin=YMnBL,yMax=YMxBL,zMin=ZMnBL,zMax=ZMxBL)
BBack=iNodes.getByBoundingBox(xMin=XMnBBK,xMax=XMxBBK,yMin=YMnBBK,yMax=YMxBBK,zMin=ZMnBBK,zMax=ZMxBBK)
BBot=iNodes.getByBoundingBox(xMin=XMnBBT,xMax=XMxBBT,yMin=YMnBBT,yMax=YMxBBT,zMin=ZMnBBT,zMax=ZMxBBT)
BRight=iNodes.getByBoundingBox(xMin=XMnBR,xMax=XMxBR,yMin=YMnBR,yMax=YMxBR,zMin=ZMnBR,zMax=ZMxBR)
Ref1=VerAssembly.ReferencePoint(point=(XRP,YRP,ZRP))
#
BLregion=regionToolset.Region(nodes=BLeft)
BBregion=regionToolset.Region(nodes=BBot)
BBKregion=regionToolset.Region(nodes=BBack)
BRregion=regionToolset.Region(nodes=BRight)
VerModel.DisplacementBC(name='LeftX', createStepName='Initial',
region=BLregion, u1=0.0, u2=UNSET, u3=UNSET, ur1=UNSET, ur2=UNSET,
ur3=UNSET, amplitude=UNSET, fixed=OFF, distributionType=UNIFORM)
VerModel.DisplacementBC(name='BottomY', createStepName='Initial',
region=BBregion, u1=UNSET, u2=0.0, u3=UNSET, ur1=UNSET, ur2=UNSET,
ur3=UNSET, amplitude=UNSET, fixed=OFF, distributionType=UNIFORM)
VerModel.DisplacementBC(name='BackZ', createStepName='Initial',
region=BBKregion, u1=UNSET, u2=UNSET, u3=0.0, ur1=UNSET, ur2=UNSET,
ur3=UNSET, amplitude=UNSET, fixed=OFF, distributionType=UNIFORM)
#
id1=VerAssembly.features['RP-1'].id
RPoint=regionToolset.Region(referencePoints=(VerAssembly.referencePoints[id1],))
VerAssembly.Set(referencePoints=(VerAssembly.referencePoints[id1],), name='RPoint')
VerAssembly.Set(nodes=BRight, name='BRight')
VerModel.Equation(name='Constraint-1', terms=((1.0, 'BRight', 1), ( -1.0, 'RPoint', 1)))
VerModel.SmoothStepAmplitude(name='Load', timeSpan=STEP, data=((0.0, 0.0), (1.0, 1.0)))
VerModel.DisplacementBC(name='RPNode', createStepName='Load',
region=RPoint, u1=total_length*0.17, u2=0., u3=UNSET, ur1=UNSET, ur2=UNSET,
ur3=UNSET, amplitude='Load', fixed=OFF, distributionType=UNIFORM)

View file

@ -0,0 +1,750 @@
! This program generates a micro-strucutre mask and applies it to
! an existing mesh.
! J.Grogan 05/08/11
program Voronoi3DPost
!
! Parameters
parameter(max_elements=100000,max_cells=20000,max_fc=100,max_faces=10000)
parameter(max_elem_in_cell=50000,max_neigh_per_elem=6,max_neighbours=50)
!
! Variables
character(len=256)input
character(len=256)input2(2)
integer cell_stat(20000)
integer,allocatable,dimension(:)::closest
integer,allocatable,dimension(:)::num_ele_cell
integer,allocatable,dimension(:)::num_faces
integer,allocatable,dimension(:)::cell_status
integer,allocatable,dimension(:,:)::cell_ele
integer,dimension(max_elements)::num_neighbours
integer,dimension(max_elements,max_neighbours)::neighbour
integer mesh_type,mask_type,num_x,num_y,num_z,num_grains
double precision grain_length,rad_hard,rscale
double precision,allocatable,dimension(:,:)::distance
double precision,allocatable,dimension(:,:)::nbr_dist
double precision,allocatable,dimension(:,:)::cor_faces
double precision,dimension(max_elements)::cor_dist
double precision,allocatable,dimension(:,:)::ele_centroid
double precision,allocatable,dimension(:,:)::cell_centroid
double precision,allocatable,dimension(:,:,:)::face
!
! Mesh Type: 2 = 2D, 3 = 3D
mesh_type=3
! Mask Type: 1= Square, 2= Hexagon, 3= Dodec, 4=2D Voronoi, 5=3D Voronoi
mask_type=5
! Grain Length
Grain_length=0.025
! Num grains x
num_x=10
! Num grains y
num_y=10
! Num grains z
num_z=1
! Hardcore Voronoi Radius
rad_hard=0.00
num_grains=num_x*num_y*num_z
if(mask_type>3)then
! Create Tessellation
allocate(face(max_cells,max_fc,4),num_faces(max_cells),cell_centroid(max_cells,3))
call make_voronoi(mask_type,mesh_type,num_grains,num_x,rad_hard,grain_length)
call process_voronoi(face,num_faces,cell_centroid,num_cells,cell_stat)
else
! Generate Centroids and faces for other geometries
icount=1
num_cells=num_grains
allocate(face(num_cells,6,4),num_faces(num_cells),cell_centroid(num_cells,3))
do i=1,num_x
do j=1,num_y
do k=1,num_z
if(mask_type==1)then
call make_square(i,j,k,grain_length,num_faces(icount), &
& face(icount,:,:),cell_centroid(icount,:),mesh_type)
elseif(mask_type==2)then
call make_hexagon(i,j,k,grain_length,num_faces(icount), &
& face(icount,:,:),cell_centroid(icount,:),mesh_type)
else
if(mod(j,2)==0)then
cell_centroid(icount,1)=2.*(i-1)*Grain_length*sqrt(2.)+&
&sqrt(2.)*Grain_length
cell_centroid(icount,3)=2.*(k-1)*Grain_length*sqrt(2.)+&
&Grain_length*sqrt(2.)
else
cell_centroid(icount,1)=2.*(i-1)*Grain_length*sqrt(2.)
cell_centroid(icount,3)=2.*(k-1)*Grain_length*sqrt(2.)
endif
cell_centroid(icount,2)=2.*(j-1)*Grain_length
endif
icount=icount+1
enddo
enddo
enddo
endif
!
allocate(ele_centroid(max_elements,3))
! Get element centroids
call elem_centroids(num_elements,ele_centroid,mesh_type)
!
! Get neighbouring elements
allocate(nbr_dist(max_elements,max_neighbours))
do i=1,num_elements
icount=1
do j=1,num_elements
if(icount>max_neighbours)then
rmaxdist=0.
do k=1,max_neighbours
if(nbr_dist(i,k)>rmaxdist)then
rmaxdist=nbr_dist(i,k)
index_max_dist=k
endif
enddo
endif
cent1x=ele_centroid(i,1)
cent1y=ele_centroid(i,2)
cent1z=ele_centroid(i,3)
cent2x=ele_centroid(j,1)
cent2y=ele_centroid(j,2)
cent2z=ele_centroid(j,3)
dist=sqrt((cent1x-cent2x)*(cent1x-cent2x)+(cent1y-cent2y)*(cent1y-cent2y)&
&+(cent1z-cent2z)*(cent1z-cent2z))
if(icount>max_neighbours)then
if(dist<rmaxdist)then
nbr_dist(i,index_max_dist)=dist
neighbour(i,index_max_dist)=j
endif
else
nbr_dist(i,j)=dist
neighbour(i,j)=j
endif
icount=icount+1
enddo
print *,float(i)/float(num_elements)
enddo
deallocate(nbr_dist)
!
! Get corrosion surface distances
open(unit=22,file='CorSurf.dat',status='unknown')
allocate(cor_faces(max_faces,3))
ierr=0
inum_faces=1
do while (ierr==0)
read(22,*,iostat=ierr)cor_faces(inum_faces,1),cor_faces(inum_faces,2),&
&cor_faces(inum_faces,3)
if(ierr==0)inum_faces=inum_faces+1
enddo
close(unit=22)
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
distmin=1000.
do j=1,inum_faces-1
facex=cor_faces(j,1)
facey=cor_faces(j,2)
facez=cor_faces(j,3)
dist=sqrt((centx-facex)*(centx-facex)+(centy-facey)*(centy-facey)&
&+(centz-facez)*(centz-facez))
if(dist<distmin)distmin=dist
enddo
cor_dist(i)=distmin
enddo
deallocate(cor_faces)
!
! Find closest cell to element centroid
allocate(closest(max_elements))
if(mask_type==5)then
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
do j=1,num_cells
if(num_faces(j)<3)then
print *,'warning',i,j,num_faces(j)
cycle
endif
if(cell_stat(j)==1)cycle
icheck=0
do k=1,num_faces(j)
rnorx=face(j,k,1)
rnory=face(j,k,2)
rnorz=face(j,k,3)
roff=face(j,k,4)
dotprod=centx*rnorx+centy*rnory+centz*rnorz+roff
if(dotprod<0.)then
icheck=1
exit
endif
enddo
if(icheck==0)then
closest(i)=j
endif
enddo
enddo
else
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
do j=1,num_cells
if(cell_stat(j)==1)cycle
cellx=cell_centroid(j,1)
celly=cell_centroid(j,2)
icheck=0
do k=1,num_faces(j)
fx1=face(j,k,1)
fx2=face(j,k,2)
fy1=face(j,k,3)
fy2=face(j,k,4)
dcell=(fx2-fx1)*(celly-fy1)-(fy2-fy1)*(cellx-fx1)
dele=(fx2-fx1)*(centy-fy1)-(fy2-fy1)*(centx-fx1)
if(dcell<0.)then
if(dele>=0.)icheck=1
else
if(dele<0.)icheck=1
endif
if(icheck==1)exit
enddo
if(icheck==0)then
closest(i)=j
endif
enddo
enddo
endif
!
allocate(num_ele_cell(num_cells),cell_ele(num_cells,max_elem_in_cell))
! Find each element in a cell
do i=1,num_cells
num_ele_cell(i)=0
do j=1,num_elements
if(closest(j)==i)then
num_ele_cell(i)=num_ele_cell(i)+1
cell_ele(i,num_ele_cell(i))=j
endif
enddo
enddo
!
!
allocate(distance(num_cells,num_elements))
! Find min distance between element centroid and cell faces/hyperplanes
do i=1,num_cells
if(i==1406) print *,num_faces(i)
do j=1,num_ele_cell(i)
centx=ele_centroid(cell_ele(i,j),1)
centy=ele_centroid(cell_ele(i,j),2)
centz=ele_centroid(cell_ele(i,j),3)
distmin=1000.
if(mask_type==5)then
do k=1,num_faces(i)
rnorx=face(i,k,1)
rnory=face(i,k,2)
rnorz=face(i,k,3)
roff=face(i,k,4)
dotprod=abs(centx*rnorx+centy*rnory+centz*rnorz+roff)
if(dotprod<distmin)distmin=dotprod
enddo
else
do k=1,num_faces(i)
x1=face(i,k,1)
x2=face(i,k,2)
y1=face(i,k,3)
y2=face(i,k,4)
dotprod=abs((x2-x1)*(y1-centy)-(x1-centx)*(y2-y1))
dotprod=dotprod/(sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)))
if(dotprod<distmin)distmin=dotprod
enddo
endif
distance(i,j)=distmin
enddo
enddo
!
! Write Element Sets
rewind(10)
open(unit=13,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Part')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
do i=1,num_cells
if(num_ele_cell(i)==0)cycle
write(13,*)'*Elset,elset=ele',i
icheck=1
do j=1,num_ele_cell(i)
if(icheck==1)then
if(num_ele_cell(i)>1)then
write(13,'(i6)',advance='no')cell_ele(i,j)
else
write(13,'(i6)')cell_ele(i,j)
endif
elseif(icheck==num_ele_cell(i))then
write(13,'(a1,i6)')',',cell_ele(i,j)
else
if(mod(icheck,15)==0)then
write(13,'(a1,i6)')',',cell_ele(i,j)
else
write(13,'(a1,i6)',advance='no')',',cell_ele(i,j)
endif
endif
icheck=icheck+1
enddo
if(iana_type==1)write(19,*)'*Solid Section,elset=ele',i,'Boundary,material=Mat',i
enddo
write(13,*)'**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(13,'(a)')'*End Assembly'
write(13,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
do i=1,num_cells
if(num_ele_cell(i)==0)cycle
do j=1,num_ele_cell(i)
write(13,'(3(a,i6),2(a,f18.6),3(i6,a))')'Assembly.CorPart.',cell_ele(i,j),',' &
& ,cell_ele(i,j),',',max_neighbours,',',distance(i,j),',',cor_dist(cell_ele(i,j)) &
& ,0,',',0,',',0,','
write(13,'(8(i6,a))')0,',',0,',',0,',',0,',',0,',',0,',',0,',',1,','
do k=1, max_neighbours
if(mod(k,8)/=0)then
if(k/=max_neighbours)then
write(13,'(i6,a)',advance='no')neighbour(cell_ele(i,j),k),','
else
write(13,'(i6)')neighbour(cell_ele(i,j),k)
endif
else
if(k/=max_neighbours)then
write(13,'(i6,a)')neighbour(cell_ele(i,j),k),','
else
write(13,'(i6)')neighbour(cell_ele(i,j),k)
endif
endif
enddo
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(13,'(a)')input2(1)
enddo
end program
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Generate Voronoi Tesselation Using QHULL
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine make_voronoi(mask_type,mesh_type,num_grains,num_x,rad_hard,grain_length)
integer mesh_type,mask_type,num_grains
integer seed(1)
double precision grain_length,rad_hard,rscale
if(mesh_type==2)mask_type=4
! Write QHull input file
open(unit=20,file='qhullin.dat',status='unknown')
write(20,*)mask_type-2
if(mask_type==5)write(20,*)num_grains*27
if(mask_type==4)write(20,*)num_grains*9
seed=1557
rscale=float(num_x)*Grain_Length
call random_seed(put=seed)
do i=1,num_grains
call random_number(xcor)
call random_number(ycor)
if(mask_type==5)call random_number(zcor)
xcor=xcor*rscale
ycor=ycor*rscale
if(mask_type==5)zcor=zcor*rscale
if(mask_type==4)then
write(20,*)xcor,ycor
write(20,*)xcor,ycor+rscale
write(20,*)xcor,ycor-rscale
write(20,*)xcor+rscale,ycor
write(20,*)xcor-rscale,ycor
write(20,*)xcor+rscale,ycor+rscale
write(20,*)xcor-rscale,ycor-rscale
write(20,*)xcor+rscale,ycor-rscale
write(20,*)xcor-rscale,ycor+rscale
elseif(mask_type==5)then
write(20,*)xcor,ycor,zcor
write(20,*)xcor+rscale,ycor,zcor
write(20,*)xcor-rscale,ycor,zcor
write(20,*)xcor,ycor+rscale,zcor
write(20,*)xcor,ycor-rscale,zcor
write(20,*)xcor+rscale,ycor+rscale,zcor
write(20,*)xcor-rscale,ycor-rscale,zcor
write(20,*)xcor+rscale,ycor-rscale,zcor
write(20,*)xcor-rscale,ycor+rscale,zcor
write(20,*)xcor,ycor,zcor+rscale
write(20,*)xcor+rscale,ycor,zcor+rscale
write(20,*)xcor-rscale,ycor,zcor+rscale
write(20,*)xcor,ycor+rscale,zcor+rscale
write(20,*)xcor,ycor-rscale,zcor+rscale
write(20,*)xcor+rscale,ycor+rscale,zcor+rscale
write(20,*)xcor-rscale,ycor-rscale,zcor+rscale
write(20,*)xcor+rscale,ycor-rscale,zcor+rscale
write(20,*)xcor-rscale,ycor+rscale,zcor+rscale
write(20,*)xcor,ycor,zcor-rscale
write(20,*)xcor+rscale,ycor,zcor-rscale
write(20,*)xcor-rscale,ycor,zcor-rscale
write(20,*)xcor,ycor+rscale,zcor-rscale
write(20,*)xcor,ycor-rscale,zcor-rscale
write(20,*)xcor+rscale,ycor+rscale,zcor-rscale
write(20,*)xcor-rscale,ycor-rscale,zcor-rscale
write(20,*)xcor+rscale,ycor-rscale,zcor-rscale
write(20,*)xcor-rscale,ycor+rscale,zcor-rscale
endif
enddo
close(20)
call system('qvoronoi.exe TI qhullin.dat o Fi TO qhullout.dat')
end subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Process Voronoi Tesselation - Return Arrays of Cell Faces and Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine process_voronoi(face_sub,num_faces_sub,cell_centroid,num_cells,cell_stat)
!
! Variables
character(len=320)full_line
character(len=320)test_string
character(len=256)input
character(len=256)input2(2)
integer seed (1)
integer cell_stat(20000)
integer,allocatable,dimension(:)::num_verts
integer,allocatable,dimension(:)::num_cell_hyp
integer,allocatable,dimension(:)::numverts
integer,dimension(20000)::num_faces_sub
integer,allocatable,dimension(:,:)::num_hyp_verts
integer,allocatable,dimension(:,:)::vert_list
integer,allocatable,dimension(:,:)::hyp_list
integer,allocatable,dimension(:,:)::facet
integer max_vc,max_hc,max_vh
double precision,allocatable,dimension(:)::xv_cor
double precision,allocatable,dimension(:)::yv_cor
double precision,allocatable,dimension(:)::zv_cor
double precision,allocatable,dimension(:)::offset
double precision,allocatable,dimension(:,:)::cor
double precision,allocatable,dimension(:,:)::ele_centroid
double precision,dimension(20000,3)::cell_centroid
double precision,dimension(20000,100,4)::face_sub
!
! Parameters
parameter(max_vc=100,max_hc=100,max_vh=50)
!
open(unit=21,file='qhullout.dat',status='unknown')
!
! Allocate Arrays
read(21,*)idimension
read(21,*)num_total_verts,num_cells
allocate(num_verts(num_cells))
allocate(xv_cor(num_total_verts),yv_cor(num_total_verts))
if(idimension==3)allocate(zv_cor(num_total_verts))
allocate(vert_list(num_cells,max_vc))
!
! Read in all vertice co-ordinates
do i=1,num_total_verts
if(idimension==2)read(21,*)xv_cor(i),yv_cor(i)
if(idimension==3)read(21,*)xv_cor(i),yv_cor(i),zv_cor(i)
enddo
!
! Read in vertice labels for each voronoi cell
do i=1,num_cells
read(21,*)num_verts(i)
backspace(21)
if(num_verts(i)>9)then
read(21,'(i3,a320)')idummy,full_line
else
read(21,'(i2,a320)')idummy,full_line
endif
ileft=1
num_points=1
do iright=1,320
test_string=full_line(iright:iright)
if((test_string==' ').or.(iright==320))then
read(full_line(ileft:iright-1),'(i6)')vert_list(i,num_points)
if(num_points==num_verts(i))exit
ileft=iright+1
num_points=num_points+1
endif
enddo
do j=1,num_points-1
if(vert_list(i,j)==0)cell_stat(i)=1
enddo
enddo
if(idimension==3)then
!
! Read in bounded hyperplane cell labels and co-ordinates
read(21,*)num_hyp
allocate(facet(2,num_hyp),cor(3,num_hyp),offset(num_hyp))
allocate(hyp_list(num_cells,num_hyp),num_cell_hyp(num_cells))
!
do i=1,num_hyp
read(21,*)dummy,facet(1,i),facet(2,i),cor(1,i),cor(2,i),cor(3,i),offset(i)
enddo
!
! Determine hyperplanes of each cell
do i=1,num_cells
num_hy=1
do j=1,num_hyp
if((facet(1,j)==i-1).or.(facet(2,j)==i-1))then
hyp_list(i,num_hy)=j
num_cell_hyp(i)=num_hy
num_hy=num_hy+1
endif
enddo
enddo
!
! Store hyperplane info in convenient format
do i=1,num_cells
num_faces_sub(i)=num_cell_hyp(i)
do j=1,num_cell_hyp(i)
face_sub(i,j,1)=cor(1,hyp_list(i,j))
face_sub(i,j,2)=cor(2,hyp_list(i,j))
face_sub(i,j,3)=cor(3,hyp_list(i,j))
face_sub(i,j,4)=offset(hyp_list(i,j))
enddo
enddo
else
do i=1,num_cells
num_faces_sub(i)=num_verts(i)
do j=1,num_verts(i)
x2=xv_cor(vert_list(i,j)+1)
y2=yv_cor(vert_list(i,j)+1)
if(j==1)then
x1=xv_cor(vert_list(i,num_verts(i))+1)
y1=yv_cor(vert_list(i,num_verts(i))+1)
else
x1=xv_cor(vert_list(i,j-1)+1)
y1=yv_cor(vert_list(i,j-1)+1)
endif
face_sub(i,j,1)=x1
face_sub(i,j,2)=x2
face_sub(i,j,3)=y1
face_sub(i,j,4)=y2
enddo
enddo
endif
!
! Get cell centroid
do i=1,num_cells
centroidx=0.
centroidy=0.
centroidz=0.
do j=1,num_verts(i)
centroidx=centroidx+xv_cor(vert_list(i,j)+1)
centroidy=centroidy+yv_cor(vert_list(i,j)+1)
if(idimension==3)centroidz=centroidz+zv_cor(vert_list(i,j)+1)
enddo
cell_centroid(i,1)=centroidx/float(num_verts(i))
cell_centroid(i,2)=centroidy/float(num_verts(i))
if(idimension==3)then
cell_centroid(i,3)=centroidz/float(num_verts(i))
else
cell_centroid(i,3)=0.d0
endif
enddo
if(idimension==3)then
! Flip hyperplane normal if it points away from cell centroid
do i=1,num_cells
centx=cell_centroid(i,1)
centy=cell_centroid(i,2)
centz=cell_centroid(i,3)
distmin=1000.
do k=1,num_faces_sub(i)
rnorx=face_sub(i,k,1)
rnory=face_sub(i,k,2)
rnorz=face_sub(i,k,3)
roff=face_sub(i,k,4)
dotprod=centx*rnorx+centy*rnory+centz*rnorz+roff
if(dotprod<0.)then
face_sub(i,k,1)=-face_sub(i,k,1)
face_sub(i,k,2)=-face_sub(i,k,2)
face_sub(i,k,3)=-face_sub(i,k,3)
face_sub(i,k,4)=-face_sub(i,k,4)
endif
enddo
enddo
endif
close(unit=21)
deallocate(num_verts,xv_cor,yv_cor)
if(idimension==3)deallocate(zv_cor,facet,cor,offset,hyp_list,num_cell_hyp)
end subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Make Squares - Return Arrays of Cell Faces and Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine make_square(i,j,k,grain_length,num_faces,face,cell_centroid,mesh_type)
!
integer num_faces,m
double precision grain_length,centrex,centrey,centrez,rsign,xnor,ynor,znor
double precision rdist
double precision,dimension(3)::cell_centroid
double precision,dimension(6,4)::face
!
!
num_faces=4
centrex=(i-1)*Grain_length+Grain_length/2.d0
centrey=(j-1)*Grain_length+Grain_length/2.d0
if(mesh_type==3)then
centrez=(k-1)*Grain_length+Grain_length/2.d0
else
centrez=0.d0
endif
!
! Centroid
cell_centroid(1)=centrex
cell_centroid(2)=centrey
cell_centroid(3)=centrez
!
! Faces
do m=1,num_faces
rsign=1.d0
xnor=0.d0
ynor=0.d0
znor=0.d0
unitx=grain_length/2.d0
unity=grain_length/2.d0
if(mod(m,2)==0)rsign=-1.d0
if(m<=2)then
x1=centrex+rsign*unitx
x2=centrex+rsign*unitx
y1=centrey+unity
y2=centrey-unity
else
x1=centrex+unitx
x2=centrex-unitx
y1=centrey+rsign*unity
y2=centrey+rsign*unity
endif
face(m,1)=x1
face(m,2)=x2
face(m,3)=y1
face(m,4)=y2
enddo
end Subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Make Hexagons - Return Arrays of Cell Faces and Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine make_hexagon(i,j,k,grain_length,num_faces,face,cell_centroid,mesh_type)
integer num_faces,m
double precision grain_length,centrex,centrey,centrez,rsign,xnor,ynor,znor
double precision rdist
double precision,dimension(3)::cell_centroid
double precision,dimension(6,4)::face
!
!
num_faces=6
if(mod(j,2)==0)then
centrex=(i-1)*sqrt(3.d0)*Grain_length+sqrt(3.d0)*Grain_length/2.d0
else
centrex=(i-1)*sqrt(3.)*Grain_length
endif
centrey=(j-1)*1.5d0*Grain_length
if(mesh_type==3)then
centrez=(k-1)*Grain_length
else
centrez=0.d0
endif
!
! Centroid
cell_centroid(1)=centrex
cell_centroid(2)=centrey
cell_centroid(3)=centrez
!
! Faces
do m=1,num_faces
rsign=1.d0
rsign2=1.d0
xnor=0.d0
ynor=0.d0
znor=0.d0
unity=0.5d0*grain_length
unitx=(sqrt(3.d0)/2.d0)*grain_length
if(mod(m,2)==0)rsign=-1.d0
if(m<=2)then
x1=centrex+rsign*unitx
x2=centrex+rsign*unitx
y1=centrey+unity
y2=centrey-unity
elseif(m>2.and.m<=4)then
x1=centrex
x2=centrex+unitx
y1=centrey+rsign*unity*2.d0
y2=centrey+rsign*unity
else
x1=centrex
x2=centrex-unitx
y1=centrey+rsign*unity*2.d0
y2=centrey+rsign*unity
endif
face(m,1)=x1
face(m,2)=x2
face(m,3)=y1
face(m,4)=y2
enddo
end Subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Get Element Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine elem_centroids(ne,ele_centroid,mesh_type)
!
! Parameters
parameter(max_nodes=1000000,max_elements=100000,max_node_in_elem=8)
!
! Variables
character(len=256)input
integer,dimension(max_elements,max_node_in_elem)::elements
double precision,dimension(max_nodes,3)::nodes
double precision,dimension(max_elements,3)::ele_centroid
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='GeomGenTemp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
if(mesh_type==3)then
read(10,*)dummy,nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
read(10,*)dummy,nodes(nn,1),nodes(nn,2)
endif
else
if(mesh_type==2)then
nele_type=4
else
if(index(input,'C3D8')/=0)nele_type=8
if(index(input,'C3D4')/=0)nele_type=4
endif
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
if(nele_type==8)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
elseif(nele_type==4)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)
endif
else
exit
endif
end do
!
! Get element centroid
do i=1,ne
centroidx=0.d0
centroidy=0.d0
centroidz=0.d0
do j=1,nele_type
centroidx=centroidx+nodes(elements(i,j),1)
centroidy=centroidy+nodes(elements(i,j),2)
if(mesh_type==3)centroidz=centroidz+nodes(elements(i,j),3)
enddo
ele_centroid(i,1)=centroidx/float(nele_type)
ele_centroid(i,2)=centroidy/float(nele_type)
if(mesh_type==3)ele_centroid(i,3)=centroidz/float(nele_type)
enddo
end subroutine

View file

@ -0,0 +1,200 @@
! This program generates a micro-strucutre mask and applies it to
! an existing mesh.
! J.Grogan 05/08/11
program Corrosion_Preprocessor
!
! Parameters
parameter(max_elements=100000,max_cells=20000,max_fc=100,max_faces=10000)
parameter(max_elem_in_cell=50000,max_neigh_per_elem=6,max_neighbours=50)
!
! Variables
character(len=256)input
character(len=256)input2(2)
integer,allocatable,dimension(:)::num_faces
integer,dimension(max_elements,max_neighbours)::neighbour
integer mesh_type
double precision,allocatable,dimension(:,:)::distance
double precision,allocatable,dimension(:,:)::nbr_dist
double precision,allocatable,dimension(:,:)::cor_faces
double precision,dimension(max_elements)::cor_dist
double precision,allocatable,dimension(:,:)::ele_centroid
!
! Mesh Type: 2 = 2D, 3 = 3D
mesh_type=3
!
allocate(ele_centroid(max_elements,3))
! Get element centroids
call elem_centroids(num_elements,ele_centroid,mesh_type)
!
! Get neighbouring elements
allocate(nbr_dist(max_elements,max_neighbours))
do i=1,num_elements
icount=1
do j=1,num_elements
if(icount>max_neighbours)then
rmaxdist=0.
do k=1,max_neighbours
if(nbr_dist(i,k)>rmaxdist)then
rmaxdist=nbr_dist(i,k)
index_max_dist=k
endif
enddo
endif
cent1x=ele_centroid(i,1)
cent1y=ele_centroid(i,2)
cent1z=ele_centroid(i,3)
cent2x=ele_centroid(j,1)
cent2y=ele_centroid(j,2)
cent2z=ele_centroid(j,3)
dist=sqrt((cent1x-cent2x)*(cent1x-cent2x)+(cent1y-cent2y)*(cent1y-cent2y)&
&+(cent1z-cent2z)*(cent1z-cent2z))
if(icount>max_neighbours)then
if(dist<rmaxdist)then
nbr_dist(i,index_max_dist)=dist
neighbour(i,index_max_dist)=j
endif
else
nbr_dist(i,j)=dist
neighbour(i,j)=j
endif
icount=icount+1
enddo
print *,float(i)/float(num_elements)
enddo
deallocate(nbr_dist)
!
! Get corrosion surface distances
open(unit=22,file='CorSurf.dat',status='unknown')
allocate(cor_faces(max_faces,3))
ierr=0
inum_faces=1
do while (ierr==0)
read(22,*,iostat=ierr)cor_faces(inum_faces,1),cor_faces(inum_faces,2),&
&cor_faces(inum_faces,3)
if(ierr==0)inum_faces=inum_faces+1
enddo
close(unit=22)
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
distmin=1000.
do j=1,inum_faces-1
facex=cor_faces(j,1)
facey=cor_faces(j,2)
facez=cor_faces(j,3)
dist=sqrt((centx-facex)*(centx-facex)+(centy-facey)*(centy-facey)&
&+(centz-facez)*(centz-facez))
if(dist<distmin)distmin=dist
enddo
cor_dist(i)=distmin
enddo
deallocate(cor_faces)
!
rewind(10)
open(unit=13,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(13,'(a)')'*End Assembly'
write(13,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
do i=1,num_elements
write(13,'(3(a,i6),2(a,f18.6),3(i6,a))')'Assembly.CorPart.',i,',' &
& ,i,',',max_neighbours,',',0.,',',cor_dist(i,j),0,',',1.,',',0,','
do k=1, max_neighbours
if(mod(k,8)/=0)then
if(k/=max_neighbours)then
write(13,'(i6,a)',advance='no')neighbour(i,k),','
else
write(13,'(i6)')neighbour(i,k)
endif
else
if(k/=max_neighbours)then
write(13,'(i6,a)')neighbour(i,k),','
else
write(13,'(i6)')neighbour(i,k)
endif
endif
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(13,'(a)')input2(1)
enddo
end program
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Get Element Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine elem_centroids(ne,ele_centroid,mesh_type)
!
! Parameters
parameter(max_nodes=1000000,max_elements=100000,max_node_in_elem=8)
!
! Variables
character(len=256)input
integer,dimension(max_elements,max_node_in_elem)::elements
double precision,dimension(max_nodes,3)::nodes
double precision,dimension(max_elements,3)::ele_centroid
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='GeomGenTemp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
if(mesh_type==3)then
read(10,*)dummy,nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
read(10,*)dummy,nodes(nn,1),nodes(nn,2)
endif
else
if(mesh_type==2)then
nele_type=4
else
if(index(input,'C3D8')/=0)nele_type=8
if(index(input,'C3D4')/=0)nele_type=4
endif
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
if(nele_type==8)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
elseif(nele_type==4)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)
endif
else
exit
endif
end do
!
! Get element centroid
do i=1,ne
centroidx=0.d0
centroidy=0.d0
centroidz=0.d0
do j=1,nele_type
centroidx=centroidx+nodes(elements(i,j),1)
centroidy=centroidy+nodes(elements(i,j),2)
if(mesh_type==3)centroidz=centroidz+nodes(elements(i,j),3)
enddo
ele_centroid(i,1)=centroidx/float(nele_type)
ele_centroid(i,2)=centroidy/float(nele_type)
if(mesh_type==3)ele_centroid(i,3)=centroidz/float(nele_type)
enddo
end subroutine

View file

@ -0,0 +1,750 @@
! This program generates a micro-strucutre mask and applies it to
! an existing mesh.
! J.Grogan 05/08/11
program Voronoi3DPost
!
! Parameters
parameter(max_elements=100000,max_cells=20000,max_fc=100,max_faces=10000)
parameter(max_elem_in_cell=50000,max_neigh_per_elem=6,max_neighbours=50)
!
! Variables
character(len=256)input
character(len=256)input2(2)
integer cell_stat(20000)
integer,allocatable,dimension(:)::closest
integer,allocatable,dimension(:)::num_ele_cell
integer,allocatable,dimension(:)::num_faces
integer,allocatable,dimension(:)::cell_status
integer,allocatable,dimension(:,:)::cell_ele
integer,dimension(max_elements)::num_neighbours
integer,dimension(max_elements,max_neighbours)::neighbour
integer mesh_type,mask_type,num_x,num_y,num_z,num_grains
double precision grain_length,rad_hard,rscale
double precision,allocatable,dimension(:,:)::distance
double precision,allocatable,dimension(:,:)::nbr_dist
double precision,allocatable,dimension(:,:)::cor_faces
double precision,dimension(max_elements)::cor_dist
double precision,allocatable,dimension(:,:)::ele_centroid
double precision,allocatable,dimension(:,:)::cell_centroid
double precision,allocatable,dimension(:,:,:)::face
!
! Mesh Type: 2 = 2D, 3 = 3D
mesh_type=3
! Mask Type: 1= Square, 2= Hexagon, 3= Dodec, 4=2D Voronoi, 5=3D Voronoi
mask_type=5
! Grain Length
Grain_length=0.025
! Num grains x
num_x=10
! Num grains y
num_y=10
! Num grains z
num_z=1
! Hardcore Voronoi Radius
rad_hard=0.00
num_grains=num_x*num_y*num_z
if(mask_type>3)then
! Create Tessellation
allocate(face(max_cells,max_fc,4),num_faces(max_cells),cell_centroid(max_cells,3))
call make_voronoi(mask_type,mesh_type,num_grains,num_x,rad_hard,grain_length)
call process_voronoi(face,num_faces,cell_centroid,num_cells,cell_stat)
else
! Generate Centroids and faces for other geometries
icount=1
num_cells=num_grains
allocate(face(num_cells,6,4),num_faces(num_cells),cell_centroid(num_cells,3))
do i=1,num_x
do j=1,num_y
do k=1,num_z
if(mask_type==1)then
call make_square(i,j,k,grain_length,num_faces(icount), &
& face(icount,:,:),cell_centroid(icount,:),mesh_type)
elseif(mask_type==2)then
call make_hexagon(i,j,k,grain_length,num_faces(icount), &
& face(icount,:,:),cell_centroid(icount,:),mesh_type)
else
if(mod(j,2)==0)then
cell_centroid(icount,1)=2.*(i-1)*Grain_length*sqrt(2.)+&
&sqrt(2.)*Grain_length
cell_centroid(icount,3)=2.*(k-1)*Grain_length*sqrt(2.)+&
&Grain_length*sqrt(2.)
else
cell_centroid(icount,1)=2.*(i-1)*Grain_length*sqrt(2.)
cell_centroid(icount,3)=2.*(k-1)*Grain_length*sqrt(2.)
endif
cell_centroid(icount,2)=2.*(j-1)*Grain_length
endif
icount=icount+1
enddo
enddo
enddo
endif
!
allocate(ele_centroid(max_elements,3))
! Get element centroids
call elem_centroids(num_elements,ele_centroid,mesh_type)
!
! Get neighbouring elements
allocate(nbr_dist(max_elements,max_neighbours))
do i=1,num_elements
icount=1
do j=1,num_elements
if(icount>max_neighbours)then
rmaxdist=0.
do k=1,max_neighbours
if(nbr_dist(i,k)>rmaxdist)then
rmaxdist=nbr_dist(i,k)
index_max_dist=k
endif
enddo
endif
cent1x=ele_centroid(i,1)
cent1y=ele_centroid(i,2)
cent1z=ele_centroid(i,3)
cent2x=ele_centroid(j,1)
cent2y=ele_centroid(j,2)
cent2z=ele_centroid(j,3)
dist=sqrt((cent1x-cent2x)*(cent1x-cent2x)+(cent1y-cent2y)*(cent1y-cent2y)&
&+(cent1z-cent2z)*(cent1z-cent2z))
if(icount>max_neighbours)then
if(dist<rmaxdist)then
nbr_dist(i,index_max_dist)=dist
neighbour(i,index_max_dist)=j
endif
else
nbr_dist(i,j)=dist
neighbour(i,j)=j
endif
icount=icount+1
enddo
print *,float(i)/float(num_elements)
enddo
deallocate(nbr_dist)
!
! Get corrosion surface distances
open(unit=22,file='CorSurf.dat',status='unknown')
allocate(cor_faces(max_faces,3))
ierr=0
inum_faces=1
do while (ierr==0)
read(22,*,iostat=ierr)cor_faces(inum_faces,1),cor_faces(inum_faces,2),&
&cor_faces(inum_faces,3)
if(ierr==0)inum_faces=inum_faces+1
enddo
close(unit=22)
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
distmin=1000.
do j=1,inum_faces-1
facex=cor_faces(j,1)
facey=cor_faces(j,2)
facez=cor_faces(j,3)
dist=sqrt((centx-facex)*(centx-facex)+(centy-facey)*(centy-facey)&
&+(centz-facez)*(centz-facez))
if(dist<distmin)distmin=dist
enddo
cor_dist(i)=distmin
enddo
deallocate(cor_faces)
!
! Find closest cell to element centroid
allocate(closest(max_elements))
if(mask_type==5)then
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
do j=1,num_cells
if(num_faces(j)<3)then
print *,'warning',i,j,num_faces(j)
cycle
endif
if(cell_stat(j)==1)cycle
icheck=0
do k=1,num_faces(j)
rnorx=face(j,k,1)
rnory=face(j,k,2)
rnorz=face(j,k,3)
roff=face(j,k,4)
dotprod=centx*rnorx+centy*rnory+centz*rnorz+roff
if(dotprod<0.)then
icheck=1
exit
endif
enddo
if(icheck==0)then
closest(i)=j
endif
enddo
enddo
else
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
do j=1,num_cells
if(cell_stat(j)==1)cycle
cellx=cell_centroid(j,1)
celly=cell_centroid(j,2)
icheck=0
do k=1,num_faces(j)
fx1=face(j,k,1)
fx2=face(j,k,2)
fy1=face(j,k,3)
fy2=face(j,k,4)
dcell=(fx2-fx1)*(celly-fy1)-(fy2-fy1)*(cellx-fx1)
dele=(fx2-fx1)*(centy-fy1)-(fy2-fy1)*(centx-fx1)
if(dcell<0.)then
if(dele>=0.)icheck=1
else
if(dele<0.)icheck=1
endif
if(icheck==1)exit
enddo
if(icheck==0)then
closest(i)=j
endif
enddo
enddo
endif
!
allocate(num_ele_cell(num_cells),cell_ele(num_cells,max_elem_in_cell))
! Find each element in a cell
do i=1,num_cells
num_ele_cell(i)=0
do j=1,num_elements
if(closest(j)==i)then
num_ele_cell(i)=num_ele_cell(i)+1
cell_ele(i,num_ele_cell(i))=j
endif
enddo
enddo
!
!
allocate(distance(num_cells,num_elements))
! Find min distance between element centroid and cell faces/hyperplanes
do i=1,num_cells
if(i==1406) print *,num_faces(i)
do j=1,num_ele_cell(i)
centx=ele_centroid(cell_ele(i,j),1)
centy=ele_centroid(cell_ele(i,j),2)
centz=ele_centroid(cell_ele(i,j),3)
distmin=1000.
if(mask_type==5)then
do k=1,num_faces(i)
rnorx=face(i,k,1)
rnory=face(i,k,2)
rnorz=face(i,k,3)
roff=face(i,k,4)
dotprod=abs(centx*rnorx+centy*rnory+centz*rnorz+roff)
if(dotprod<distmin)distmin=dotprod
enddo
else
do k=1,num_faces(i)
x1=face(i,k,1)
x2=face(i,k,2)
y1=face(i,k,3)
y2=face(i,k,4)
dotprod=abs((x2-x1)*(y1-centy)-(x1-centx)*(y2-y1))
dotprod=dotprod/(sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)))
if(dotprod<distmin)distmin=dotprod
enddo
endif
distance(i,j)=distmin
enddo
enddo
!
! Write Element Sets
rewind(10)
open(unit=13,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Part')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
do i=1,num_cells
if(num_ele_cell(i)==0)cycle
write(13,*)'*Elset,elset=ele',i
icheck=1
do j=1,num_ele_cell(i)
if(icheck==1)then
if(num_ele_cell(i)>1)then
write(13,'(i6)',advance='no')cell_ele(i,j)
else
write(13,'(i6)')cell_ele(i,j)
endif
elseif(icheck==num_ele_cell(i))then
write(13,'(a1,i6)')',',cell_ele(i,j)
else
if(mod(icheck,15)==0)then
write(13,'(a1,i6)')',',cell_ele(i,j)
else
write(13,'(a1,i6)',advance='no')',',cell_ele(i,j)
endif
endif
icheck=icheck+1
enddo
if(iana_type==1)write(19,*)'*Solid Section,elset=ele',i,'Boundary,material=Mat',i
enddo
write(13,*)'**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(13,'(a)')'*End Assembly'
write(13,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
do i=1,num_cells
if(num_ele_cell(i)==0)cycle
do j=1,num_ele_cell(i)
write(13,'(3(a,i6),2(a,f18.6),3(i6,a))')'Assembly.CorPart.',cell_ele(i,j),',' &
& ,cell_ele(i,j),',',max_neighbours,',',distance(i,j),',',cor_dist(cell_ele(i,j)) &
& ,0,',',0,',',0,','
write(13,'(8(i6,a))')0,',',0,',',0,',',0,',',0,',',0,',',0,',',1,','
do k=1, max_neighbours
if(mod(k,8)/=0)then
if(k/=max_neighbours)then
write(13,'(i6,a)',advance='no')neighbour(cell_ele(i,j),k),','
else
write(13,'(i6)')neighbour(cell_ele(i,j),k)
endif
else
if(k/=max_neighbours)then
write(13,'(i6,a)')neighbour(cell_ele(i,j),k),','
else
write(13,'(i6)')neighbour(cell_ele(i,j),k)
endif
endif
enddo
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(13,'(a)')input2(1)
enddo
end program
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Generate Voronoi Tesselation Using QHULL
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine make_voronoi(mask_type,mesh_type,num_grains,num_x,rad_hard,grain_length)
integer mesh_type,mask_type,num_grains
integer seed(1)
double precision grain_length,rad_hard,rscale
if(mesh_type==2)mask_type=4
! Write QHull input file
open(unit=20,file='qhullin.dat',status='unknown')
write(20,*)mask_type-2
if(mask_type==5)write(20,*)num_grains*27
if(mask_type==4)write(20,*)num_grains*9
seed=1557
rscale=float(num_x)*Grain_Length
call random_seed(put=seed)
do i=1,num_grains
call random_number(xcor)
call random_number(ycor)
if(mask_type==5)call random_number(zcor)
xcor=xcor*rscale
ycor=ycor*rscale
if(mask_type==5)zcor=zcor*rscale
if(mask_type==4)then
write(20,*)xcor,ycor
write(20,*)xcor,ycor+rscale
write(20,*)xcor,ycor-rscale
write(20,*)xcor+rscale,ycor
write(20,*)xcor-rscale,ycor
write(20,*)xcor+rscale,ycor+rscale
write(20,*)xcor-rscale,ycor-rscale
write(20,*)xcor+rscale,ycor-rscale
write(20,*)xcor-rscale,ycor+rscale
elseif(mask_type==5)then
write(20,*)xcor,ycor,zcor
write(20,*)xcor+rscale,ycor,zcor
write(20,*)xcor-rscale,ycor,zcor
write(20,*)xcor,ycor+rscale,zcor
write(20,*)xcor,ycor-rscale,zcor
write(20,*)xcor+rscale,ycor+rscale,zcor
write(20,*)xcor-rscale,ycor-rscale,zcor
write(20,*)xcor+rscale,ycor-rscale,zcor
write(20,*)xcor-rscale,ycor+rscale,zcor
write(20,*)xcor,ycor,zcor+rscale
write(20,*)xcor+rscale,ycor,zcor+rscale
write(20,*)xcor-rscale,ycor,zcor+rscale
write(20,*)xcor,ycor+rscale,zcor+rscale
write(20,*)xcor,ycor-rscale,zcor+rscale
write(20,*)xcor+rscale,ycor+rscale,zcor+rscale
write(20,*)xcor-rscale,ycor-rscale,zcor+rscale
write(20,*)xcor+rscale,ycor-rscale,zcor+rscale
write(20,*)xcor-rscale,ycor+rscale,zcor+rscale
write(20,*)xcor,ycor,zcor-rscale
write(20,*)xcor+rscale,ycor,zcor-rscale
write(20,*)xcor-rscale,ycor,zcor-rscale
write(20,*)xcor,ycor+rscale,zcor-rscale
write(20,*)xcor,ycor-rscale,zcor-rscale
write(20,*)xcor+rscale,ycor+rscale,zcor-rscale
write(20,*)xcor-rscale,ycor-rscale,zcor-rscale
write(20,*)xcor+rscale,ycor-rscale,zcor-rscale
write(20,*)xcor-rscale,ycor+rscale,zcor-rscale
endif
enddo
close(20)
call system('qvoronoi.exe TI qhullin.dat o Fi TO qhullout.dat')
end subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Process Voronoi Tesselation - Return Arrays of Cell Faces and Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine process_voronoi(face_sub,num_faces_sub,cell_centroid,num_cells,cell_stat)
!
! Variables
character(len=320)full_line
character(len=320)test_string
character(len=256)input
character(len=256)input2(2)
integer seed (1)
integer cell_stat(20000)
integer,allocatable,dimension(:)::num_verts
integer,allocatable,dimension(:)::num_cell_hyp
integer,allocatable,dimension(:)::numverts
integer,dimension(20000)::num_faces_sub
integer,allocatable,dimension(:,:)::num_hyp_verts
integer,allocatable,dimension(:,:)::vert_list
integer,allocatable,dimension(:,:)::hyp_list
integer,allocatable,dimension(:,:)::facet
integer max_vc,max_hc,max_vh
double precision,allocatable,dimension(:)::xv_cor
double precision,allocatable,dimension(:)::yv_cor
double precision,allocatable,dimension(:)::zv_cor
double precision,allocatable,dimension(:)::offset
double precision,allocatable,dimension(:,:)::cor
double precision,allocatable,dimension(:,:)::ele_centroid
double precision,dimension(20000,3)::cell_centroid
double precision,dimension(20000,100,4)::face_sub
!
! Parameters
parameter(max_vc=100,max_hc=100,max_vh=50)
!
open(unit=21,file='qhullout.dat',status='unknown')
!
! Allocate Arrays
read(21,*)idimension
read(21,*)num_total_verts,num_cells
allocate(num_verts(num_cells))
allocate(xv_cor(num_total_verts),yv_cor(num_total_verts))
if(idimension==3)allocate(zv_cor(num_total_verts))
allocate(vert_list(num_cells,max_vc))
!
! Read in all vertice co-ordinates
do i=1,num_total_verts
if(idimension==2)read(21,*)xv_cor(i),yv_cor(i)
if(idimension==3)read(21,*)xv_cor(i),yv_cor(i),zv_cor(i)
enddo
!
! Read in vertice labels for each voronoi cell
do i=1,num_cells
read(21,*)num_verts(i)
backspace(21)
if(num_verts(i)>9)then
read(21,'(i3,a320)')idummy,full_line
else
read(21,'(i2,a320)')idummy,full_line
endif
ileft=1
num_points=1
do iright=1,320
test_string=full_line(iright:iright)
if((test_string==' ').or.(iright==320))then
read(full_line(ileft:iright-1),'(i6)')vert_list(i,num_points)
if(num_points==num_verts(i))exit
ileft=iright+1
num_points=num_points+1
endif
enddo
do j=1,num_points-1
if(vert_list(i,j)==0)cell_stat(i)=1
enddo
enddo
if(idimension==3)then
!
! Read in bounded hyperplane cell labels and co-ordinates
read(21,*)num_hyp
allocate(facet(2,num_hyp),cor(3,num_hyp),offset(num_hyp))
allocate(hyp_list(num_cells,num_hyp),num_cell_hyp(num_cells))
!
do i=1,num_hyp
read(21,*)dummy,facet(1,i),facet(2,i),cor(1,i),cor(2,i),cor(3,i),offset(i)
enddo
!
! Determine hyperplanes of each cell
do i=1,num_cells
num_hy=1
do j=1,num_hyp
if((facet(1,j)==i-1).or.(facet(2,j)==i-1))then
hyp_list(i,num_hy)=j
num_cell_hyp(i)=num_hy
num_hy=num_hy+1
endif
enddo
enddo
!
! Store hyperplane info in convenient format
do i=1,num_cells
num_faces_sub(i)=num_cell_hyp(i)
do j=1,num_cell_hyp(i)
face_sub(i,j,1)=cor(1,hyp_list(i,j))
face_sub(i,j,2)=cor(2,hyp_list(i,j))
face_sub(i,j,3)=cor(3,hyp_list(i,j))
face_sub(i,j,4)=offset(hyp_list(i,j))
enddo
enddo
else
do i=1,num_cells
num_faces_sub(i)=num_verts(i)
do j=1,num_verts(i)
x2=xv_cor(vert_list(i,j)+1)
y2=yv_cor(vert_list(i,j)+1)
if(j==1)then
x1=xv_cor(vert_list(i,num_verts(i))+1)
y1=yv_cor(vert_list(i,num_verts(i))+1)
else
x1=xv_cor(vert_list(i,j-1)+1)
y1=yv_cor(vert_list(i,j-1)+1)
endif
face_sub(i,j,1)=x1
face_sub(i,j,2)=x2
face_sub(i,j,3)=y1
face_sub(i,j,4)=y2
enddo
enddo
endif
!
! Get cell centroid
do i=1,num_cells
centroidx=0.
centroidy=0.
centroidz=0.
do j=1,num_verts(i)
centroidx=centroidx+xv_cor(vert_list(i,j)+1)
centroidy=centroidy+yv_cor(vert_list(i,j)+1)
if(idimension==3)centroidz=centroidz+zv_cor(vert_list(i,j)+1)
enddo
cell_centroid(i,1)=centroidx/float(num_verts(i))
cell_centroid(i,2)=centroidy/float(num_verts(i))
if(idimension==3)then
cell_centroid(i,3)=centroidz/float(num_verts(i))
else
cell_centroid(i,3)=0.d0
endif
enddo
if(idimension==3)then
! Flip hyperplane normal if it points away from cell centroid
do i=1,num_cells
centx=cell_centroid(i,1)
centy=cell_centroid(i,2)
centz=cell_centroid(i,3)
distmin=1000.
do k=1,num_faces_sub(i)
rnorx=face_sub(i,k,1)
rnory=face_sub(i,k,2)
rnorz=face_sub(i,k,3)
roff=face_sub(i,k,4)
dotprod=centx*rnorx+centy*rnory+centz*rnorz+roff
if(dotprod<0.)then
face_sub(i,k,1)=-face_sub(i,k,1)
face_sub(i,k,2)=-face_sub(i,k,2)
face_sub(i,k,3)=-face_sub(i,k,3)
face_sub(i,k,4)=-face_sub(i,k,4)
endif
enddo
enddo
endif
close(unit=21)
deallocate(num_verts,xv_cor,yv_cor)
if(idimension==3)deallocate(zv_cor,facet,cor,offset,hyp_list,num_cell_hyp)
end subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Make Squares - Return Arrays of Cell Faces and Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine make_square(i,j,k,grain_length,num_faces,face,cell_centroid,mesh_type)
!
integer num_faces,m
double precision grain_length,centrex,centrey,centrez,rsign,xnor,ynor,znor
double precision rdist
double precision,dimension(3)::cell_centroid
double precision,dimension(6,4)::face
!
!
num_faces=4
centrex=(i-1)*Grain_length+Grain_length/2.d0
centrey=(j-1)*Grain_length+Grain_length/2.d0
if(mesh_type==3)then
centrez=(k-1)*Grain_length+Grain_length/2.d0
else
centrez=0.d0
endif
!
! Centroid
cell_centroid(1)=centrex
cell_centroid(2)=centrey
cell_centroid(3)=centrez
!
! Faces
do m=1,num_faces
rsign=1.d0
xnor=0.d0
ynor=0.d0
znor=0.d0
unitx=grain_length/2.d0
unity=grain_length/2.d0
if(mod(m,2)==0)rsign=-1.d0
if(m<=2)then
x1=centrex+rsign*unitx
x2=centrex+rsign*unitx
y1=centrey+unity
y2=centrey-unity
else
x1=centrex+unitx
x2=centrex-unitx
y1=centrey+rsign*unity
y2=centrey+rsign*unity
endif
face(m,1)=x1
face(m,2)=x2
face(m,3)=y1
face(m,4)=y2
enddo
end Subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Make Hexagons - Return Arrays of Cell Faces and Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine make_hexagon(i,j,k,grain_length,num_faces,face,cell_centroid,mesh_type)
integer num_faces,m
double precision grain_length,centrex,centrey,centrez,rsign,xnor,ynor,znor
double precision rdist
double precision,dimension(3)::cell_centroid
double precision,dimension(6,4)::face
!
!
num_faces=6
if(mod(j,2)==0)then
centrex=(i-1)*sqrt(3.d0)*Grain_length+sqrt(3.d0)*Grain_length/2.d0
else
centrex=(i-1)*sqrt(3.)*Grain_length
endif
centrey=(j-1)*1.5d0*Grain_length
if(mesh_type==3)then
centrez=(k-1)*Grain_length
else
centrez=0.d0
endif
!
! Centroid
cell_centroid(1)=centrex
cell_centroid(2)=centrey
cell_centroid(3)=centrez
!
! Faces
do m=1,num_faces
rsign=1.d0
rsign2=1.d0
xnor=0.d0
ynor=0.d0
znor=0.d0
unity=0.5d0*grain_length
unitx=(sqrt(3.d0)/2.d0)*grain_length
if(mod(m,2)==0)rsign=-1.d0
if(m<=2)then
x1=centrex+rsign*unitx
x2=centrex+rsign*unitx
y1=centrey+unity
y2=centrey-unity
elseif(m>2.and.m<=4)then
x1=centrex
x2=centrex+unitx
y1=centrey+rsign*unity*2.d0
y2=centrey+rsign*unity
else
x1=centrex
x2=centrex-unitx
y1=centrey+rsign*unity*2.d0
y2=centrey+rsign*unity
endif
face(m,1)=x1
face(m,2)=x2
face(m,3)=y1
face(m,4)=y2
enddo
end Subroutine
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Get Element Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine elem_centroids(ne,ele_centroid,mesh_type)
!
! Parameters
parameter(max_nodes=1000000,max_elements=100000,max_node_in_elem=8)
!
! Variables
character(len=256)input
integer,dimension(max_elements,max_node_in_elem)::elements
double precision,dimension(max_nodes,3)::nodes
double precision,dimension(max_elements,3)::ele_centroid
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='GeomGenTemp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
if(mesh_type==3)then
read(10,*)dummy,nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
read(10,*)dummy,nodes(nn,1),nodes(nn,2)
endif
else
if(mesh_type==2)then
nele_type=4
else
if(index(input,'C3D8')/=0)nele_type=8
if(index(input,'C3D4')/=0)nele_type=4
endif
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
if(nele_type==8)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
elseif(nele_type==4)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)
endif
else
exit
endif
end do
!
! Get element centroid
do i=1,ne
centroidx=0.d0
centroidy=0.d0
centroidz=0.d0
do j=1,nele_type
centroidx=centroidx+nodes(elements(i,j),1)
centroidy=centroidy+nodes(elements(i,j),2)
if(mesh_type==3)centroidz=centroidz+nodes(elements(i,j),3)
enddo
ele_centroid(i,1)=centroidx/float(nele_type)
ele_centroid(i,2)=centroidy/float(nele_type)
if(mesh_type==3)ele_centroid(i,3)=centroidz/float(nele_type)
enddo
end subroutine

View file

@ -0,0 +1,205 @@
! This program generates a micro-strucutre mask and applies it to
! an existing mesh.
! J.Grogan 05/08/11
program Corrosion_Preprocessor
!
! Parameters
parameter(max_elements=600000,max_cells=20000,max_fc=100,max_faces=10000)
parameter(max_elem_in_cell=50000,max_neigh_per_elem=6,max_neighbours=50)
!
! Variables
character(len=256)input
character(len=256)input2(2)
integer,allocatable,dimension(:)::num_faces
integer,dimension(max_elements,max_neighbours)::neighbour
integer mesh_type
integer(1) iseed
double precision,allocatable,dimension(:,:)::distance
double precision,allocatable,dimension(:,:)::nbr_dist
double precision,allocatable,dimension(:,:)::cor_faces
double precision,dimension(max_elements)::cor_dist
double precision,allocatable,dimension(:,:)::ele_centroid
!
! Mesh Type: 2 = 2D, 3 = 3D
mesh_type=3
iseed=3
call random_seed(iseed)
!
allocate(ele_centroid(max_elements,3))
! Get element centroids
call elem_centroids(num_elements,ele_centroid,mesh_type)
!
! Get neighbouring elements
allocate(nbr_dist(max_elements,max_neighbours))
do i=1,num_elements
icount=1
do j=1,num_elements
if(icount>max_neighbours)then
rmaxdist=0.
do k=1,max_neighbours
if(nbr_dist(i,k)>rmaxdist)then
rmaxdist=nbr_dist(i,k)
index_max_dist=k
endif
enddo
endif
cent1x=ele_centroid(i,1)
cent1y=ele_centroid(i,2)
cent1z=ele_centroid(i,3)
cent2x=ele_centroid(j,1)
cent2y=ele_centroid(j,2)
cent2z=ele_centroid(j,3)
dist=sqrt((cent1x-cent2x)*(cent1x-cent2x)+(cent1y-cent2y)*(cent1y-cent2y)&
&+(cent1z-cent2z)*(cent1z-cent2z))
if(icount>max_neighbours)then
if(dist<rmaxdist)then
nbr_dist(i,index_max_dist)=dist
neighbour(i,index_max_dist)=j
endif
else
nbr_dist(i,j)=dist
neighbour(i,j)=j
endif
icount=icount+1
enddo
print *,float(i)/float(num_elements)
enddo
deallocate(nbr_dist)
!
! Get corrosion surface distances
open(unit=22,file='CorSurf.dat',status='unknown')
allocate(cor_faces(max_faces,3))
ierr=0
inum_faces=1
do while (ierr==0)
read(22,*,iostat=ierr)cor_faces(inum_faces,1),cor_faces(inum_faces,2),&
&cor_faces(inum_faces,3)
if(ierr==0)inum_faces=inum_faces+1
enddo
close(unit=22)
do i=1,num_elements
centx=ele_centroid(i,1)
centy=ele_centroid(i,2)
centz=ele_centroid(i,3)
distmin=1000.
do j=1,inum_faces-1
facex=cor_faces(j,1)
facey=cor_faces(j,2)
facez=cor_faces(j,3)
dist=sqrt((centx-facex)*(centx-facex)+(centy-facey)*(centy-facey)&
&+(centz-facez)*(centz-facez))
if(dist<distmin)distmin=dist
enddo
cor_dist(i)=distmin
enddo
deallocate(cor_faces)
!
rewind(10)
open(unit=13,file='GeomGenINP.inp',status='unknown')
input2(1)='**'
do while (index(input2(1),'*End Assembly')==0)
read(10,'(a)')input2(2)
write(13,'(a)')input2(1)
input2(1)=input2(2)
enddo
write(13,'(a)')'*End Assembly'
write(13,*)'*INITIAL CONDITIONS,TYPE=SOLUTION'
do i=1,num_elements
call random_number(randnum)
randnum=0
write(13,'(3(a,i6),2(a,f18.6),a,2(i6,a),f18.6,a)')'Assembly.CorPart.',i,',' &
& ,i,',',max_neighbours,',',0.,',',cor_dist(i),',',0,',',1,',',randnum,','
do k=1, max_neighbours
if(mod(k,8)/=0)then
if(k/=max_neighbours)then
write(13,'(i6,a)',advance='no')neighbour(i,k),','
else
write(13,'(i6,a,f18.6,a,i6,a,i6,a,i6)')neighbour(i,k),',',cor_dist(i),',',0,',',0,',',0
endif
else
if(k/=max_neighbours)then
write(13,'(i6,a)')neighbour(i,k),','
else
write(13,'(i6,a,f18.6,a,i6,a,i6,a,i6)')neighbour(i,k),',',cor_dist(i),',',0,',',0,',',0
endif
endif
enddo
enddo
ierr=0
do while (ierr==0)
read(10,'(a)',iostat=ierr)input2(1)
if(ierr==0)write(13,'(a)')input2(1)
enddo
end program
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Get Element Centroids
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
subroutine elem_centroids(ne,ele_centroid,mesh_type)
!
! Parameters
parameter(max_nodes=6000000,max_elements=600000,max_node_in_elem=8)
!
! Variables
character(len=256)input
integer,dimension(max_elements,max_node_in_elem)::elements
double precision,dimension(max_nodes,3)::nodes
double precision,dimension(max_elements,3)::ele_centroid
!
! Open Input File and read node and element co-ordinates
open(unit=10,file='GeomGenTemp.inp',status='unknown')
do while (index(input,'*Node')==0)
read(10,'(a)')input
end do
nn=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
nn=nn+1
if(mesh_type==3)then
read(10,*)dummy,nodes(nn,1),nodes(nn,2),nodes(nn,3)
else
read(10,*)dummy,nodes(nn,1),nodes(nn,2)
endif
else
if(mesh_type==2)then
nele_type=4
else
if(index(input,'C3D8')/=0)nele_type=8
if(index(input,'C3D4')/=0)nele_type=4
endif
exit
endif
end do
ne=0
do while(1==1)
read(10,'(a)')input
if(index(input,'*')==0)then
backspace(10)
ne=ne+1
if(nele_type==8)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)&
& ,elements(ne,5),elements(ne,6),elements(ne,7),elements(ne,8)
elseif(nele_type==4)then
read(10,*)dummy,elements(ne,1),elements(ne,2),elements(ne,3),elements(ne,4)
endif
else
exit
endif
end do
!
! Get element centroid
do i=1,ne
centroidx=0.d0
centroidy=0.d0
centroidz=0.d0
do j=1,nele_type
centroidx=centroidx+nodes(elements(i,j),1)
centroidy=centroidy+nodes(elements(i,j),2)
if(mesh_type==3)centroidz=centroidz+nodes(elements(i,j),3)
enddo
ele_centroid(i,1)=centroidx/float(nele_type)
ele_centroid(i,2)=centroidy/float(nele_type)
if(mesh_type==3)ele_centroid(i,3)=centroidz/float(nele_type)
enddo
end subroutine

View file

@ -0,0 +1,88 @@
! This program takes output from the QHULL package and converts it into
! a format suitable for use with the GeomGen script
! J.Grogan 05/08/11
program Voronoi2DPost
!
! Parameters
parameter(max_verts=1000000,max_cells=100000,max_verts_in_cell=100)
!
! Variables
character(len=256)full_line,test_string
integer vnum(max_cells,max_verts_in_cell),num_verts(max_cells)
integer in_tol(max_cells)
real xv_cor(max_verts)
real yv_cor(max_verts)
logical xtrue
logical ytrue
!
! Read Scales
open(unit=15,file='scales.dat',status='unknown')
read(15,*)rmaxscale
!
! Read in vertex co-ordinates
open(unit=11,file='qhullout.dat',status='unknown')
read(11,*)
read(11,*)num_verts_tot,num_cells,dummy
do i=1,num_verts_tot
read(11,*)xv_cor(i),yv_cor(i)
enddo
!
! Read in vertices on each cell
do i=1,num_cells
read(11,*)num_verts(i)
backspace(11)
read(11,'(i2,a256)')idummy,full_line
ileft=1
num_points=1
do iright=1,256
test_string=full_line(iright:iright)
if((test_string==' ').or.(iright==256))then
read(full_line(ileft:iright-1),'(i6)')vnum(i,num_points)
if(num_points==num_verts(i))exit
ileft=iright+1
num_points=num_points+1
endif
enddo
enddo
!
! Check if cells are within specified region
open(unit=12,file='fortranout.dat',status='unknown')
num_inside_cells=num_cells
do i=1,num_cells
icheck=0
do j=1,num_verts(i)
xcor=xv_cor(vnum(i,j)+1)
ycor=yv_cor(vnum(i,j)+1)
if(abs(xcor)==10.101)then
icheck=0
exit
endif
rmax=1.1*rmaxscale
rmin=-0.1
xtrue=(xcor<rmax).and.(xcor>rmin)
ytrue=(ycor<rmax).and.(ycor>rmin)
if(xtrue.and.ytrue)icheck=icheck+1
enddo
if(icheck<1)then
in_tol(i)=2
num_inside_cells=num_inside_cells-1
else
in_tol(i)=1
endif
enddo
!
! Write vertex coordinates for each cell
write(12,*)num_inside_cells
do i=1,num_cells
if(in_tol(i)==1)then
write(12,*)num_verts(i)
do j=1,num_verts(i)
write(12,*)xv_cor(vnum(i,j)+1),',',yv_cor(vnum(i,j)+1)
enddo
else
cycle
endif
enddo
close(unit=11)
close(unit=12)
end program

View file

@ -0,0 +1,141 @@
! This program takes output from the QHULL package and converts it into
! a format suitable for use with the GeomGen script
! J.Grogan 05/08/11
program Voronoi3DPost
!
! Parameters
parameter(max_verts=500000,max_cells=50000,max_verts_in_cell=100)
parameter(max_hyps=500000,max_hyp_in_cell=100,max_verts_on_hyp=50)
!
! Variables
character(len=256)full_line,test_string
integer num_verts(max_cells)
integer vert_list(max_cells,max_verts_in_cell)
integer facet(2,max_hyps)
integer hyp_list(max_cells,max_hyp_in_cell)
integer num_cell_hyp(max_cells)
integer cell_status(max_cells)
integer num_hyp_verts(max_cells,max_hyp_in_cell)
integer hyp_vert_list(max_cells,max_hyp_in_cell,max_verts_on_hyp)
double precision xv_cor(max_verts)
double precision yv_cor(max_verts)
double precision zv_cor(max_verts)
double precision cor(3,max_hyps)
double precision offset(max_hyps)
double precision xcor,ycor,zcor
double precision dotrprod,distance,tol
logical xtrue,ytrue,ztrue
!
! Open output files
open(unit=12,file='fortranout.dat',status='unknown')
!
! Open scales file
open(unit=15,file='scales.dat',status='unknown')
read(15,*)rmaxscale
!
! Read tessellation results from QHULL
open(unit=11,file='qhullout.dat',status='unknown')
read(11,*)
read(11,*)num_total_verts,num_cells
!
! Read in all vertice co-ordinates
do i=1,num_total_verts
read(11,*)xv_cor(i),yv_cor(i),zv_cor(i)
enddo
!
! Read in vertice labels for each voronoi cell
do i=1,num_cells
read(11,*)num_verts(i)
backspace(11)
if(num_verts(i)>9)then
read(11,'(i3,a256)')idummy,full_line
else
read(11,'(i2,a256)')idummy,full_line
endif
ileft=1
num_points=1
do iright=1,256
test_string=full_line(iright:iright)
if((test_string==' ').or.(iright==256))then
read(full_line(ileft:iright-1),'(i6)')vert_list(i,num_points)
if(num_points==num_verts(i))exit
ileft=iright+1
num_points=num_points+1
endif
enddo
enddo
!
! Read in bounded hyperplane cell labels and co-ordinates
read(11,*)num_hyp
do i=1,num_hyp
read(11,*)dummy,facet(1,i),facet(2,i),cor(1,i),cor(2,i),cor(3,i),offset(i)
enddo
!
! Determine hyperplanes of each cell
do i=1,num_cells
num_hy=1
do j=1,num_hyp
if((facet(1,j)==i-1).or.(facet(2,j)==i-1))then
hyp_list(i,num_hy)=j
num_cell_hyp(i)=num_hy
num_hy=num_hy+1
endif
enddo
enddo
!
! Check if any cell vertices are outside the chosen tolerance
do i=1,num_cells
cell_status(i)=1
do j=1,num_verts(i)
xcor=xv_cor(vert_list(i,j)+1)
ycor=yv_cor(vert_list(i,j)+1)
zcor=zv_cor(vert_list(i,j)+1)
rmax=1.1*rmaxscale
rmin=-0.1
xtrue=(xcor<rmax).and.(xcor>rmin)
ytrue=(ycor<rmax).and.(ycor>rmin)
ztrue=(zcor<rmax).and.(zcor>rmin)
if(xtrue.and.ytrue.and.ztrue)cell_status(i)=0
enddo
enddo
!
! For all cells within tolerance determine vertices on each hyperplane
num_skipped=0
tol=1.e-5*rmaxscale
do i=1,num_cells
if(cell_status(i)/=0)then
num_skipped=num_skipped+1
cycle
endif
do j=1,num_cell_hyp(i)
nverts_on_hyp=1
do k=1,num_verts(i)
dotprod1=cor(1,hyp_list(i,j))*xv_cor(vert_list(i,k)+1)
dotprod2=cor(2,hyp_list(i,j))*yv_cor(vert_list(i,k)+1)
dotprod3=cor(3,hyp_list(i,j))*zv_cor(vert_list(i,k)+1)
distance=dotprod1+dotprod2+dotprod3+offset(hyp_list(i,j))
if(abs(distance)<tol)then
hyp_vert_list(i,j,nverts_on_hyp)=vert_list(i,k)
num_hyp_verts(i,j)=nverts_on_hyp
nverts_on_hyp=nverts_on_hyp+1
endif
enddo
enddo
enddo
! Write output for the of co-orindates of vertices on each hyperplane
! that make up a cell.
write(12,*)num_cells-num_skipped
do i=1,num_cells
if(cell_status(i)/=0)cycle
write(12,*)num_cell_hyp(i)
do j=1,num_cell_hyp(i)
write(12,*)num_hyp_verts(i,j)
do k=1,num_hyp_verts(i,j)
xcor=xv_cor(hyp_vert_list(i,j,k)+1)
ycor=yv_cor(hyp_vert_list(i,j,k)+1)
zcor=zv_cor(hyp_vert_list(i,j,k)+1)
write(12,'(2(f20.15,a),f20.15)')xcor,',',ycor,',',zcor
enddo
enddo
enddo
end program