Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5bcfadc
feat: add function to insert mask at front of material stack
tobre1 Mar 24, 2026
4507984
feat: directional process rate based
tobre1 Mar 25, 2026
53f3251
feat: material value mapping in single particle process rates
tobre1 Mar 25, 2026
38a9b3e
feat: single particle process python bindings updated
tobre1 Mar 25, 2026
241a463
feat: add mapping in IsotropicProcess
tobre1 Mar 25, 2026
20cb88a
refactor: material mapping, allow custom material registration
tobre1 Mar 25, 2026
ba2cf1e
feat: materials on CUDA device code
tobre1 Mar 26, 2026
6ee9e32
fix: plasma etching models
tobre1 Mar 26, 2026
0e92b90
feat: add material factors in plasma etching model
tobre1 Mar 26, 2026
3d1de56
test adding custom material to domain
tobre1 Mar 30, 2026
696bf6a
refactor: use singleton MaterialRegistry
tobre1 Mar 30, 2026
dfee758
material registry tests
tobre1 Mar 30, 2026
777cc0c
refactor: update directional process
tobre1 Mar 30, 2026
12c2c53
refactor: udpate ion beam etching model
tobre1 Mar 30, 2026
d1f98f8
fix: faraday cage model, update python bindings
tobre1 Mar 30, 2026
55d45f4
merge master into branch
tobre1 Mar 30, 2026
35eb16a
small map refactor
tobre1 Mar 31, 2026
0d37a97
fix: bug in mask blur GDS
tobre1 Mar 31, 2026
0b77abc
feat: parallel blur loop
tobre1 Mar 31, 2026
8d55eb7
fix: correct material check function in CSV file process
tobre1 Mar 31, 2026
dafdb18
refactor: material info
tobre1 Apr 1, 2026
f7b1093
feat: fix build
tobre1 Apr 1, 2026
a841c14
chore: format
tobre1 Apr 1, 2026
5e55098
fix: material info requires string for custom values
tobre1 Apr 1, 2026
2a4179f
feat: MaterialValueMap iterator includes custom values
tobre1 Apr 1, 2026
5130a41
feat(MaterialValueMap): get entries by index
tobre1 Apr 1, 2026
d3f4298
refactor: SelectiveEpitaxy material handling and emulation examples
tobre1 Apr 1, 2026
708422a
merge master
tobre1 Apr 2, 2026
d3509dd
refactor: rename header file with MaterialMap
tobre1 Apr 2, 2026
e8af7b0
refactor: CF4O2 model and selective epitaxy
tobre1 Apr 2, 2026
966ab6a
fix: clean up finFET example
tobre1 Apr 2, 2026
b0f2b64
refactor: MultiParticleProcess uses MaterialValueMap
tobre1 Apr 2, 2026
e8a9efc
fix: check all examples
tobre1 Apr 2, 2026
f33ac44
format
tobre1 Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 23 additions & 30 deletions examples/SiGeSelectiveEtching/SiGeEtching.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,36 +40,29 @@
modelParams.Passivation.A_C_ie = params["A_C"]

# Use Material enum
modelParams.gamma_F = {
ps.Material.Mask: 0.0,
ps.Material.Si: 0.1,
ps.Material.SiGe: 0.1,
}
modelParams.gamma_F_oxidized = {
ps.Material.Mask: 0.0,
ps.Material.Si: 0.1,
ps.Material.SiGe: 0.1,
}
modelParams.gamma_O = {
ps.Material.Mask: 0.0,
ps.Material.Si: 0.7,
ps.Material.SiGe: 0.7,
}
modelParams.gamma_O_passivated = {
ps.Material.Mask: 0.0,
ps.Material.Si: 0.7,
ps.Material.SiGe: 0.7,
}
modelParams.gamma_C = {
ps.Material.Mask: 0.0,
ps.Material.Si: 0.7,
ps.Material.SiGe: 0.7,
}
modelParams.gamma_C_oxidized = {
ps.Material.Mask: 0.0,
ps.Material.Si: 0.7,
ps.Material.SiGe: 0.7,
}
modelParams.gamma_F.set(ps.Material.Mask, 0.0)
modelParams.gamma_F.set(ps.Material.Si, 0.1)
modelParams.gamma_F.set(ps.Material.SiGe, 0.1)

modelParams.gamma_F_oxidized.set(ps.Material.Mask, 0.0)
modelParams.gamma_F_oxidized.set(ps.Material.Si, 0.1)
modelParams.gamma_F_oxidized.set(ps.Material.SiGe, 0.1)

modelParams.gamma_O.set(ps.Material.Mask, 0.0)
modelParams.gamma_O.set(ps.Material.Si, 0.7)
modelParams.gamma_O.set(ps.Material.SiGe, 0.7)

