Skip to content
Merged
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ CPMAddPackage(

CPMAddPackage(
NAME ViennaRay
VERSION 3.10.1
VERSION 3.10.2
GIT_REPOSITORY "https://github.com/ViennaTools/ViennaRay"
EXCLUDE_FROM_ALL ${VIENNAPS_BUILD_PYTHON}
OPTIONS "VIENNARAY_USE_GPU ${VIENNAPS_USE_GPU}")
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ ViennaPS is also available on the [Python Package Index (PyPI)](https://pypi.org

* macOS (clang)

* Windows (Visual Studio)
* Windows (MSVC)

### System Requirements

* C++20 Compiler with OpenMP support

### ViennaTools Dependencies (installed automatically)

ViennaPS is part of the ViennaTools ecosystem and depends on several lightweight, header-only ViennaTools libraries. During configuration, CMake will look for them and fetch them automatically as part of the ViennaPS build. No separate installation step is required for these dependencies:
ViennaPS is part of the ViennaTools ecosystem and depends on several lightweight, header-only ViennaTools libraries. During configuration, CMake will fetch them automatically as part of the ViennaPS build. No separate installation step is required for these dependencies:

* [ViennaCore](https://github.com/ViennaTools/viennacore)
* [ViennaLS](https://github.com/ViennaTools/viennals)
Expand Down Expand Up @@ -98,6 +98,14 @@ cd ViennaPS
pip install .
```

To build the Python package with **GPU** support, use the install script in `python/scripts` folder. On Linux, e.g., run:
```bash
python3 -m venv .venv # create virtual environment (optional, but recommended)
source .venv/bin/activate # activate virtual environment
python python/scripts/install_ViennaPS.py
```
A CUDA toolkit and driver compatible with your GPU must be installed on your system to use the GPU functionality.

> Some features of the ViennaPS Python module depend on the ViennaLS Python module. The ViennaLS is installed automatically as a dependency.
> Note: A locally built ViennaPS Python module is typically not compatible with the ViennaLS package from PyPI. For details and troubleshooting, see [this guide](https://viennatools.github.io/ViennaPS/inst/troubleshooting.html#python-importerror).

Expand Down
21 changes: 9 additions & 12 deletions examples/DRAMWiggling/DRAMWiggling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
using namespace viennaps;

int main(int argc, char **argv) {
using NumericType = double;
constexpr int D = 3;

Logger::setLogLevel(LogLevel::INFO);
omp_set_num_threads(12);
Expand All @@ -27,23 +25,22 @@ int main(int argc, char **argv) {
units::Length::setUnit(params.get<std::string>("lengthUnit"));
units::Time::setUnit(params.get<std::string>("timeUnit"));

constexpr NumericType gridDelta = 0.01 * (1. + 1e-12);
BoundaryType boundaryConds[D] = {BoundaryType::REFLECTIVE_BOUNDARY,
constexpr double gridDelta = 0.01 * (1. + 1e-12);
BoundaryType boundaryConds[3] = {BoundaryType::REFLECTIVE_BOUNDARY,
BoundaryType::REFLECTIVE_BOUNDARY,
BoundaryType::INFINITE_BOUNDARY};

auto mask =
SmartPointer<GDSGeometry<NumericType, D>>::New(gridDelta, boundaryConds);
auto mask = SmartPointer<GDSGeometry_double_3>::New(gridDelta, boundaryConds);
mask->setBoundaryPadding(0.1, 0.1);
GDSReader<NumericType, D>(mask, params.get<std::string>("gdsFile")).apply();
GDSReader_double_3(mask, params.get<std::string>("gdsFile")).apply();

// geometry setup
auto geometry = Domain<NumericType, D>::New();
auto geometry = Domain_double_3::New();
auto maskLS = mask->layerToLevelSet(0, 0.0, 0.18);
geometry->insertNextLevelSetAsMaterial(maskLS, Material::Mask);
MakePlane<NumericType, D>(geometry, 0.0, Material::Si, true).apply();
MakePlane_double_3(geometry, 0.0, Material::Si, true).apply();

auto modelParams = HBrO2Etching<NumericType, D>::defaultParameters();
auto modelParams = HBrO2Etching_double_3::defaultParameters();
modelParams.ionFlux = params.get("ionFlux");
modelParams.etchantFlux = params.get("etchantFlux");
modelParams.passivationFlux = params.get("oxygenFlux");
Expand All @@ -52,7 +49,7 @@ int main(int argc, char **argv) {
modelParams.Ions.exponent = params.get("ionExponent");
modelParams.Ions.n_l = 200;
modelParams.Substrate.B_sp = 0.75;
auto model = SmartPointer<HBrO2Etching<NumericType, D>>::New(modelParams);
auto model = SmartPointer<HBrO2Etching_double_3>::New(modelParams);

// Advection parameters
AdvectionParameters advectionParams;
Expand All @@ -69,7 +66,7 @@ int main(int argc, char **argv) {
coverageParams.tolerance = 1e-5;

// Process setup
Process<NumericType, D> process(geometry, model, params.get("processTime"));
Process_double_3 process(geometry, model, params.get("processTime"));
process.setParameters(advectionParams);
process.setParameters(rayParams);
process.setParameters(coverageParams);
Expand Down
8 changes: 2 additions & 6 deletions examples/DRAMWiggling/DRAMWiggling.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@
# Add plane
ps.MakePlane(geometry, 0.0, ps.Material.Si, True).apply()

# print intermediate output surfaces during the process
ps.Logger.setLogLevel(ps.LogLevel.INFO)

ps.Length.setUnit(params["lengthUnit"])
ps.Time.setUnit(params["timeUnit"])

Expand All @@ -49,6 +46,7 @@
modelParams.Ions.sigmaEnergy = params["sigmaEnergy"]
modelParams.Ions.exponent = params["ionExponent"]
modelParams.Ions.n_l = 200
modelParams.Substrate.B_sp = 0.75
model = ps.HBrO2Etching(modelParams)

coverageParameters = ps.CoverageParameters()
Expand All @@ -58,9 +56,7 @@
rayTracingParams.raysPerPoint = int(params["raysPerPoint"])

advectionParams = ps.AdvectionParameters()
advectionParams.spatialScheme = ps.util.convertSpatialScheme(
params["spatialScheme"]
)
advectionParams.spatialScheme = ps.util.convertSpatialScheme(params["spatialScheme"])

fluxEngineStr = params["fluxEngine"]
fluxEngine = ps.util.convertFluxEngineType(fluxEngineStr)
Expand Down
6 changes: 3 additions & 3 deletions examples/SiGeSelectiveEtching/SiGeEtching.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import viennaps.d2 as psd
import viennaps as ps
from SiGeStackGeometry import CreateGeometry

ps.setDimension(2)
ps.setNumThreads(16)

# create initial geometry
Expand Down Expand Up @@ -71,7 +71,7 @@
ps.Material.SiGe: 0.7,
}

model = psd.CF4O2Etching(modelParams)
model = ps.CF4O2Etching(modelParams)
parameters = model.getParameters()

covParams = ps.CoverageParameters()
Expand All @@ -85,7 +85,7 @@
advParams.timeStepRatio = 0.2

# process setup
process = psd.Process()
process = ps.Process()
process.setDomain(geometry)
process.setProcessModel(model)
process.setProcessDuration(params["processTime"]) # seconds
Expand Down
35 changes: 17 additions & 18 deletions examples/SiGeSelectiveEtching/SiGeStackGeometry.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# Create a SiGe stack geometry with SiO2 mask

import viennaps.d2 as psd
import viennaps as ps
import viennals.d2 as lsd
from viennals import BooleanOperationEnum

ps.setDimension(2)

def CreateGeometry(paramDict: dict) -> psd.Domain:
domain = psd.Domain()

def CreateGeometry(paramDict: dict) -> ps.Domain:
domain = ps.Domain()
totalHeight = paramDict["numLayers"] * paramDict["layerHeight"]
extent = (
2 * paramDict["lateralSpacing"]
Expand All @@ -25,17 +24,17 @@ def CreateGeometry(paramDict: dict) -> psd.Domain:
origin = [0, 0]

# substrate plane
plane = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
lsd.MakeGeometry(plane, lsd.Plane(origin, normal)).apply()
plane = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
ps.ls.MakeGeometry(plane, ps.ls.Plane(origin, normal)).apply()
domain.insertNextLevelSetAsMaterial(
levelSet=plane, material=ps.Material.Si, wrapLowerLevelSet=True
)

# alternating layers
for i in range(paramDict["numLayers"]):
origin[1] += paramDict["layerHeight"]
plane = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
lsd.MakeGeometry(plane, lsd.Plane(origin, normal)).apply()
plane = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
ps.ls.MakeGeometry(plane, ps.ls.Plane(origin, normal)).apply()
if i % 2 == 0:
domain.insertNextLevelSetAsMaterial(plane, ps.Material.SiGe)
else:
Expand All @@ -44,15 +43,15 @@ def CreateGeometry(paramDict: dict) -> psd.Domain:
# SiO2 mask
maskPosY = totalHeight + paramDict["maskHeight"]
origin[1] = maskPosY
mask = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
lsd.MakeGeometry(mask, lsd.Plane(origin, normal)).apply()
mask = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
ps.ls.MakeGeometry(mask, ps.ls.Plane(origin, normal)).apply()
domain.insertNextLevelSetAsMaterial(mask, ps.Material.SiO2)

# mask
maskPosY = totalHeight + paramDict["maskHeight"] + 5 * paramDict["gridDelta"]
origin[1] = maskPosY
etchMask = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
lsd.MakeGeometry(etchMask, lsd.Plane(origin, normal)).apply()
etchMask = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
ps.ls.MakeGeometry(etchMask, ps.ls.Plane(origin, normal)).apply()
domain.insertNextLevelSetAsMaterial(etchMask, ps.Material.Mask)

# left right space
Expand All @@ -64,20 +63,20 @@ def CreateGeometry(paramDict: dict) -> psd.Domain:
-extent / 2 + paramDict["lateralSpacing"],
maskPosY + paramDict["gridDelta"],
]
box = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
lsd.MakeGeometry(box, lsd.Box(minPoint, maxPoint)).apply()
box = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
ps.ls.MakeGeometry(box, ps.ls.Box(minPoint, maxPoint)).apply()
domain.applyBooleanOperation(box, BooleanOperationEnum.RELATIVE_COMPLEMENT)

minPoint[0] = extent / 2 - paramDict["lateralSpacing"]
maxPoint[0] = extent / 2 + paramDict["gridDelta"]
lsd.MakeGeometry(box, lsd.Box(minPoint, maxPoint)).apply()
ps.ls.MakeGeometry(box, ps.ls.Box(minPoint, maxPoint)).apply()
domain.applyBooleanOperation(box, BooleanOperationEnum.RELATIVE_COMPLEMENT)

xpos = -extent / 2 + paramDict["lateralSpacing"] + paramDict["maskWidth"]
for i in range(paramDict["numPillars"]):
minPoint[0] = xpos
maxPoint[0] = xpos + paramDict["trenchWidthTop"]
lsd.MakeGeometry(box, lsd.Box(minPoint, maxPoint)).apply()
ps.ls.MakeGeometry(box, ps.ls.Box(minPoint, maxPoint)).apply()
domain.applyBooleanOperation(box, BooleanOperationEnum.RELATIVE_COMPLEMENT)
xpos += paramDict["maskWidth"] + paramDict["trenchWidthTop"]

Expand All @@ -90,14 +89,14 @@ def CreateGeometry(paramDict: dict) -> psd.Domain:
* (paramDict["trenchWidthTop"] - paramDict["trenchWidthBottom"])
/ (paramDict["numLayers"] * paramDict["layerHeight"] + paramDict["maskHeight"])
)
processModel = psd.DirectionalProcess(direction, -1, isoVel, ps.Material.Mask)
processModel = ps.DirectionalProcess(direction, -1, isoVel, ps.Material.Mask)

time = (
paramDict["numLayers"] * paramDict["layerHeight"]
+ paramDict["maskHeight"]
+ paramDict["overEtch"]
)
psd.Process(domain, processModel, time).apply()
ps.Process(domain, processModel, time).apply()

# remove trench etching mask
domain.removeTopLevelSet()
Expand Down
4 changes: 2 additions & 2 deletions examples/TEOSTrenchDeposition/multiTEOS.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
process.setParameters(rayParams)
process.setProcessDuration(params["processTime"])

geometry.saveVolumeMesh("MultiTEOS_initial.vtp")
geometry.saveVolumeMesh("MultiTEOS_initial")

process.apply()

geometry.saveVolumeMesh("MultiTEOS_final.vtp")
geometry.saveVolumeMesh("MultiTEOS_final")
4 changes: 2 additions & 2 deletions examples/TEOSTrenchDeposition/singleTEOS.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
process.setParameters(rayParams)
process.setProcessDuration(params["processTime"])

geometry.saveVolumeMesh("SingleTEOS_initial.vtp")
geometry.saveVolumeMesh("SingleTEOS_initial")

process.apply()

geometry.saveVolumeMesh("SingleTEOS_final.vtp")
geometry.saveVolumeMesh("SingleTEOS_final")
4 changes: 2 additions & 2 deletions examples/atomicLayerDeposition/atomicLayerDeposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
ls.MakeGeometry(horiBox, ls.Box(minPoint, maxPoint)).apply()
geometry.applyBooleanOperation(horiBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)

geometry.saveVolumeMesh("SingleParticleALD_initial.vtu")
geometry.saveVolumeMesh("SingleParticleALD_initial")

geometry.duplicateTopLevelSet(ps.Material.Al2O3)

Expand Down Expand Up @@ -81,4 +81,4 @@
# MeasureProfile<NumericType, D>(domain, params.get("gapHeight") / 2.)
# .save(params.get<std::string>("outputFile"));

geometry.saveVolumeMesh("SingleParticleALD_final.vtu")
geometry.saveVolumeMesh("SingleParticleALD_final")
67 changes: 37 additions & 30 deletions examples/blazedGratingsEtching/blazedGratingsEtching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
using namespace viennaps;

int main(int argc, char **argv) {
using NumericType = double;
constexpr int D = 2;
omp_set_num_threads(16);
Logger::setLogLevel(LogLevel::DEBUG);

// Parse the parameters
util::Parameters params;
Expand All @@ -25,10 +24,10 @@ int main(int argc, char **argv) {
}
}

auto geometry = GenerateMask<NumericType, D>(
params.get("bumpWidth"), params.get("bumpHeight"),
params.get<int>("numBumps"), params.get("bumpDuty"),
params.get("gridDelta"));
auto geometry =
GenerateMask<double, 2>(params.get("bumpWidth"), params.get("bumpHeight"),
params.get<int>("numBumps"),
params.get("bumpDuty"), params.get("gridDelta"));
geometry->saveSurfaceMesh("initial");

AdvectionParameters advParams;
Expand All @@ -40,9 +39,9 @@ int main(int argc, char **argv) {
rayTracingParams.raysPerPoint = params.get<unsigned>("raysPerPoint");
rayTracingParams.smoothingNeighbors = 1;

const NumericType yieldFac = params.get("yieldFactor");
const double yieldFac = params.get("yieldFactor");

IBEParameters<NumericType> ibeParams;
IBEParameters<double> ibeParams;
ibeParams.materialPlaneWaferRate[Material::SiO2] = 1.0;
ibeParams.materialPlaneWaferRate[Material::Mask] = 1. / 11.;
ibeParams.exponent = params.get("exponent");
Expand All @@ -51,36 +50,44 @@ int main(int argc, char **argv) {
ibeParams.cos4Yield.a1 = yieldFac;
ibeParams.cos4Yield.a2 = -1.55;
ibeParams.cos4Yield.a3 = 0.65;
auto model = SmartPointer<IonBeamEtching<NumericType, D>>::New(ibeParams);

Process<NumericType, D> process(geometry, model);
process.setParameters(advParams);
process.setParameters(rayTracingParams);

// ANSGM Etch
NumericType angle = params.get("phi1");
NumericType angleRad = constants::degToRad(angle);
model->setPrimaryDirection(
Vec3D<NumericType>{-std::sin(angleRad), -std::cos(angleRad), 0});
ibeParams.tiltAngle = angle;
{
double angle = params.get("phi1");
double angleRad = constants::degToRad(angle);
ibeParams.tiltAngle = angle;
auto model = SmartPointer<IonBeamEtching_double_2>::New(ibeParams);
model->setPrimaryDirection(
Vec3Dd{-std::sin(angleRad), -std::cos(angleRad), 0});
model->setProcessName("ANSGM_Etch");

process.setProcessDuration(params.get("ANSGM_Depth"));
process.apply();
geometry->saveSurfaceMesh("ANSGM_Etch");
Process_double_2(geometry, model, params.get("ANSGM_Depth"), advParams,
rayTracingParams)
.apply();
geometry->saveSurfaceMesh("ANSGM_Etch");
}

geometry->removeTopLevelSet(); // remove mask
geometry->saveSurfaceMesh("ANSGM");

// Blazed Gratings Etch
angle = params.get("phi2");
angleRad = constants::degToRad(angle);
model->setPrimaryDirection(
Vec3D<NumericType>{-std::sin(angleRad), -std::cos(angleRad), 0});
ibeParams.tiltAngle = angle;
{
double angle = params.get("phi2");
double angleRad = constants::degToRad(angle);
ibeParams.tiltAngle = angle;
auto model = SmartPointer<IonBeamEtching_double_2>::New(ibeParams);
model->setPrimaryDirection(
Vec3Dd{-std::sin(angleRad), -std::cos(angleRad), 0});
model->setProcessName("BlazedGratings_Etch");

for (int i = 1; i < 5; ++i) {
process.setProcessDuration(params.get("etchTimeP" + std::to_string(i)));
process.apply();
geometry->saveSurfaceMesh("BlazedGratingsEtch_P" + std::to_string(i));
Process_double_2 process(geometry, model);
process.setParameters(advParams);
process.setParameters(rayTracingParams);

for (int i = 1; i < 5; ++i) {
process.setProcessDuration(params.get("etchTimeP" + std::to_string(i)));
process.apply();
geometry->saveSurfaceMesh("BlazedGratingsEtch_P" + std::to_string(i));
}
}
}
Loading
Loading