Skip to content

Commit 0585707

Browse files
authored
refactor: split ElementToPointData into prepare and convert phase, fix: update examples (#197)
* Add Windwos Python install script * Format * Merge Linux and Windows GPU install scripts, relax GCC requirements * Example formatting * Fix blazed gratings example * Update process flags before selecting flux engine * Remove uneccessary dynamic pointer casts * refactor: split ElementToPointData into prepare and convert phase * add comments * refactor: remove IndexMap, get particle data labels from ProcessModel * Fix examples * Small fixes in examples
1 parent 62766a1 commit 0585707

33 files changed

Lines changed: 597 additions & 507 deletions

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ CPMAddPackage(
117117

118118
CPMAddPackage(
119119
NAME ViennaRay
120-
VERSION 3.10.1
120+
VERSION 3.10.2
121121
GIT_REPOSITORY "https://github.com/ViennaTools/ViennaRay"
122122
EXCLUDE_FROM_ALL ${VIENNAPS_BUILD_PYTHON}
123123
OPTIONS "VIENNARAY_USE_GPU ${VIENNAPS_USE_GPU}")

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ ViennaPS is also available on the [Python Package Index (PyPI)](https://pypi.org
4747

4848
* macOS (clang)
4949

50-
* Windows (Visual Studio)
50+
* Windows (MSVC)
5151

5252
### System Requirements
5353

5454
* C++20 Compiler with OpenMP support
5555

5656
### ViennaTools Dependencies (installed automatically)
5757

58-
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:
58+
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:
5959

6060
* [ViennaCore](https://github.com/ViennaTools/viennacore)
6161
* [ViennaLS](https://github.com/ViennaTools/viennals)
@@ -98,6 +98,14 @@ cd ViennaPS
9898
pip install .
9999
```
100100

101+
To build the Python package with **GPU** support, use the install script in `python/scripts` folder. On Linux, e.g., run:
102+
```bash
103+
python3 -m venv .venv # create virtual environment (optional, but recommended)
104+
source .venv/bin/activate # activate virtual environment
105+
python python/scripts/install_ViennaPS.py
106+
```
107+
A CUDA toolkit and driver compatible with your GPU must be installed on your system to use the GPU functionality.
108+
101109
> Some features of the ViennaPS Python module depend on the ViennaLS Python module. The ViennaLS is installed automatically as a dependency.
102110
> 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).
103111

examples/DRAMWiggling/DRAMWiggling.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
using namespace viennaps;
44

55
int main(int argc, char **argv) {
6-
using NumericType = double;
7-
constexpr int D = 3;
86

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

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

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

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

46-
auto modelParams = HBrO2Etching<NumericType, D>::defaultParameters();
43+
auto modelParams = HBrO2Etching_double_3::defaultParameters();
4744
modelParams.ionFlux = params.get("ionFlux");
4845
modelParams.etchantFlux = params.get("etchantFlux");
4946
modelParams.passivationFlux = params.get("oxygenFlux");
@@ -52,7 +49,7 @@ int main(int argc, char **argv) {
5249
modelParams.Ions.exponent = params.get("ionExponent");
5350
modelParams.Ions.n_l = 200;
5451
modelParams.Substrate.B_sp = 0.75;
55-
auto model = SmartPointer<HBrO2Etching<NumericType, D>>::New(modelParams);
52+
auto model = SmartPointer<HBrO2Etching_double_3>::New(modelParams);
5653

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

7168
// Process setup
72-
Process<NumericType, D> process(geometry, model, params.get("processTime"));
69+
Process_double_3 process(geometry, model, params.get("processTime"));
7370
process.setParameters(advectionParams);
7471
process.setParameters(rayParams);
7572
process.setParameters(coverageParams);

examples/DRAMWiggling/DRAMWiggling.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@
3535
# Add plane
3636
ps.MakePlane(geometry, 0.0, ps.Material.Si, True).apply()
3737

38-
# print intermediate output surfaces during the process
39-
ps.Logger.setLogLevel(ps.LogLevel.INFO)
40-
4138
ps.Length.setUnit(params["lengthUnit"])
4239
ps.Time.setUnit(params["timeUnit"])
4340

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

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

6058
advectionParams = ps.AdvectionParameters()
61-
advectionParams.spatialScheme = ps.util.convertSpatialScheme(
62-
params["spatialScheme"]
63-
)
59+
advectionParams.spatialScheme = ps.util.convertSpatialScheme(params["spatialScheme"])
6460

6561
fluxEngineStr = params["fluxEngine"]
6662
fluxEngine = ps.util.convertFluxEngineType(fluxEngineStr)

examples/SiGeSelectiveEtching/SiGeEtching.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import viennaps.d2 as psd
21
import viennaps as ps
32
from SiGeStackGeometry import CreateGeometry
43

4+
ps.setDimension(2)
55
ps.setNumThreads(16)
66

77
# create initial geometry
@@ -71,7 +71,7 @@
7171
ps.Material.SiGe: 0.7,
7272
}
7373

74-
model = psd.CF4O2Etching(modelParams)
74+
model = ps.CF4O2Etching(modelParams)
7575
parameters = model.getParameters()
7676

7777
covParams = ps.CoverageParameters()
@@ -85,7 +85,7 @@
8585
advParams.timeStepRatio = 0.2
8686

8787
# process setup
88-
process = psd.Process()
88+
process = ps.Process()
8989
process.setDomain(geometry)
9090
process.setProcessModel(model)
9191
process.setProcessDuration(params["processTime"]) # seconds

examples/SiGeSelectiveEtching/SiGeStackGeometry.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Create a SiGe stack geometry with SiO2 mask
22

3-
import viennaps.d2 as psd
43
import viennaps as ps
5-
import viennals.d2 as lsd
64
from viennals import BooleanOperationEnum
75

6+
ps.setDimension(2)
87

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

9+
def CreateGeometry(paramDict: dict) -> ps.Domain:
10+
domain = ps.Domain()
1211
totalHeight = paramDict["numLayers"] * paramDict["layerHeight"]
1312
extent = (
1413
2 * paramDict["lateralSpacing"]
@@ -25,17 +24,17 @@ def CreateGeometry(paramDict: dict) -> psd.Domain:
2524
origin = [0, 0]
2625

2726
# substrate plane
28-
plane = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
29-
lsd.MakeGeometry(plane, lsd.Plane(origin, normal)).apply()
27+
plane = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
28+
ps.ls.MakeGeometry(plane, ps.ls.Plane(origin, normal)).apply()
3029
domain.insertNextLevelSetAsMaterial(
3130
levelSet=plane, material=ps.Material.Si, wrapLowerLevelSet=True
3231
)
3332

3433
# alternating layers
3534
for i in range(paramDict["numLayers"]):
3635
origin[1] += paramDict["layerHeight"]
37-
plane = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
38-
lsd.MakeGeometry(plane, lsd.Plane(origin, normal)).apply()
36+
plane = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
37+
ps.ls.MakeGeometry(plane, ps.ls.Plane(origin, normal)).apply()
3938
if i % 2 == 0:
4039
domain.insertNextLevelSetAsMaterial(plane, ps.Material.SiGe)
4140
else:
@@ -44,15 +43,15 @@ def CreateGeometry(paramDict: dict) -> psd.Domain:
4443
# SiO2 mask
4544
maskPosY = totalHeight + paramDict["maskHeight"]
4645
origin[1] = maskPosY
47-
mask = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
48-
lsd.MakeGeometry(mask, lsd.Plane(origin, normal)).apply()
46+
mask = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
47+
ps.ls.MakeGeometry(mask, ps.ls.Plane(origin, normal)).apply()
4948
domain.insertNextLevelSetAsMaterial(mask, ps.Material.SiO2)
5049

5150
# mask
5251
maskPosY = totalHeight + paramDict["maskHeight"] + 5 * paramDict["gridDelta"]
5352
origin[1] = maskPosY
54-
etchMask = lsd.Domain(bounds, boundaryConds, paramDict["gridDelta"])
55-
lsd.MakeGeometry(etchMask, lsd.Plane(origin, normal)).apply()
53+
etchMask = ps.ls.Domain(bounds, boundaryConds, paramDict["gridDelta"])
54+
ps.ls.MakeGeometry(etchMask, ps.ls.Plane(origin, normal)).apply()
5655
domain.insertNextLevelSetAsMaterial(etchMask, ps.Material.Mask)
5756

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

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

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

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

9594
time = (
9695
paramDict["numLayers"] * paramDict["layerHeight"]
9796
+ paramDict["maskHeight"]
9897
+ paramDict["overEtch"]
9998
)
100-
psd.Process(domain, processModel, time).apply()
99+
ps.Process(domain, processModel, time).apply()
101100

102101
# remove trench etching mask
103102
domain.removeTopLevelSet()

examples/TEOSTrenchDeposition/multiTEOS.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@
5353
process.setParameters(rayParams)
5454
process.setProcessDuration(params["processTime"])
5555

56-
geometry.saveVolumeMesh("MultiTEOS_initial.vtp")
56+
geometry.saveVolumeMesh("MultiTEOS_initial")
5757

5858
process.apply()
5959

60-
geometry.saveVolumeMesh("MultiTEOS_final.vtp")
60+
geometry.saveVolumeMesh("MultiTEOS_final")

examples/TEOSTrenchDeposition/singleTEOS.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
process.setParameters(rayParams)
5252
process.setProcessDuration(params["processTime"])
5353

54-
geometry.saveVolumeMesh("SingleTEOS_initial.vtp")
54+
geometry.saveVolumeMesh("SingleTEOS_initial")
5555

5656
process.apply()
5757

58-
geometry.saveVolumeMesh("SingleTEOS_final.vtp")
58+
geometry.saveVolumeMesh("SingleTEOS_final")

examples/atomicLayerDeposition/atomicLayerDeposition.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
ls.MakeGeometry(horiBox, ls.Box(minPoint, maxPoint)).apply()
4444
geometry.applyBooleanOperation(horiBox, ls.BooleanOperationEnum.RELATIVE_COMPLEMENT)
4545

46-
geometry.saveVolumeMesh("SingleParticleALD_initial.vtu")
46+
geometry.saveVolumeMesh("SingleParticleALD_initial")
4747

4848
geometry.duplicateTopLevelSet(ps.Material.Al2O3)
4949

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

84-
geometry.saveVolumeMesh("SingleParticleALD_final.vtu")
84+
geometry.saveVolumeMesh("SingleParticleALD_final")

examples/blazedGratingsEtching/blazedGratingsEtching.cpp

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
using namespace viennaps;
88

99
int main(int argc, char **argv) {
10-
using NumericType = double;
11-
constexpr int D = 2;
1210
omp_set_num_threads(16);
11+
Logger::setLogLevel(LogLevel::DEBUG);
1312

1413
// Parse the parameters
1514
util::Parameters params;
@@ -25,10 +24,10 @@ int main(int argc, char **argv) {
2524
}
2625
}
2726

28-
auto geometry = GenerateMask<NumericType, D>(
29-
params.get("bumpWidth"), params.get("bumpHeight"),
30-
params.get<int>("numBumps"), params.get("bumpDuty"),
31-
params.get("gridDelta"));
27+
auto geometry =
28+
GenerateMask<double, 2>(params.get("bumpWidth"), params.get("bumpHeight"),
29+
params.get<int>("numBumps"),
30+
params.get("bumpDuty"), params.get("gridDelta"));
3231
geometry->saveSurfaceMesh("initial");
3332

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

43-
const NumericType yieldFac = params.get("yieldFactor");
42+
const double yieldFac = params.get("yieldFactor");
4443

45-
IBEParameters<NumericType> ibeParams;
44+
IBEParameters<double> ibeParams;
4645
ibeParams.materialPlaneWaferRate[Material::SiO2] = 1.0;
4746
ibeParams.materialPlaneWaferRate[Material::Mask] = 1. / 11.;
4847
ibeParams.exponent = params.get("exponent");
@@ -51,36 +50,44 @@ int main(int argc, char **argv) {
5150
ibeParams.cos4Yield.a1 = yieldFac;
5251
ibeParams.cos4Yield.a2 = -1.55;
5352
ibeParams.cos4Yield.a3 = 0.65;
54-
auto model = SmartPointer<IonBeamEtching<NumericType, D>>::New(ibeParams);
55-
56-
Process<NumericType, D> process(geometry, model);
57-
process.setParameters(advParams);
58-
process.setParameters(rayTracingParams);
5953

6054
// ANSGM Etch
61-
NumericType angle = params.get("phi1");
62-
NumericType angleRad = constants::degToRad(angle);
63-
model->setPrimaryDirection(
64-
Vec3D<NumericType>{-std::sin(angleRad), -std::cos(angleRad), 0});
65-
ibeParams.tiltAngle = angle;
55+
{
56+
double angle = params.get("phi1");
57+
double angleRad = constants::degToRad(angle);
58+
ibeParams.tiltAngle = angle;
59+
auto model = SmartPointer<IonBeamEtching_double_2>::New(ibeParams);
60+
model->setPrimaryDirection(
61+
Vec3Dd{-std::sin(angleRad), -std::cos(angleRad), 0});
62+
model->setProcessName("ANSGM_Etch");
6663

67-
process.setProcessDuration(params.get("ANSGM_Depth"));
68-
process.apply();
69-
geometry->saveSurfaceMesh("ANSGM_Etch");
64+
Process_double_2(geometry, model, params.get("ANSGM_Depth"), advParams,
65+
rayTracingParams)
66+
.apply();
67+
geometry->saveSurfaceMesh("ANSGM_Etch");
68+
}
7069

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

7473
// Blazed Gratings Etch
75-
angle = params.get("phi2");
76-
angleRad = constants::degToRad(angle);
77-
model->setPrimaryDirection(
78-
Vec3D<NumericType>{-std::sin(angleRad), -std::cos(angleRad), 0});
79-
ibeParams.tiltAngle = angle;
74+
{
75+
double angle = params.get("phi2");
76+
double angleRad = constants::degToRad(angle);
77+
ibeParams.tiltAngle = angle;
78+
auto model = SmartPointer<IonBeamEtching_double_2>::New(ibeParams);
79+
model->setPrimaryDirection(
80+
Vec3Dd{-std::sin(angleRad), -std::cos(angleRad), 0});
81+
model->setProcessName("BlazedGratings_Etch");
8082

81-
for (int i = 1; i < 5; ++i) {
82-
process.setProcessDuration(params.get("etchTimeP" + std::to_string(i)));
83-
process.apply();
84-
geometry->saveSurfaceMesh("BlazedGratingsEtch_P" + std::to_string(i));
83+
Process_double_2 process(geometry, model);
84+
process.setParameters(advParams);
85+
process.setParameters(rayTracingParams);
86+
87+
for (int i = 1; i < 5; ++i) {
88+
process.setProcessDuration(params.get("etchTimeP" + std::to_string(i)));
89+
process.apply();
90+
geometry->saveSurfaceMesh("BlazedGratingsEtch_P" + std::to_string(i));
91+
}
8592
}
8693
}

0 commit comments

Comments
 (0)