Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
mdStackingFaultCorrelations/main.py
Go to the documentation of this file.
1import os
2import sys
3import vtk
4import glob
5import string
6import numpy as np
7import matplotlib.pyplot as plt
8
9#plt.rcParams["text.usetex"] = True
10import matplotlib as mpl
11import matplotlib.transforms as mtransforms
12
13sys.path.append("../../build/tools/pyMoDELib/")
14import pyMoDELib
15from scipy.signal import correlate2d
16from scipy.stats import norm
17from matplotlib import cm
18from matplotlib.colors import Normalize
19
20sys.path.append("../../python")
21from modlibUtils import *
22from pathlib import Path
23
24# Define all file templates (using pathlib for cross-platform paths)
25file_templates = {
26 "dd_file": Path("../../Library/DislocationDynamics/DD.txt"),
27 "noise_file": Path("../../Library/GlidePlaneNoise/MDStackingFault.txt"),
28 "material_file": Path("../../Library/Materials/AlMg5.txt"),
29 "elastic_deformation_file": Path(
30 "../../Library/ElasticDeformation/ElasticDeformation.txt"
31 ),
32 "mesh": Path("../../Library/Meshes/unitCube24.msh"),
33 "microstructure": Path(
34 "../../Library/Microstructures/periodicDipoleIndividual.txt"
35 ),
36}
37
38MDStackingFault_parameters = {
39 "variables": {
40 # Scalar parameters (use setInputVariable)
41 "type": "MDStackingFaultNoise",
42 "tag": 1,
43 "seed": 2,
44 "outputNoise": 1,
45 "noiseFile": "AlMg5_ISF.vtk",
46 # File paths (convert to absolute paths)
47 "correlationFile": Path(
48 "../../Library/GlidePlaneNoise/AlMg5_Cx_R100_ISF.vtk"
49 ).resolve(),
50 },
51 "vectors": {
52 # Vector parameters with comments (use setInputVector)
53 "gridSize": {
54 "value": np.array([60, 60, 1]),
55 "comment": "number of grid points in each direction",
56 },
57 "gridSpacing_SI": {
58 "value": np.array([1.0e-10, 1.0e-10, 1e-10]),
59 "comment": "grid spacing in each direction",
60 },
61 },
62 "copy_to": "inputFiles/MDStackingFault.txt",
63}
64
65Material_parameters = {
66 "variables": {
67 "enabledSlipSystems": "Shockley",
68 #'glidePlaneNoise': ['MDSolidSolution.txt', 'MDStackingFault.txt'],
69 "glidePlaneNoise": "MDStackingFault.txt",
70 "atomsPerUnitCell": "1",
71 "dislocationMobilityType": "default",
72 },
73 "copy_to": "inputFiles/AlMg5.txt",
74}
75
76Polycrystal_parameters = {
77 "parameters": {
78 "absoluteTemperature": 1,
79 "grain1globalX1": np.array([0, 1, 1]),
80 "grain1globalX3": np.array([-1, 1, -1]),
81 "boxEdges": np.array([[0, 1, 1], [-2, -1, 1], [-1, 1, -1]]),
82 "boxScaling": np.array([200, 200, 200]),
83 #'X0': np.array([0.5, 0.5, 0.5]),
84 "X0": np.array([0.0, 0.0, 0.0]),
85 "periodicFaceIDs": np.array([0, 1, 2, 3, 4, 5]),
86 "gridSpacing_SI": np.array([1.0e-10, 1.0e-10]),
87 }
88}
89
90
91def readVTKnoise(fname: str):
92 reader = vtk.vtkGenericDataObjectReader()
93 reader.SetFileName(fname) # declare the vtk filename
94 reader.ReadAllVectorsOn() # read all vector data
95 reader.ReadAllScalarsOn() # read all scalar data
96 reader.Update() # update to new file
97 # read data dimensions
98 dims = [0, 0, 0]
99 reader.GetOutput().GetDimensions(dims)
100 NX, NY, NZ = dims
101 # NX, NY, NZ = reader.GetOutput().GetDimensions()
102 # creates dynamic point data object
103 pointData = reader.GetOutput().GetPointData()
104
105 # Initialize a list to store scalar arrays
106 scalarArrays = []
107 # Iterate over the number of arrays in pointData
108 for i in range(pointData.GetNumberOfArrays()):
109 array = pointData.GetArray(i)
110 # Check if it's a scalar array
111 if array.GetNumberOfComponents() == 1:
112 scalarArrays.append(np.array(array))
113 noiseScalars = scalarArrays[0]
114 noiseScalars = np.reshape(noiseScalars, shape=(NX, NY))
115 return noiseScalars, dims
116
117
118def processInitialConfigurations() -> None:
119 # Copy all template files
120 print("\033[1;32mCopying template files...\033[0m")
121 for key, src_path in file_templates.items():
122 dest = f"inputFiles/{src_path.name}"
123 shutil.copy2(src_path.resolve(), dest)
124 # shutil.copy2(src_path, dest)
125 print(f"Created {dest}")
126
127 # print("\033[1;32mCreating ddFile\033[0m")
128
131
132 print("\033[1;32mCreating noiseFile\033[0m")
133 # copy noise file into inputFiles
134 shutil.copy2(
135 MDStackingFault_parameters["variables"]["correlationFile"], "inputFiles/"
136 )
137 # copy declared variables to the configuration txt file
138 for param, value in MDStackingFault_parameters["variables"].items():
139 if "correlationFile" in param:
140 relativePath = f"{str(value).split('/')[-1]}"
141 setInputVariable(MDStackingFault_parameters["copy_to"], param, relativePath)
142 else:
143 setInputVariable(MDStackingFault_parameters["copy_to"], param, str(value))
144 for param, data in MDStackingFault_parameters["vectors"].items():
146 MDStackingFault_parameters["copy_to"], param, data["value"], data["comment"]
147 )
148
149 # Process material file
150 print("\033[1;32mCreating materialFile...\033[0m")
151 # print(Material_parameters['variables'].items())
152 matParams = Material_parameters["variables"]
154 Material_parameters["copy_to"],
155 "enabledSlipSystems",
156 matParams["enabledSlipSystems"],
157 )
158
159 # for gPlaneNoise in matParams['glidePlaneNoise']:
160 # setInputVariable(Material_parameters['copy_to'],'glidePlaneNoise',gPlaneNoise)
162 Material_parameters["copy_to"], "glidePlaneNoise", matParams["glidePlaneNoise"]
163 )
164
166 Material_parameters["copy_to"],
167 "atomsPerUnitCell",
168 matParams["atomsPerUnitCell"],
169 )
171 Material_parameters["copy_to"],
172 "dislocationMobilityType",
173 matParams["dislocationMobilityType"],
174 )
175
176 # Process polycrystal
177 # pf = PolyCrystalFile('FeCrAl_Fe.txt')
178 pf = PolyCrystalFile(Material_parameters["copy_to"].split("/")[-1])
179 # pf.meshFile='unitCube24.msh'
180 pf.meshFile = f'{str(file_templates["mesh"]).split("/")[-1]}'
181 for param, value in Polycrystal_parameters["parameters"].items():
182 setattr(pf, param, value)
183 pf.write("inputFiles")
184
185
186def constructDotGrid(NX, NY, unitVec1, unitVec2):
187 # Construct non-orthogonal dot grid based on the non-minimized atom structure
188 firstNearNeighborDist = 2.8
189 dotGrid = np.zeros((NX * NY, 2)) # each row contains x and y position of the dot
190 vec1 = unitVec1 * firstNearNeighborDist
191 vec2 = unitVec2 * firstNearNeighborDist
192 for yIdx in range(NY):
193 for xIdx in range(NX):
194 dotGrid[yIdx * NX + xIdx] = vec1 * xIdx + vec2 * yIdx
195 return dotGrid
196
197
198def initUnitVectors(originalCorrVTK: str):
199 latVector1 = None
200 latVector2 = None
201 copyFlag1 = False
202 copyFlag2 = False
203 with open(originalCorrVTK) as o:
204 for line in o:
205 if copyFlag1:
206 latVector1 = np.array(line.strip().split(), dtype=float)
207 copyFlag1 = False
208 elif copyFlag2:
209 latVector2 = np.array(line.strip().split(), dtype=float)
210 copyFlag2 = False
211 elif "VECTORS lattice_basis1 double" in line:
212 copyFlag1 = True
213 elif "VECTORS lattice_basis2 double" in line:
214 copyFlag2 = True
215
216 unitVec1 = latVector1 / np.linalg.norm(latVector1)
217 unitVec2 = latVector2 / np.linalg.norm(latVector2)
218 unitVec1 = unitVec1[:2] # drop the z axis value
219 unitVec2 = unitVec2[:2]
220 return unitVec1, unitVec2
221
222
223def circularShift(corrArray: np.ndarray, gridSize: np.ndarray) -> np.ndarray:
224 NX, NY = np.squeeze(gridSize[0]), np.squeeze(gridSize[1])
225 shiftY = NY / 2
226 shiftX = NX / 2
227 tempArr = np.zeros(NX * NY)
228 for y in np.arange(NY):
229 newY = int((y + shiftY) % NY)
230 for x in np.arange(NX):
231 newX = int((x + shiftX) % NX)
232 tempArr[newY * NX + newX] += corrArray[y * NX + x]
233 return tempArr
234
235
236def main() -> int:
237 # Preparing input files
238 folders = ["inputFiles"]
239 for x in folders:
240 # remove existing data
241 if os.path.exists(x):
242 shutil.rmtree(x)
243 # create necessary folder structure for the simulation
244 os.makedirs(x)
245
246 # set simulation parameters in inputFiles
248
249 # setInputVariable(MDStackingFault_parameters['copy_to'], 'testNoiseSampling', str(1))
250 simulationDir = os.path.abspath(".")
251 ddBase = pyMoDELib.DefectiveCrystalBase(simulationDir)
252
253 matFile = "inputFiles/AlMg5.txt"
254 absoluteTemp = 1
255 mat = pyMoDELib.PolycrystallineMaterialBase(matFile, absoluteTemp)
256 b_SI = getValueInFile(f"{matFile}", "b_SI")
257 mu0_SI = getValueInFile(f"{matFile}", "mu0_SI")
258 rho_SI = getValueInFile(f"{matFile}", "rho_SI")
259
260 tag = "0"
261 originalCorrFile = "inputFiles/AlMg5_Cx_R100_ISF.vtk"
262 seed = 1
263 gridSize = np.array([100, 100, 1])
264 gridSpacing = np.array([1e-10, 1e-10, 1e-10]) / b_SI
265 latticeBasis = np.array([[1, 1], [1, 1]]).reshape(2, 2)
266 sfNoise = pyMoDELib.MDStackingFaultNoise(
267 mat,
268 tag,
269 originalCorrFile,
270 seed,
271 gridSize.reshape(3, 1),
272 gridSpacing.reshape(3, 1),
273 latticeBasis,
274 )
275
276 realizationNum = 100
277 correlation = sfNoise.averageNoiseCorrelation(realizationNum)
278 correlation = np.squeeze(np.array(correlation))
279 # circular shift
280 correlation = circularShift(correlation, gridSize)
281 correlation = np.array(correlation).reshape(gridSize[0], gridSize[1])
282 # convert unit from DDD to SI
283 correlation *= (mu0_SI * b_SI) ** 2
284
285 unitVec1, unitVec2 = initUnitVectors(originalCorrFile)
286
287 inputPath = "./inputFiles/"
288 # reshape the correlation data to 1D array
289 NX_s, NY_s, NZ_s = gridSize
290
291 # create callable color map
292 color_map = mpl.colormaps["coolwarm"]
293
294 # normalize the correlation coefficient array for the color assignment
295 dotGrid_s = constructDotGrid(NX_s, NY_s, unitVec1, unitVec2)
296 correlation = correlation.reshape(NY_s * NX_s, 1)
297 c_normalized = (correlation - np.min(correlation.flatten())) / (
298 np.max(correlation.flatten()) - np.min(correlation.flatten())
299 )
300 color = color_map(c_normalized)
301
302 # load input correlation values from the correlation vtk files
303 inputCorrelationField, i_dim = readVTKnoise(originalCorrFile)
304 NX_i, NY_i, NZ_i = i_dim
305 dotGrid_i = constructDotGrid(NX_i, NY_i, unitVec1, unitVec2)
306 inputCorrelationField = inputCorrelationField.reshape(NY_i * NX_i, 1)
307 c_normalized_i = (
308 inputCorrelationField - np.min(inputCorrelationField.flatten())
309 ) / (
310 np.max(inputCorrelationField.flatten())
311 - np.min(inputCorrelationField.flatten())
312 )
313 color_i = color_map(c_normalized_i)
314
315 # plot correlation data on the dot grid
316 fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(10, 8.6), dpi=500)
317
318 axes[0].set_title("Input Correlation")
319 axes[0].scatter(dotGrid_i[:, 0], dotGrid_i[:, 1], c=color_i, s=30)
320 axes[1].set_title(f"Sampled R")
321 axes[1].scatter(dotGrid_s[:, 0], dotGrid_s[:, 1], c=color, s=10)
322 fig.colorbar(
323 plt.cm.ScalarMappable(
324 norm=Normalize(
325 np.min(inputCorrelationField), np.max(inputCorrelationField)
326 ),
327 cmap=color_map,
328 ),
329 ax=axes[0], label="J/m2"
330 )
331 fig.colorbar(
332 plt.cm.ScalarMappable(
333 norm=Normalize(np.min(correlation), np.max(correlation)), cmap=color_map
334 ),
335 ax=axes[1], label="J/m2"
336 )
337 plt.tight_layout()
338 fig.savefig(f"ensemCorr_R{realizationNum}.png", transparent=True)
339 plt.close()
340
341 return 0
342
343
344if __name__ == "__main__":
345 main()
initUnitVectors(str originalCorrVTK)
np.ndarray circularShift(np.ndarray corrArray, np.ndarray gridSize)
constructDotGrid(NX, NY, unitVec1, unitVec2)
setInputVector(fileName, variable, newVal, newCom)
setInputVariable(fileName, variable, newVal)
getValueInFile(fileName, variable)
REAL split