modelParams.gamma_O_passivated.set(ps.Material.Mask, 0.0)
modelParams.gamma_O_passivated.set(ps.Material.Si, 0.7)
modelParams.gamma_O_passivated.set(ps.Material.SiGe, 0.7)

modelParams.gamma_C.set(ps.Material.Mask, 0.0)
modelParams.gamma_C.set(ps.Material.Si, 0.7)
modelParams.gamma_C.set(ps.Material.SiGe, 0.7)

modelParams.gamma_C_oxidized.set(ps.Material.Mask, 0.0)
modelParams.gamma_C_oxidized.set(ps.Material.Si, 0.7)
modelParams.gamma_C_oxidized.set(ps.Material.SiGe, 0.7)

model = ps.CF4O2Etching(modelParams)
parameters = model.getParameters()
Expand Down
191 changes: 75 additions & 116 deletions examples/atomicLayerDeposition/atomicLayerDeposition.py
Original file line number Diff line number Diff line change
@@ -1,127 +1,86 @@
import viennaps as ps
import viennals as ls
import matplotlib.pyplot as plt
import numpy as np

ps.setDimension(2)
ls.setDimension(2)

ps.Logger.setLogLevel(ps.LogLevel.DEBUG)


def run_simulation(gd, filename):
params = ps.readConfigFile("config.txt")
geometry = ps.Domain()

# Create the geometry
boundaryCons = [
ps.BoundaryType.REFLECTIVE_BOUNDARY,
ps.BoundaryType.INFINITE_BOUNDARY,
]
gridDelta = gd
bounds = [
0.0,
params["openingWidth"] / 2.0 + params["xPad"] + params["gapLength"],
-gridDelta,
params["openingDepth"] + params["gapHeight"] + gridDelta,
]

substrate = ls.Domain(bounds, boundaryCons, gridDelta)
normal = [0.0, 1.0]
origin = [0.0, params["openingDepth"] + params["gapHeight"]]
ls.MakeGeometry(substrate, ls.Plane(origin, normal)).apply()

geometry.insertNextLevelSetAsMaterial(substrate, ps.Material.Si)

vertBox = ls.Domain(bounds, boundaryCons, gridDelta)
minPoint = [-gridDelta, 0.0]
maxPoint = [
params["openingWidth"] / 2.0,
params["gapHeight"] + params["openingDepth"] + gridDelta,
]
ls.MakeGeometry(vertBox, ls.Box(minPoint, maxPoint)).apply()

geometry.applyBooleanOperation(vertBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)

horiBox = ls.Domain(bounds, boundaryCons, gridDelta)
minPoint = [params["openingWidth"] / 2.0 - gridDelta, 0.0]
maxPoint = [params["openingWidth"] / 2.0 + params["gapLength"], params["gapHeight"]]
ls.MakeGeometry(horiBox, ls.Box(minPoint, maxPoint)).apply()
geometry.applyBooleanOperation(horiBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)

geometry.saveSurfaceMesh("SingleParticleALD_initial")

model = ps.SingleParticleProcess(rate=1.0, stickingProbability=1e-4)

geometry.duplicateTopLevelSet(ps.Material.Al2O3)

gasMFP = ps.constants.gasMeanFreePath(
params["pressure"], params["temperature"], params["diameter"]
)
print("Mean free path: ", gasMFP, " um")

model = ps.SingleParticleALD(
stickingProbability=params["stickingProbability"],
numCycles=int(params["numCycles"]),
growthPerCycle=params["growthPerCycle"],
totalCycles=int(params["totalCycles"]),
coverageTimeStep=params["coverageTimeStep"],
evFlux=params["evFlux"],
inFlux=params["inFlux"],
s0=params["s0"],
gasMFP=gasMFP,
)
model.setProcessName(filename)

alpParams = ps.AtomicLayerProcessParameters()
alpParams.pulseTime = params["pulseTime"]
alpParams.coverageTimeStep = params["coverageTimeStep"]
alpParams.numCycles = 1

p = ps.Process(geometry, model, 1.0)
p.setParameters(alpParams)
p.setFluxEngineType(ps.FluxEngineType.GPU_TRIANGLE)
p.apply()

# flux = p.calculateFlux()

# points = np.array(flux.getNodes())
# fluxValues = np.array(flux.getCellData().getScalarData("particleFlux", True))

# cuts = points[:, 1] < 0.25
# points = points[cuts]
# fluxValues = fluxValues[cuts]

# ps.ls.VTKWriter(flux, filename).apply()

