Skip to content

Commit f777edb

Browse files
authored
refactor: improve MaterialValueMap and update examples (#222)
* feat: add function to insert mask at front of material stack * feat: directional process rate based * feat: material value mapping in single particle process rates * feat: single particle process python bindings updated * feat: add mapping in IsotropicProcess * refactor: material mapping, allow custom material registration * feat: materials on CUDA device code * fix: plasma etching models * feat: add material factors in plasma etching model * test adding custom material to domain * refactor: use singleton MaterialRegistry * material registry tests * refactor: update directional process * refactor: udpate ion beam etching model * fix: faraday cage model, update python bindings * small map refactor * fix: bug in mask blur GDS * feat: parallel blur loop * fix: correct material check function in CSV file process * refactor: material info * feat: fix build * chore: format * fix: material info requires string for custom values * feat: MaterialValueMap iterator includes custom values * feat(MaterialValueMap): get entries by index * refactor: SelectiveEpitaxy material handling and emulation examples * refactor: rename header file with MaterialMap * refactor: CF4O2 model and selective epitaxy * fix: clean up finFET example * refactor: MultiParticleProcess uses MaterialValueMap * fix: check all examples * format
1 parent e35d96a commit f777edb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+774
-599
lines changed

examples/SiGeSelectiveEtching/SiGeEtching.py

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,29 @@
4040
modelParams.Passivation.A_C_ie = params["A_C"]
4141

4242
# Use Material enum
43-
modelParams.gamma_F = {
44-
ps.Material.Mask: 0.0,
45-
ps.Material.Si: 0.1,
46-
ps.Material.SiGe: 0.1,
47-
}
48-
modelParams.gamma_F_oxidized = {
49-
ps.Material.Mask: 0.0,
50-
ps.Material.Si: 0.1,
51-
ps.Material.SiGe: 0.1,
52-
}
53-
modelParams.gamma_O = {
54-
ps.Material.Mask: 0.0,
55-
ps.Material.Si: 0.7,
56-
ps.Material.SiGe: 0.7,
57-
}
58-
modelParams.gamma_O_passivated = {
59-
ps.Material.Mask: 0.0,
60-
ps.Material.Si: 0.7,
61-
ps.Material.SiGe: 0.7,
62-
}
63-
modelParams.gamma_C = {
64-
ps.Material.Mask: 0.0,
65-
ps.Material.Si: 0.7,
66-
ps.Material.SiGe: 0.7,
67-
}
68-
modelParams.gamma_C_oxidized = {
69-
ps.Material.Mask: 0.0,
70-
ps.Material.Si: 0.7,
71-
ps.Material.SiGe: 0.7,
72-
}
43+
modelParams.gamma_F.set(ps.Material.Mask, 0.0)
44+
modelParams.gamma_F.set(ps.Material.Si, 0.1)
45+
modelParams.gamma_F.set(ps.Material.SiGe, 0.1)
46+
47+
modelParams.gamma_F_oxidized.set(ps.Material.Mask, 0.0)
48+
modelParams.gamma_F_oxidized.set(ps.Material.Si, 0.1)
49+
modelParams.gamma_F_oxidized.set(ps.Material.SiGe, 0.1)
50+
51+
modelParams.gamma_O.set(ps.Material.Mask, 0.0)
52+
modelParams.gamma_O.set(ps.Material.Si, 0.7)
53+
modelParams.gamma_O.set(ps.Material.SiGe, 0.7)
54+
55+
modelParams.gamma_O_passivated.set(ps.Material.Mask, 0.0)
56+
modelParams.gamma_O_passivated.set(ps.Material.Si, 0.7)
57+
modelParams.gamma_O_passivated.set(ps.Material.SiGe, 0.7)
58+
59+
modelParams.gamma_C.set(ps.Material.Mask, 0.0)
60+
modelParams.gamma_C.set(ps.Material.Si, 0.7)
61+
modelParams.gamma_C.set(ps.Material.SiGe, 0.7)
62+
63+
modelParams.gamma_C_oxidized.set(ps.Material.Mask, 0.0)
64+
modelParams.gamma_C_oxidized.set(ps.Material.Si, 0.7)
65+
modelParams.gamma_C_oxidized.set(ps.Material.SiGe, 0.7)
7366

7467
model = ps.CF4O2Etching(modelParams)
7568
parameters = model.getParameters()
Lines changed: 75 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,86 @@
11
import viennaps as ps
22
import viennals as ls
3-
import matplotlib.pyplot as plt
4-
import numpy as np
53

64
ps.setDimension(2)
75
ls.setDimension(2)
86

9-
ps.Logger.setLogLevel(ps.LogLevel.DEBUG)
10-
11-
12-
def run_simulation(gd, filename):
13-
params = ps.readConfigFile("config.txt")
14-
geometry = ps.Domain()
15-
16-
# Create the geometry
17-
boundaryCons = [
18-
ps.BoundaryType.REFLECTIVE_BOUNDARY,
19-
ps.BoundaryType.INFINITE_BOUNDARY,
20-
]
21-
gridDelta = gd
22-
bounds = [
23-
0.0,
24-
params["openingWidth"] / 2.0 + params["xPad"] + params["gapLength"],
25-
-gridDelta,
26-
params["openingDepth"] + params["gapHeight"] + gridDelta,
27-
]
28-
29-
substrate = ls.Domain(bounds, boundaryCons, gridDelta)
30-
normal = [0.0, 1.0]
31-
origin = [0.0, params["openingDepth"] + params["gapHeight"]]
32-
ls.MakeGeometry(substrate, ls.Plane(origin, normal)).apply()
33-
34-
geometry.insertNextLevelSetAsMaterial(substrate, ps.Material.Si)
35-
36-
vertBox = ls.Domain(bounds, boundaryCons, gridDelta)
37-
minPoint = [-gridDelta, 0.0]
38-
maxPoint = [
39-
params["openingWidth"] / 2.0,
40-
params["gapHeight"] + params["openingDepth"] + gridDelta,
41-
]
42-
ls.MakeGeometry(vertBox, ls.Box(minPoint, maxPoint)).apply()
43-
44-
geometry.applyBooleanOperation(vertBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)
45-
46-
horiBox = ls.Domain(bounds, boundaryCons, gridDelta)
47-
minPoint = [params["openingWidth"] / 2.0 - gridDelta, 0.0]
48-
maxPoint = [params["openingWidth"] / 2.0 + params["gapLength"], params["gapHeight"]]
49-
ls.MakeGeometry(horiBox, ls.Box(minPoint, maxPoint)).apply()
50-
geometry.applyBooleanOperation(horiBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)
51-
52-
geometry.saveSurfaceMesh("SingleParticleALD_initial")
53-
54-
model = ps.SingleParticleProcess(rate=1.0, stickingProbability=1e-4)
55-
56-
geometry.duplicateTopLevelSet(ps.Material.Al2O3)
57-
58-
gasMFP = ps.constants.gasMeanFreePath(
59-
params["pressure"], params["temperature"], params["diameter"]
60-
)
61-
print("Mean free path: ", gasMFP, " um")
62-
63-
model = ps.SingleParticleALD(
64-
stickingProbability=params["stickingProbability"],
65-
numCycles=int(params["numCycles"]),
66-
growthPerCycle=params["growthPerCycle"],
67-
totalCycles=int(params["totalCycles"]),
68-
coverageTimeStep=params["coverageTimeStep"],
69-
evFlux=params["evFlux"],
70-
inFlux=params["inFlux"],
71-
s0=params["s0"],
72-
gasMFP=gasMFP,
73-
)
74-
model.setProcessName(filename)
75-
76-
alpParams = ps.AtomicLayerProcessParameters()
77-
alpParams.pulseTime = params["pulseTime"]
78-
alpParams.coverageTimeStep = params["coverageTimeStep"]
79-
alpParams.numCycles = 1
80-
81-
p = ps.Process(geometry, model, 1.0)
82-
p.setParameters(alpParams)
83-
p.setFluxEngineType(ps.FluxEngineType.GPU_TRIANGLE)
84-
p.apply()
85-
86-
# flux = p.calculateFlux()
87-
88-
# points = np.array(flux.getNodes())
89-
# fluxValues = np.array(flux.getCellData().getScalarData("particleFlux", True))
90-
91-
# cuts = points[:, 1] < 0.25
92-
# points = points[cuts]
93-
# fluxValues = fluxValues[cuts]
94-
95-
# ps.ls.VTKWriter(flux, filename).apply()
96-
97-
mesh = ps.ls.Mesh()
98-
ps.ToDiskMesh(geometry, mesh).apply()
99-
points = np.array(mesh.getNodes())
100-
cuts = points[:, 1] < 0.25
101-
points = points[cuts]
102-
return points
103-
# return points, fluxValues
104-
105-
106-
p = run_simulation(0.1, "flux_0p1")
107-
plt.plot(p[:, 0], p[:, 1], "--")
108-
p = run_simulation(0.01, "flux_0p01")
109-
plt.plot(p[:, 0], p[:, 1], ".-")
110-
p = run_simulation(0.05, "flux_0p05")
111-
plt.plot(p[:, 0], p[:, 1], "-")
112-
plt.show()
113-
114-
115-
# rayParams = ps.RayTracingParameters()
116-
# rayParams.raysPerPoint = int(params["numRaysPerPoint"])
117-
118-
# ALP = ps.Process(geometry, model)
119-
# ALP.setParameters(rayParams)
120-
# ALP.setParameters(alpParams)
121-
# ALP.apply()
7+
params = ps.readConfigFile("config.txt")
8+
geometry = ps.Domain()
9+
10+
# Create the geometry
11+
boundaryCons = [
12+
ps.BoundaryType.REFLECTIVE_BOUNDARY,
13+
ps.BoundaryType.INFINITE_BOUNDARY,
14+
]
15+
gridDelta = params["gridDelta"]
16+
bounds = [
17+
0.0,
18+
params["openingWidth"] / 2.0 + params["xPad"] + params["gapLength"],
19+
-gridDelta,
20+
params["openingDepth"] + params["gapHeight"] + gridDelta,
21+
]
22+
23+
substrate = ls.Domain(bounds, boundaryCons, gridDelta)
24+
normal = [0.0, 1.0]
25+
origin = [0.0, params["openingDepth"] + params["gapHeight"]]
26+
ls.MakeGeometry(substrate, ls.Plane(origin, normal)).apply()
27+
28+
geometry.insertNextLevelSetAsMaterial(substrate, ps.Material.Si)
29+
30+
vertBox = ls.Domain(bounds, boundaryCons, gridDelta)
31+
minPoint = [-gridDelta, 0.0]
32+
maxPoint = [
33+
params["openingWidth"] / 2.0,
34+
params["gapHeight"] + params["openingDepth"] + gridDelta,
35+
]
36+
ls.MakeGeometry(vertBox, ls.Box(minPoint, maxPoint)).apply()
37+
38+
geometry.applyBooleanOperation(vertBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)
39+
40+
horiBox = ls.Domain(bounds, boundaryCons, gridDelta)
41+
minPoint = [params["openingWidth"] / 2.0 - gridDelta, 0.0]
42+
maxPoint = [params["openingWidth"] / 2.0 + params["gapLength"], params["gapHeight"]]
43+
ls.MakeGeometry(horiBox, ls.Box(minPoint, maxPoint)).apply()
44+
geometry.applyBooleanOperation(horiBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)
45+
46+
geometry.saveSurfaceMesh("SingleParticleALD_initial")
47+
48+
model = ps.SingleParticleProcess(rate=1.0, stickingProbability=1e-4)
49+
50+
geometry.duplicateTopLevelSet(ps.Material.Al2O3)
51+
52+
gasMFP = ps.constants.gasMeanFreePath(
53+
params["pressure"], params["temperature"], params["diameter"]
54+
)
55+
print("Mean free path: ", gasMFP, " um")
56+
57+
model = ps.SingleParticleALD(
58+
stickingProbability=params["stickingProbability"],
59+
numCycles=int(params["numCycles"]),
60+
growthPerCycle=params["growthPerCycle"],
61+
totalCycles=int(params["totalCycles"]),
62+
coverageTimeStep=params["coverageTimeStep"],
63+
evFlux=params["evFlux"],
64+
inFlux=params["inFlux"],
65+
s0=params["s0"],
66+
gasMFP=gasMFP,
67+
)
68+
69+
alpParams = ps.AtomicLayerProcessParameters()
70+
alpParams.pulseTime = params["pulseTime"]
71+
alpParams.coverageTimeStep = params["coverageTimeStep"]
72+
alpParams.numCycles = int(params["numCycles"])
73+
74+
rayParams = ps.RayTracingParameters()
75+
rayParams.raysPerPoint = int(params["numRaysPerPoint"])
76+
77+
ALP = ps.Process(geometry, model)
78+
ALP.setParameters(rayParams)
79+
ALP.setParameters(alpParams)
80+
ALP.apply()
12281

12382
# ## TODO: Implement MeasureProfile in Python
12483
# # MeasureProfile<NumericType, D>(domain, params.get("gapHeight") / 2.)
12584
# # .save(params.get<std::string>("outputFile"));
12685

127-
# geometry.saveVolumeMesh("SingleParticleALD_final")
86+
geometry.saveSurfaceMesh("SingleParticleALD_final")

examples/blazedGratingsEtching/blazedGratingsEtching.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
ibeParams = ps.IBEParameters()
6565
ibeParams.exponent = params["exponent"]
6666
ibeParams.meanEnergy = params["meanEnergy"]
67-
ibeParams.materialPlaneWaferRate = {ps.Material.SiO2: 1, ps.Material.Mask: 1 / 11}
67+
ibeParams.materialPlaneWaferRate.set(ps.Material.SiO2, 1.0)
68+
ibeParams.materialPlaneWaferRate.set(ps.Material.Mask, 1.0 / 11.0)
6869
ibeParams.cos4Yield.isDefined = True
6970
ibeParams.cos4Yield.a1 = params["yieldFactor"]
7071
ibeParams.cos4Yield.a2 = -1.55

0 commit comments

Comments
 (0)