Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
tutorials/polycrystalFEM/generateInputFiles.py
Go to the documentation of this file.
1"""Generate an empty XY-periodic polycrystal with FEM strain-rate loading in z."""
2import argparse
3import os
4from pathlib import Path
5import sys
6
7repository = Path(__file__).resolve().parents[2]
8parser = argparse.ArgumentParser(description=__doc__)
9parser.add_argument("--output-dir", type=Path, default=Path(__file__).resolve().parent,
10 help="Simulation folder (defaults to this tutorial folder).")
11args = parser.parse_args()
12args.output_dir.mkdir(parents=True, exist_ok=True)
13os.chdir(args.output_dir.resolve())
14sys.path.insert(0, str(repository / "python"))
15from modlibUtils import *
16
17
18# Create folder structure
19folders=['config','F','inputFiles']
20for x in folders:
21 if not os.path.exists(x):
22 os.makedirs(x)
23
24# Make a local copy of DefectiveCrystal parameters file and modify that copy if necessary
25DCfile='DefectiveCrystal.txt'
26DCfileTemplate=str(repository)+'/Library/DefectiveCrystal/'+DCfile
27print("\033[1;32mCreating DDfile\033[0m")
28shutil.copy2(DCfileTemplate,'inputFiles/'+DCfile)
29setInputVariable('inputFiles/'+DCfile,'physics','DislocationDynamics ElasticDeformation')
30setInputVariable('inputFiles/'+DCfile,'useFEM','1')
31setInputVariable('inputFiles/'+DCfile,'Nsteps','100') # number of simulation steps
32setInputVariable('inputFiles/'+DCfile,'maxResolveSteps','0') # number of simulation steps
33setInputVariable('inputFiles/'+DCfile,'dtMax','1e4')
34setInputVariable('inputFiles/'+DCfile,'outputFrequency','1') # output frequency
35
36setInputVariable('inputFiles/'+DCfile,'startAtTimeStep','0')
37p = Path('inputFiles') / DCfile
38p.write_text('\n'.join('startAtTimeStep=0; # start from the empty frame 0' if line.startswith('startAtTimeStep') else line for line in p.read_text().splitlines()) + '\n')
39setInputVector('inputFiles/'+DCfile,'periodicImageSize',np.array([0,0]),'image counts for the active periodic directions')
40
41# Make a local copy of DD parameters file and modify that copy if necessary
42DDfile='DD.txt'
43DDfileTemplate=str(repository)+'/Library/DislocationDynamics/'+DDfile
44print("\033[1;32mCreating DDfile\033[0m")
45shutil.copy2(DDfileTemplate,'inputFiles/'+DDfile)
46setInputVariable('inputFiles/'+DDfile,'timeSteppingMethod','fixed') # adaptive or fixed
47setInputVariable('inputFiles/'+DDfile,'dxMax','10') # max nodal displacement for when timeSteppingMethod=adaptive
48setInputVariable('inputFiles/'+DDfile,'use_velocityFilter','1') # don't filter velocity if noise is enabled
49setInputVariable('inputFiles/'+DDfile,'alphaLineTension','1.0') # dimensionless scale factor in for line tension forces
50setInputVariable('inputFiles/'+DDfile,'Lmin','25') # min segment length (in Burgers vector units)
51setInputVariable('inputFiles/'+DDfile,'Lmax','150') # max segment length (in Burgers vector units)
52setInputVariable('inputFiles/'+DDfile,'outputQuadraturePoints','1') # output quadrature data
53setInputVariable('inputFiles/'+DDfile,'glideSolverType','Galerkin') # type of glide solver, or none
54setInputVariable('inputFiles/'+DDfile,'climbSolverType','none') # type of clim solver, or none
55setInputVariable('inputFiles/'+DDfile,'crossSlipModel','0') # crossSlipModel
56
57# Make a local copy of material file, and modify that copy if necessary
58materialFile='W.txt';
59materialFileTemplate=str(repository)+'/Library/Materials/'+materialFile;
60print("\033[1;32mCreating materialFile\033[0m")
61shutil.copy2(materialFileTemplate,'inputFiles/'+materialFile)
62#setInputVariable('inputFiles/'+materialFile,'enabledSlipSystems','full<111>{110}')
63b_SI=getValueInFile('inputFiles/'+materialFile,'b_SI')
64
65# Make a local copy of ElasticDeformation file, and modify that copy if necessary
66elasticDeformatinoFile='ElasticDeformation.txt';
67elasticDeformatinoFileTemplate=str(repository)+'/Library/ElasticDeformation/'+elasticDeformatinoFile;
68print("\033[1;32mCreating elasticDeformatinoFile\033[0m")
69shutil.copy2(elasticDeformatinoFileTemplate,'inputFiles/'+elasticDeformatinoFile)
70setInputVariable('inputFiles/'+elasticDeformatinoFile, 'useElasticDeformationFEM', '1')
71setInputVector('inputFiles/'+elasticDeformatinoFile,'ExternalStress0',np.zeros(6),'applied stress')
72# Voigt order: 11, 22, 33, 12, 23, 13. Strain rate is per simulation time b/cs.
73strainRate33 = 1e-8
74setInputVector('inputFiles/'+elasticDeformatinoFile, 'ExternalStrainRate',
75 np.array([0.0, 0.0, strainRate33, 0.0, 0.0, 0.0]), 'applied strain rate in the global 33 direction')
76setInputVector('inputFiles/'+elasticDeformatinoFile, 'stiffnessRatio',
77 np.array([1e20, 0.0, 1e20, 0.0, 0.0, 0.0]), 'strain control in 11 and 33; zero stress in 22 and shear components')
78
79
80# Create polycrystal.txt using local material file
81meshFile='polycrystalCube_10_periodicXY.msh';
82meshFileTemplate=str(repository)+'/Library/Meshes/'+meshFile;
83print("\033[1;32mCreating polycrystalFile\033[0m")
84shutil.copy2(meshFileTemplate,'inputFiles/'+meshFile)
85pf=PolyCrystalFile(materialFile);
86pf.absoluteTemperature=300;
87pf.meshFile=meshFile
88# Grain 1: crystal and global coordinates aligned.
89pf.grain1globalX1 = np.array([1.0, 0.0, 0.0])
90pf.grain1globalX3 = np.array([0.0, 0.0, 1.0])
91pf.boxScaling=np.array([4e-6,4e-6,4e-6])/b_SI # scale of each mesh coordinate in Burgers vector units
92pf.X0=np.array([0,0,0]) # Mesh nodes X are mapped to x=F*(X-X0)
93pf.periodicFaceIDs=np.array([-1])
94# Explicit example orientations for all 10 grains. These rational rotations
95# are chosen for lattice-compatible periodic translations; they do not use the
96# random orientations stored in the source mesh's ElsetOrientations section.
97rx = np.array([[1., 0., 0.], [0., 0.8, -0.6], [0., 0.6, 0.8]])
98ry = np.array([[0.8, 0., 0.6], [0., 1., 0.], [-0.6, 0., 0.8]])
99rz = np.array([[0.8, -0.6, 0.], [0.6, 0.8, 0.], [0., 0., 1.]])
100grainOrientations = [np.eye(3), rx, rx.T, ry, ry.T, rz, rz.T,
101 rx @ ry, ry @ rz, rz @ rx]
102# The source mesh has unit volume and unit X/Y repeats, with an irregular
103# outer boundary. Scale to approximately (4 micrometers)^3, not a 4 um
104# bounding cube. Round repeats to multiples of 25 for all orientations.
105pf.compute()
106repeatCounts = 25 * np.maximum(1, np.round(pf.boxScaling / (25 * pf.boxEdgesLatticeLengths)))
107pf.boxScaling = repeatCounts * pf.boxEdgesLatticeLengths
108pf.write('inputFiles')
109with open('inputFiles/polycrystal.txt', 'a') as polycrystalFile:
110 for grainID, orientation in enumerate(grainOrientations[1:], start=2):
111 rows = [' '.join(f'{value:.17g}' for value in row) for row in orientation]
112 polycrystalFile.write(f'C2G{grainID}=' + '\n '.join(rows)
113 + '; # crystal-to-global rotation\n')
114
115# Enable DD without inserting any defects. The generator writes an empty frame 0.
116with open('inputFiles/initialMicrostructure.txt', 'w') as initialMicrostructureFile:
117 initialMicrostructureFile.write('# No initial defects; no microstructureFile entries.\n')
118
119lengthSI = pf.F[0, 0] * b_SI
120print(f'XY repeat length and height: {lengthSI * 1e6:.6f} um')
121print(f'Mesh volume: {(lengthSI * 1e6)**3:.6f} um^3')
122print('Strain increment per step: 1e-4; last saved strain: 0.0099 at frame 99.')
123print('Inputs ready: ' + str(Path.cwd()))
124print('Run microstructureGenerator, then DDomp, using this simulation folder.')
setInputVector(fileName, variable, newVal, newCom)
setInputVariable(fileName, variable, newVal)
getValueInFile(fileName, variable)