mesh = ps.ls.Mesh()
ps.ToDiskMesh(geometry, mesh).apply()
points = np.array(mesh.getNodes())
cuts = points[:, 1] < 0.25
points = points[cuts]
return points
# return points, fluxValues


p = run_simulation(0.1, "flux_0p1")
plt.plot(p[:, 0], p[:, 1], "--")
p = run_simulation(0.01, "flux_0p01")
plt.plot(p[:, 0], p[:, 1], ".-")
p = run_simulation(0.05, "flux_0p05")
plt.plot(p[:, 0], p[:, 1], "-")
plt.show()


# rayParams = ps.RayTracingParameters()
# rayParams.raysPerPoint = int(params["numRaysPerPoint"])

# ALP = ps.Process(geometry, model)
# ALP.setParameters(rayParams)
# ALP.setParameters(alpParams)
# ALP.apply()
params = ps.readConfigFile("config.txt")
geometry = ps.Domain()

# Create the geometry
boundaryCons = [
ps.BoundaryType.REFLECTIVE_BOUNDARY,
ps.BoundaryType.INFINITE_BOUNDARY,
]
gridDelta = params["gridDelta"]
bounds = [
0.0,
params["openingWidth"] / 2.0 + params["xPad"] + params["gapLength"],
-gridDelta,
params["openingDepth"] + params["gapHeight"] + gridDelta,
]

substrate = ls.Domain(bounds, boundaryCons, gridDelta)
normal = [0.0, 1.0]
origin = [0.0, params["openingDepth"] + params["gapHeight"]]
ls.MakeGeometry(substrate, ls.Plane(origin, normal)).apply()

geometry.insertNextLevelSetAsMaterial(substrate, ps.Material.Si)

vertBox = ls.Domain(bounds, boundaryCons, gridDelta)
minPoint = [-gridDelta, 0.0]
maxPoint = [
params["openingWidth"] / 2.0,
params["gapHeight"] + params["openingDepth"] + gridDelta,
]
ls.MakeGeometry(vertBox, ls.Box(minPoint, maxPoint)).apply()

geometry.applyBooleanOperation(vertBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)

horiBox = ls.Domain(bounds, boundaryCons, gridDelta)
minPoint = [params["openingWidth"] / 2.0 - gridDelta, 0.0]
maxPoint = [params["openingWidth"] / 2.0 + params["gapLength"], params["gapHeight"]]
ls.MakeGeometry(horiBox, ls.Box(minPoint, maxPoint)).apply()
geometry.applyBooleanOperation(horiBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)

geometry.saveSurfaceMesh("SingleParticleALD_initial")

model = ps.SingleParticleProcess(rate=1.0, stickingProbability=1e-4)

geometry.duplicateTopLevelSet(ps.Material.Al2O3)

gasMFP = ps.constants.gasMeanFreePath(
params["pressure"], params["temperature"], params["diameter"]
)
print("Mean free path: ", gasMFP, " um")

model = ps.SingleParticleALD(
stickingProbability=params["stickingProbability"],
numCycles=int(params["numCycles"]),
growthPerCycle=params["growthPerCycle"],
totalCycles=int(params["totalCycles"]),
coverageTimeStep=params["coverageTimeStep"],
evFlux=params["evFlux"],
inFlux=params["inFlux"],
s0=params["s0"],
gasMFP=gasMFP,
)

alpParams = ps.AtomicLayerProcessParameters()
alpParams.pulseTime = params["pulseTime"]
alpParams.coverageTimeStep = params["coverageTimeStep"]
alpParams.numCycles = int(params["numCycles"])

rayParams = ps.RayTracingParameters()
rayParams.raysPerPoint = int(params["numRaysPerPoint"])

ALP = ps.Process(geometry, model)
ALP.setParameters(rayParams)
ALP.setParameters(alpParams)
ALP.apply()

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

# geometry.saveVolumeMesh("SingleParticleALD_final")
geometry.saveSurfaceMesh("SingleParticleALD_final")
3 changes: 2 additions & 1 deletion examples/blazedGratingsEtching/blazedGratingsEtching.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
ibeParams = ps.IBEParameters()
ibeParams.exponent = params["exponent"]
ibeParams.meanEnergy = params["meanEnergy"]
ibeParams.materialPlaneWaferRate = {ps.Material.SiO2: 1, ps.Material.Mask: 1 / 11}
ibeParams.materialPlaneWaferRate.set(ps.Material.SiO2, 1.0)
ibeParams.materialPlaneWaferRate.set(ps.Material.Mask, 1.0 / 11.0)
ibeParams.cos4Yield.isDefined = True
ibeParams.cos4Yield.a1 = params["yieldFactor"]
ibeParams.cos4Yield.a2 = -1.55
Expand Down
Loading
Loading