Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testPhysicsBases.py
Go to the documentation of this file.
1"""Python ownership and shared-context API regression. Takes module directory and repository root."""
2import gc
3import math
4from pathlib import Path
5import shutil
6import sys
7import tempfile
8import numpy as np
9
10sys.path.insert(0, sys.argv[1])
11import pyMoDELib as model
12root = Path(sys.argv[2])
13
14with tempfile.TemporaryDirectory(prefix="modelib-python-bases-") as directory:
15 folder = Path(directory)
16 inputs = folder / "inputFiles"
17 inputs.mkdir()
18 (folder / "F").mkdir()
19 shutil.copy(root / "Library/Materials/W.txt", inputs / "W.txt")
20 shutil.copy(root / "Library/Meshes/unitCube24.msh", inputs / "mesh.msh")
21
22 def configure(physics, length):
23 (inputs / "DefectiveCrystal.txt").write_text(
24 f"physics={physics};\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\n"
25 "outputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\n"
26 "periodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n")
27 (inputs / "polycrystal.txt").write_text(
28 "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\n"
29 "C2G1=1 0 0 0 1 0 0 0 1;\n"
30 f"F={length:.17g} 0 0 0 {length:.17g} 0 0 0 {length:.17g};\n"
31 "X0=0 0 0;\nperiodicFaceIDs=-1;\n")
32
33 configure("ElasticDeformation", 123.456)
34 traits = model.DefectiveCrystalTraitsIO(str(folder))
35 assert traits.configFolder == str(folder / "config")
36 assert traits.auxFolder == traits.configFolder
38 custom_config = model.DefectiveCrystalConfigIO(str(folder / "custom"))
39 base = model.DefectiveCrystalBase(str(folder))
40 assert base.dislocationDynamicsBase is None
41 assert base.clusterDynamicsBase is None
42 assert base.elasticDeformationBase is base.elasticDeformation()
43 assert base.hasPhysics("ElasticDeformation")
44 assert base.periodicLatticeBasis.shape == (3, 3)
45 assert base.periodicCoordinates(np.zeros(3)).shape == (3,)
47 assert isinstance(generator.configIO, model.DefectiveCrystalConfigIO)
48 del base
49 gc.collect()
50 try:
51 generator.addPrismaticLoopDensity(model.PrismaticLoopDensitySpecification())
52 except RuntimeError as error:
53 assert "not enabled" in str(error)
54 else:
55 raise AssertionError("DD generation was allowed without DD")
56 del generator
57
58 configure("DislocationDynamics", 200 / math.sqrt(3))
59 base = model.DefectiveCrystalBase(str(folder))
60 dd = base.dislocationDynamicsBase
61 assert dd is base.dislocationDynamics()
62 plane = dd.glidePlane(np.zeros(3), np.array([0., 0., 1.]), 1)
63 periodic = dd.periodicGlidePlane(np.zeros(3), np.array([0., 0., 1.]), 1)
64 assert dd.glidePlaneCount() >= 1
65 assert dd.periodicGlidePlaneCount() == 1
66 del base
67 gc.collect()
68 assert np.isfinite(dd.EwaldLength)
69 assert plane.planeBaseID() == periodic.referencePlane.planeBaseID()
70 del dd
71 gc.collect()
72 assert plane.planeBaseID() == periodic.referencePlane.planeBaseID()
73 del plane, periodic
74
75 # CD context methods and ownership, without constructing DD factories.
76 shutil.copy(root / "tests/spatialCDtest/inputFiles/Zr4_Fitted.txt", inputs / "Zr4_Fitted.txt")
77 configure("ClusterDynamics", 123.456)
78 poly = inputs / "polycrystal.txt"
79 poly.write_text(poly.read_text().replace("W.txt", "Zr4_Fitted.txt").replace("=300", "=553"))
80 base = model.DefectiveCrystalBase(str(folder))
81 cd = base.clusterDynamicsBase
82 assert cd is base.clusterDynamics()
83 assert base.dislocationDynamicsBase is None
84 del base
85 gc.collect()
86 assert np.isfinite(cd.equilibriumMobileConcentration(0.)).all()
87 assert np.isfinite(cd.getDlocal()).all()
88print("PASS: Python base API, activation, and lifetimes")
89
90# Region/face APIs expose the same factory-owned polyhedra at every level.
91mesh = model.SimplicialMesh(str(root / "Library/Meshes/bicrystal_48.msh"),
92 np.eye(3), np.zeros(3), set())
93regions = mesh.regions()
94assert len(regions) == 2
95shared_faces = {}
96for region_id, region in regions.items():
97 assert mesh.region(region_id) is region
98 assert region.regionID == region_id
99 assert region.simplexIDs()
100 for face_id, face in region.faces().items():
101 assert region.children[face_id] is face
102 assert face.key == face_id == face.sID
103 assert face.parents[region_id] is region
104 assert face.simplexIDs()
105 if face_id in shared_faces:
106 assert shared_faces[face_id] is face
107 assert not face.isExternal()
108 shared_faces[face_id] = face
109 for edge_key, edge in face.children.items():
110 assert tuple(edge.key) == edge_key
111 assert edge.parents[face_id] is face
112 assert len(edge.simplexIDs()) == 1
113 for vertex_key, vertex in edge.children.items():
114 assert tuple(vertex.key) == vertex_key
115 assert vertex.parents[edge_key] is edge
116 assert len(vertex.simplexIDs()) == 1
117assert any(not face.isExternal() for face in shared_faces.values())
118print("PASS: Python unified polyhedral hierarchy")
configure(physics, length)
int regions
Definition triangle.cpp:696