From 0a5d1d8cb22973c3cc0fa25dbc049802ed78cd77 Mon Sep 17 00:00:00 2001 From: Tobias Reiter <44025882+tobre1@users.noreply.github.com> Date: Mon, 24 Feb 2025 09:22:57 +0100 Subject: [PATCH] Refactor basic geometry builders and add new domain setup (#112) * Test domain setup * Refactor MakeTrench with new domain setup * Setup python bindings for new setup * Domain setup Python bindings * Refactor MakeHole * Add geometry base builder * Refactor MakePlane * Refactor MakeFin * Refactor GeometryBase * More geometry builder refactoring * Domain setup check * Add Python wrappers * Rename GeometryBase to GeometryFactory! * Seperate GeometryFactory from builders * Update stub files * Minor fixes * Format application * clang format is strange * Adjust examples with new geometry builders --- CMakeLists.txt | 4 +- app/application.hpp | 9 +- app/applicationParser.hpp | 4 +- examples/TEOSTrenchDeposition/multiTEOS.cpp | 18 +- examples/TEOSTrenchDeposition/multiTEOS.py | 20 +- examples/TEOSTrenchDeposition/singleTEOS.cpp | 22 +- examples/TEOSTrenchDeposition/singleTEOS.py | 21 +- examples/boschProcess/boschProcessEmulate.cpp | 15 +- examples/boschProcess/boschProcessEmulate.py | 18 +- .../boschProcess/boschProcessRayTracing.py | 15 +- .../boschProcess/boschProcessSimulate.cpp | 11 +- examples/boschProcess/boschProcessSimulate.py | 19 +- .../faradayCageEtching/faradayCageEtching.cpp | 13 +- .../faradayCageEtching/faradayCageEtching.py | 18 +- examples/holeEtching/holeEtching.cpp | 12 +- examples/holeEtching/holeEtching.py | 19 +- examples/holeEtching/testFluxes.py | 24 +- examples/ionBeamEtching/ionBeamEtching.cpp | 21 +- examples/ionBeamEtching/ionBeamEtching.py | 23 +- examples/stackEtching/stackEtching.cpp | 10 +- examples/stackEtching/stackEtching.py | 8 +- .../trenchDeposition/trenchDeposition.cpp | 16 +- examples/trenchDeposition/trenchDeposition.py | 13 +- .../trenchDepositionGeometric.cpp | 12 +- .../trenchDepositionGeometric.py | 14 +- .../viennaps/geometries/psGeometryFactory.hpp | 212 ++++++ include/viennaps/geometries/psMakeFin.hpp | 270 ++----- include/viennaps/geometries/psMakeHole.hpp | 192 ++--- include/viennaps/geometries/psMakePlane.hpp | 100 +-- include/viennaps/geometries/psMakeStack.hpp | 328 +++------ include/viennaps/geometries/psMakeTrench.hpp | 250 ++----- .../viennaps/models/psIsotropicProcess.hpp | 2 +- .../models/psSingleParticleProcess.hpp | 2 +- include/viennaps/psAtomicLayerProcess.hpp | 2 +- include/viennaps/psDomain.hpp | 65 +- include/viennaps/psDomainSetup.hpp | 169 +++++ include/viennaps/psMaterials.hpp | 8 +- include/viennaps/psProcess.hpp | 2 +- include/viennaps/psUtils.hpp | 7 +- python/__init__.py.in | 5 +- python/generateStubs.py | 6 +- python/pyWrap.cpp | 180 +++-- python/test/viennaps2d/__init__.pyi | 3 + python/test/viennaps2d/viennaps2d.pyi | 675 ++++++++++++++++++ python/viennaps2d/viennaps2d.pyi | 222 +++++- python/viennaps3d/viennaps3d.pyi | 202 +++++- tests/fin/fin.cpp | 27 +- tests/hole/hole.cpp | 20 +- tests/materialMap/materialMap.cpp | 2 +- tests/plane/plane.cpp | 7 +- tests/stack/stack.cpp | 19 +- tests/trench/trench.cpp | 36 +- 52 files changed, 2177 insertions(+), 1215 deletions(-) create mode 100644 include/viennaps/geometries/psGeometryFactory.hpp create mode 100644 include/viennaps/psDomainSetup.hpp create mode 100644 python/test/viennaps2d/__init__.pyi create mode 100644 python/test/viennaps2d/viennaps2d.pyi diff --git a/CMakeLists.txt b/CMakeLists.txt index b62977d0..91e9c2ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ CPMAddPackage( NAME ViennaCore VERSION 1.2.0 GIT_REPOSITORY "https://github.com/ViennaTools/ViennaCore" - OPTIONS "VIENNACORE_FORMAT_EXCLUDE docs/" + OPTIONS "VIENNACORE_FORMAT_EXCLUDE app/" EXCLUDE_FROM_ALL ${VIENNAPS_BUILD_PYTHON}) CPMAddPackage( @@ -114,7 +114,7 @@ CPMFindPackage( CPMFindPackage( NAME ViennaLS - VERSION 4.2.0 + VERSION 4.2.1 GIT_REPOSITORY "https://github.com/ViennaTools/ViennaLS" EXCLUDE_FROM_ALL ${VIENNAPS_BUILD_PYTHON}) diff --git a/app/application.hpp b/app/application.hpp index 3cb54ff3..64e53459 100644 --- a/app/application.hpp +++ b/app/application.hpp @@ -306,8 +306,7 @@ template class Application { break; case GeometryType::PLANE: - std::cout << "Plane" - << "\n\tzPos: " << params->maskZPos << "\n\n"; + std::cout << "Plane" << "\n\tzPos: " << params->maskZPos << "\n\n"; if (!geometry->getLevelSets().empty()) { std::cout << "\tAdding plane to current geometry...\n\n"; MakePlane(geometry, params->maskZPos, params->material) @@ -341,8 +340,8 @@ template class Application { << "\n\tzPos: " << params->maskZPos << "\n\tinvert: " << boolString(params->maskInvert) << "\n\txPadding: " << params->xPadding - << "\n\tyPadding: " << params->yPadding << "\n\tPoint order: " - << "\n\n"; + << "\n\tyPadding: " << params->yPadding + << "\n\tPoint order: " << "\n\n"; if constexpr (D == 3) { typename viennals::Domain::BoundaryType boundaryCons[D]; @@ -604,7 +603,7 @@ template class Application { static std::string materialString(const Material material) { switch (material) { - case Material::None: + case Material::Undefined: return "None"; case Material::Mask: return "Mask"; diff --git a/app/applicationParser.hpp b/app/applicationParser.hpp index 2592c719..b2cfd214 100644 --- a/app/applicationParser.hpp +++ b/app/applicationParser.hpp @@ -56,7 +56,7 @@ class ApplicationParser { private: void parseMaterial(const std::string materialString, Material &material) { if (materialString == "Undefined") { - material = Material::None; + material = Material::Undefined; } else if (materialString == "Si") { material = Material::Si; } else if (materialString == "SiO2") { @@ -93,7 +93,7 @@ class ApplicationParser { material = Material::GaN; } else { std::cout << "Unknown material: " << materialString << std::endl; - material = Material::None; + material = Material::Undefined; } } diff --git a/examples/TEOSTrenchDeposition/multiTEOS.cpp b/examples/TEOSTrenchDeposition/multiTEOS.cpp index e78d76fb..3d282f4e 100644 --- a/examples/TEOSTrenchDeposition/multiTEOS.cpp +++ b/examples/TEOSTrenchDeposition/multiTEOS.cpp @@ -20,15 +20,12 @@ int main(int argc, char **argv) { return 1; } - auto geometry = ps::SmartPointer>::New(); - ps::MakeTrench( - geometry, params.get("gridDelta") /* grid delta */, - params.get("xExtent") /*x extent*/, params.get("yExtent") /*y extent*/, - params.get("trenchWidth") /*trench width*/, - params.get("trenchHeight") /*trench height*/, - params.get("taperAngle") /* tapering angle */, 0 /*base height*/, - false /*periodic boundary*/, false /*create mask*/, - ps::Material::Si /*material*/) + auto geometry = ps::SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + ps::MakeTrench(geometry, + params.get("trenchWidth") /*trench width*/, + params.get("trenchHeight") /*trench height*/, + params.get("taperAngle") /* tapering angle */) .apply(); // copy top layer to capture deposition @@ -48,10 +45,9 @@ int main(int argc, char **argv) { process.setNumberOfRaysPerPoint(params.get("numRaysPerPoint")); process.setProcessDuration(params.get("processTime")); - geometry->saveSurfaceMesh("MulitTEOS_initial.vtp"); + geometry->saveVolumeMesh("MulitTEOS_initial"); process.apply(); - geometry->saveSurfaceMesh("MulitTEOS_final.vtp"); geometry->saveVolumeMesh("MulitTEOS_final"); } diff --git a/examples/TEOSTrenchDeposition/multiTEOS.py b/examples/TEOSTrenchDeposition/multiTEOS.py index 3859b5cf..f83f6ca9 100644 --- a/examples/TEOSTrenchDeposition/multiTEOS.py +++ b/examples/TEOSTrenchDeposition/multiTEOS.py @@ -19,19 +19,16 @@ params = vps.ReadConfigFile(args.filename) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], trenchDepth=params["trenchHeight"], - taperingAngle=params["taperAngle"], - baseHeight=0.0, - periodicBoundary=False, - makeMask=False, - material=vps.Material.Si, + trenchTaperAngle=params["taperAngle"], ).apply() # copy top layer to capture deposition @@ -53,11 +50,8 @@ process.setNumberOfRaysPerPoint(int(params["numRaysPerPoint"])) process.setProcessDuration(params["processTime"]) -geometry.saveSurfaceMesh("MultiTEOS_initial.vtp") +geometry.saveVolumeMesh("MultiTEOS_initial.vtp") process.apply() -geometry.saveSurfaceMesh("MultiTEOS_final.vtp") - -if args.dim == 2: - geometry.saveVolumeMesh("MultiTEOS_final") +geometry.saveVolumeMesh("MultiTEOS_final.vtp") diff --git a/examples/TEOSTrenchDeposition/singleTEOS.cpp b/examples/TEOSTrenchDeposition/singleTEOS.cpp index abf2711b..53a621b9 100644 --- a/examples/TEOSTrenchDeposition/singleTEOS.cpp +++ b/examples/TEOSTrenchDeposition/singleTEOS.cpp @@ -20,15 +20,12 @@ int main(int argc, char **argv) { return 1; } - auto geometry = ps::SmartPointer>::New(); - ps::MakeTrench( - geometry, params.get("gridDelta") /* grid delta */, - params.get("xExtent") /*x extent*/, params.get("yExtent") /*y extent*/, - params.get("trenchWidth") /*trench width*/, - params.get("trenchHeight") /*trench height*/, - params.get("taperAngle") /* tapering angle */, 0 /*base height*/, - false /*periodic boundary*/, false /*create mask*/, - ps::Material::Si /*material*/) + auto geometry = ps::SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + ps::MakeTrench(geometry, + params.get("trenchWidth") /*trench width*/, + params.get("trenchHeight") /*trench height*/, + params.get("taperAngle") /* tapering angle */) .apply(); // copy top layer to capture deposition @@ -46,12 +43,9 @@ int main(int argc, char **argv) { process.setNumberOfRaysPerPoint(params.get("numRaysPerPoint")); process.setProcessDuration(params.get("processTime")); - geometry->saveSurfaceMesh("SingleTEOS_initial.vtp"); + geometry->saveVolumeMesh("SingleTEOS_initial"); process.apply(); - geometry->saveSurfaceMesh("SingleTEOS_final.vtp"); - - if constexpr (D == 2) - geometry->saveVolumeMesh("SingleTEOS_final"); + geometry->saveVolumeMesh("SingleTEOS_final"); } diff --git a/examples/TEOSTrenchDeposition/singleTEOS.py b/examples/TEOSTrenchDeposition/singleTEOS.py index ed927be4..91f757e9 100644 --- a/examples/TEOSTrenchDeposition/singleTEOS.py +++ b/examples/TEOSTrenchDeposition/singleTEOS.py @@ -19,21 +19,19 @@ params = vps.ReadConfigFile(args.filename) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], trenchDepth=params["trenchHeight"], - taperingAngle=params["taperAngle"], - baseHeight=0.0, - periodicBoundary=False, - makeMask=False, - material=vps.Material.Si, + trenchTaperAngle=params["taperAngle"], ).apply() + # copy top layer to capture deposition geometry.duplicateTopLevelSet(vps.Material.SiO2) @@ -50,11 +48,8 @@ process.setNumberOfRaysPerPoint(int(params["numRaysPerPoint"])) process.setProcessDuration(params["processTime"]) -geometry.saveSurfaceMesh("SingleTEOS_initial.vtp") +geometry.saveVolumeMesh("SingleTEOS_initial.vtp") process.apply() -geometry.saveSurfaceMesh("SingleTEOS_final.vtp") - -if args.dim == 2: - geometry.saveVolumeMesh("SingleTEOS_final") +geometry.saveVolumeMesh("SingleTEOS_final.vtp") diff --git a/examples/boschProcess/boschProcessEmulate.cpp b/examples/boschProcess/boschProcessEmulate.cpp index 5b35e173..d050fd7e 100644 --- a/examples/boschProcess/boschProcessEmulate.cpp +++ b/examples/boschProcess/boschProcessEmulate.cpp @@ -11,6 +11,7 @@ using NumericType = double; void etch(SmartPointer> domain, utils::Parameters ¶ms) { + std::cout << " - Etching - " << std::endl; typename DirectionalEtching::RateSet rateSet; rateSet.direction = {0.}; rateSet.direction[D - 1] = -1.; @@ -27,6 +28,7 @@ void etch(SmartPointer> domain, void punchThrough(SmartPointer> domain, utils::Parameters ¶ms) { + std::cout << " - Punching through - " << std::endl; typename DirectionalEtching::RateSet rateSet; rateSet.direction = {0.}; rateSet.direction[D - 1] = -1.; @@ -44,6 +46,7 @@ void punchThrough(SmartPointer> domain, void deposit(SmartPointer> domain, NumericType depositionThickness) { + std::cout << " - Deposition - " << std::endl; domain->duplicateTopLevelSet(Material::Polymer); auto model = SmartPointer>::New( depositionThickness, domain->getGridDelta()); @@ -77,12 +80,11 @@ int main(int argc, char **argv) { } // geometry setup - auto geometry = SmartPointer>::New(); - MakeTrench( - geometry, params.get("gridDelta"), params.get("xExtent"), - params.get("yExtent"), params.get("trenchWidth"), - params.get("maskHeight"), 0. /* taper angle */, 0. /* base height */, - false /* periodic boundary */, true /* create mask */, Material::Si) + auto geometry = SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + MakeTrench(geometry, params.get("trenchWidth"), + 0.0 /* trenchDepth */, 0.0 /* trenchTaperAngle */, + params.get("maskHeight")) .apply(); const NumericType depositionThickness = params.get("depositionThickness"); @@ -95,6 +97,7 @@ int main(int argc, char **argv) { geometry->saveSurfaceMesh(name + std::to_string(n++) + ".vtp"); for (int i = 0; i < numCycles; ++i) { + std::cout << "Cycle " << i + 1 << std::endl; deposit(geometry, depositionThickness); geometry->saveSurfaceMesh(name + std::to_string(n++) + ".vtp"); punchThrough(geometry, params); diff --git a/examples/boschProcess/boschProcessEmulate.py b/examples/boschProcess/boschProcessEmulate.py index b8c3ed94..023dfb69 100644 --- a/examples/boschProcess/boschProcessEmulate.py +++ b/examples/boschProcess/boschProcessEmulate.py @@ -17,24 +17,20 @@ print("Running 3D simulation.") import viennaps3d as vps - -params = vps.ReadConfigFile(args.filename) vps.Logger.setLogLevel(vps.LogLevel.ERROR) +params = vps.ReadConfigFile(args.filename) vps.setNumThreads(16) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], - trenchDepth=params["maskHeight"], - taperingAngle=0.0, - baseHeight=0.0, - periodicBoundary=False, - makeMask=True, - material=vps.Material.Si, + trenchDepth=0.0, + maskHeight=params["maskHeight"], ).apply() diff --git a/examples/boschProcess/boschProcessRayTracing.py b/examples/boschProcess/boschProcessRayTracing.py index d2007c3a..dad5d713 100644 --- a/examples/boschProcess/boschProcessRayTracing.py +++ b/examples/boschProcess/boschProcessRayTracing.py @@ -40,19 +40,18 @@ hole_shape_str = params.get("holeShape", "Full").strip() # geometry setup, all units in um -geometry = vps.Domain() -vps.MakeHole( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeHole( + domain=geometry, holeRadius=params["holeRadius"], - holeDepth=params["maskHeight"], - taperingAngle=params["taperAngle"], + holeDepth=0.0, + maskHeight=params["maskHeight"], + maskTaperAngle=params["taperAngle"], holeShape=shape_map[hole_shape_str], - periodicBoundary=False, - makeMask=True, - material=vps.Material.Si, ).apply() depoModel = vps.MultiParticleProcess() diff --git a/examples/boschProcess/boschProcessSimulate.cpp b/examples/boschProcess/boschProcessSimulate.cpp index 91979b59..23c4421c 100644 --- a/examples/boschProcess/boschProcessSimulate.cpp +++ b/examples/boschProcess/boschProcessSimulate.cpp @@ -81,12 +81,11 @@ int main(int argc, char **argv) { } // geometry setup - auto geometry = SmartPointer>::New(); - MakeTrench( - geometry, params.get("gridDelta"), params.get("xExtent"), - params.get("yExtent"), params.get("trenchWidth"), - params.get("maskHeight"), 0. /* taper angle */, 0. /* base height */, - false /* periodic boundary */, true /* create mask */, Material::Si) + auto geometry = SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + MakeTrench(geometry, params.get("trenchWidth"), + 0.0 /* trenchDepth */, 0.0 /* trenchTaperAngle */, + params.get("maskHeight")) .apply(); const NumericType depositionThickness = params.get("depositionThickness"); diff --git a/examples/boschProcess/boschProcessSimulate.py b/examples/boschProcess/boschProcessSimulate.py index ff6531bd..5b4e6f68 100644 --- a/examples/boschProcess/boschProcessSimulate.py +++ b/examples/boschProcess/boschProcessSimulate.py @@ -17,26 +17,23 @@ print("Running 3D simulation.") import viennaps3d as vps -params = vps.ReadConfigFile(args.filename) vps.Logger.setLogLevel(vps.LogLevel.ERROR) +params = vps.ReadConfigFile(args.filename) vps.setNumThreads(16) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], - trenchDepth=params["maskHeight"], - taperingAngle=0.0, - baseHeight=0.0, - periodicBoundary=False, - makeMask=True, - material=vps.Material.Si, + trenchDepth=0.0, + maskHeight=params["maskHeight"], ).apply() -# Isoptropic deposition model +# Isotropic deposition model depoModel = vps.SingleParticleProcess( rate=params["depositionThickness"], stickingProbability=params["depositionStickingProbability"], diff --git a/examples/faradayCageEtching/faradayCageEtching.cpp b/examples/faradayCageEtching/faradayCageEtching.cpp index 691e892a..b9dbef0a 100644 --- a/examples/faradayCageEtching/faradayCageEtching.cpp +++ b/examples/faradayCageEtching/faradayCageEtching.cpp @@ -23,11 +23,12 @@ int main(int argc, char *argv[]) { } // geometry setup - auto geometry = ps::SmartPointer>::New(); - ps::MakeFin( - geometry, params.get("gridDelta"), params.get("xExtent"), - params.get("yExtent"), params.get("finWidth"), params.get("maskHeight"), - 0.0, 0.0, true /*enables periodic BCs*/, true, ps::Material::Si) + auto geometry = ps::SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent"), + ps::BoundaryType::PERIODIC_BOUNDARY); + ps::MakeFin(geometry, params.get("finWidth"), + 0.0 /*finHeight*/, 0.0 /*finTaperAngle*/, + params.get("maskHeight")) .apply(); std::vector maskMaterials = {ps::Material::Mask}; @@ -47,7 +48,7 @@ int main(int argc, char *argv[]) { ps::IntegrationScheme::LOCAL_LAX_FRIEDRICHS_1ST_ORDER); // print initial surface - geometry->saveSurfaceMesh("initial.vtp"); + geometry->saveHullMesh("initial.vtp"); // run the process process.apply(); diff --git a/examples/faradayCageEtching/faradayCageEtching.py b/examples/faradayCageEtching/faradayCageEtching.py index 87b812c8..463dcd3b 100644 --- a/examples/faradayCageEtching/faradayCageEtching.py +++ b/examples/faradayCageEtching/faradayCageEtching.py @@ -22,17 +22,17 @@ vps.Logger.setLogLevel(vps.LogLevel.INTERMEDIATE) # geometry setup, all units in um -geometry = vps.Domain() -vps.MakeFin( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], + boundary=vps.BoundaryType.PERIODIC_BOUNDARY, +) +vps.MakeFin( + domain=geometry, finWidth=params["finWidth"], - finHeight=params["maskHeight"], - periodicBoundary=True, - makeMask=True, - material=vps.Material.Si, + finHeight=0.0, + maskHeight=params["maskHeight"], ).apply() # use pre-defined etching model @@ -51,10 +51,10 @@ process.setProcessDuration(params["etchTime"]) # seconds # print initial surface -geometry.saveSurfaceMesh(filename="initial.vtp", addMaterialIds=True) +geometry.saveHullMesh(filename="initial") # run the process process.apply() # print final surface -geometry.saveSurfaceMesh(filename="final.vtp", addMaterialIds=True) +geometry.saveHullMesh(filename="final") diff --git a/examples/holeEtching/holeEtching.cpp b/examples/holeEtching/holeEtching.cpp index 5a9cc34e..f8a4cfad 100644 --- a/examples/holeEtching/holeEtching.cpp +++ b/examples/holeEtching/holeEtching.cpp @@ -27,12 +27,12 @@ int main(int argc, char *argv[]) { units::Time::setUnit(params.get("timeUnit")); // geometry setup - auto geometry = SmartPointer>::New(); - MakeHole( - geometry, params.get("gridDelta"), params.get("xExtent"), - params.get("yExtent"), params.get("holeRadius"), params.get("maskHeight"), - params.get("taperAngle"), 0 /* base height */, - false /* periodic boundary */, true /*create mask*/, Material::Si) + auto geometry = SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + MakeHole(geometry, params.get("holeRadius"), + 0.0 /* holeDepth */, 0.0 /* holeTaperAngle */, + params.get("maskHeight"), params.get("taperAngle"), + HoleShape::Half) .apply(); // use pre-defined model SF6O2 etching model diff --git a/examples/holeEtching/holeEtching.py b/examples/holeEtching/holeEtching.py index 61c1412b..0a3fb4af 100644 --- a/examples/holeEtching/holeEtching.py +++ b/examples/holeEtching/holeEtching.py @@ -23,17 +23,17 @@ vps.Time.setUnit(params["timeUnit"]) # geometry setup, all units in um -geometry = vps.Domain() -vps.MakeHole( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeHole( + domain=geometry, holeRadius=params["holeRadius"], - holeDepth=params["maskHeight"], - taperingAngle=params["taperAngle"], - makeMask=True, - material=vps.Material.Si, + holeDepth=0.0, + maskHeight=params["maskHeight"], + maskTaperAngle=params["taperAngle"], holeShape=vps.HoleShape.Half, ).apply() @@ -44,16 +44,17 @@ modelParams.oxygenFlux = params["oxygenFlux"] modelParams.Ions.meanEnergy = params["meanEnergy"] modelParams.Ions.sigmaEnergy = params["sigmaEnergy"] +modelParams.Ions.exponent = params["ionExponent"] modelParams.Passivation.A_ie = params["A_O"] +modelParams.Si.A_ie = params["A_Si"] modelParams.etchStopDepth = params["etchStopDepth"] - model = vps.SF6O2Etching(modelParams) # process setup process = vps.Process() process.setDomain(geometry) process.setProcessModel(model) -process.setMaxCoverageInitIterations(10) +process.setMaxCoverageInitIterations(20) process.setNumberOfRaysPerPoint(int(params["raysPerPoint"])) process.setProcessDuration(params["processTime"]) # seconds process.setIntegrationScheme( diff --git a/examples/holeEtching/testFluxes.py b/examples/holeEtching/testFluxes.py index ec9e4caa..9b37b1f0 100644 --- a/examples/holeEtching/testFluxes.py +++ b/examples/holeEtching/testFluxes.py @@ -60,19 +60,19 @@ for i in range(len(yo2)): - geometry = vps.Domain() + # geometry setup, all units in um + geometry = vps.Domain( + gridDelta=params["gridDelta"], + xExtent=params["xExtent"], + yExtent=params["yExtent"], + ) vps.MakeHole( - geometry, - gridDelta, - xExtent, - yExtent, - holeRadius, - maskHeight, - taperAngle, - 0.0, - False, - True, - vps.Material.Si, + domain=geometry, + holeRadius=params["holeRadius"], + holeDepth=0.0, + maskHeight=params["maskHeight"], + maskTaperAngle=params["taperAngle"], + holeShape=vps.HoleShape.Half, ).apply() process = vps.Process() diff --git a/examples/ionBeamEtching/ionBeamEtching.cpp b/examples/ionBeamEtching/ionBeamEtching.cpp index 8f61a684..493033b7 100644 --- a/examples/ionBeamEtching/ionBeamEtching.cpp +++ b/examples/ionBeamEtching/ionBeamEtching.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -21,23 +20,13 @@ int main(int argc, char *argv[]) { return 1; } - auto geometry = SmartPointer>::New(); - MakeTrench( - geometry, params.get("gridDelta"), params.get("xExtent"), - params.get("yExtent"), params.get("trenchWidth"), - params.get("maskHeight"), 0.0 /* tapering angle */, 0.0 /* base height */, - true /*periodic*/, true /*make mask*/, Material::Si) + auto geometry = SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + MakeTrench(geometry, params.get("trenchWidth"), + params.get("trenchDepth"), + 0.0 /*trenchTaperAngle*/, params.get("maskHeight")) .apply(); - { - // etch trench - Vec3D direction{0., 0., 0.}; - direction[D - 1] = -1.; - auto model = - SmartPointer>::New(direction, -1.0); - Process(geometry, model, params.get("trenchDepth")).apply(); - } - // copy top layer to capture deposition geometry->duplicateTopLevelSet(Material::Polymer); diff --git a/examples/ionBeamEtching/ionBeamEtching.py b/examples/ionBeamEtching/ionBeamEtching.py index a99c3e91..cd33149e 100644 --- a/examples/ionBeamEtching/ionBeamEtching.py +++ b/examples/ionBeamEtching/ionBeamEtching.py @@ -22,29 +22,18 @@ params = vps.ReadConfigFile(args.filename) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], - trenchDepth=params["maskHeight"], - taperingAngle=0.0, - baseHeight=0.0, - periodicBoundary=True, - makeMask=True, - material=vps.Material.Si, + trenchDepth=params["trenchDepth"], + maskHeight=params["maskHeight"], ).apply() -direction = [0.0, 0.0, 0.0] -direction[args.dim - 1] = -1.0 -model = vps.DirectionalEtching( - direction=direction, - directionalVelocity=-1.0, -) -vps.Process(geometry, model, params["trenchDepth"]).apply() - # copy top layer to capture deposition geometry.duplicateTopLevelSet(vps.Material.Polymer) diff --git a/examples/stackEtching/stackEtching.cpp b/examples/stackEtching/stackEtching.cpp index 1b558c97..97759e19 100644 --- a/examples/stackEtching/stackEtching.cpp +++ b/examples/stackEtching/stackEtching.cpp @@ -27,12 +27,12 @@ int main(int argc, char *argv[]) { units::Time::setUnit(params.get("timeUnit")); // geometry setup - auto geometry = SmartPointer>::New(); + auto geometry = SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); MakeStack( - geometry, params.get("gridDelta"), params.get("xExtent"), - params.get("yExtent"), params.get("numLayers"), - params.get("layerHeight"), params.get("substrateHeight"), 0.0, - params.get("trenchWidth"), params.get("maskHeight"), false) + geometry, params.get("numLayers"), params.get("layerHeight"), + params.get("substrateHeight"), 0.0 /*holeRadius*/, + params.get("trenchWidth"), params.get("maskHeight"), false /*halfStack*/) .apply(); // copy top layer for deposition diff --git a/examples/stackEtching/stackEtching.py b/examples/stackEtching/stackEtching.py index 04c29403..6d8f45b6 100644 --- a/examples/stackEtching/stackEtching.py +++ b/examples/stackEtching/stackEtching.py @@ -19,19 +19,19 @@ vps.Time.setUnit(params["timeUnit"]) # Geometry setup -geometry = vps.Domain() -vps.MakeStack( - geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeStack( + domain=geometry, numLayers=int(params["numLayers"]), layerHeight=params["layerHeight"], substrateHeight=params["substrateHeight"], holeRadius=0.0, trenchWidth=params["trenchWidth"], maskHeight=params["maskHeight"], - periodicBoundary=False, ).apply() geometry.duplicateTopLevelSet(vps.Material.Polymer) diff --git a/examples/trenchDeposition/trenchDeposition.cpp b/examples/trenchDeposition/trenchDeposition.cpp index bf2c67ba..379ffdea 100644 --- a/examples/trenchDeposition/trenchDeposition.cpp +++ b/examples/trenchDeposition/trenchDeposition.cpp @@ -8,7 +8,7 @@ namespace ps = viennaps; int main(int argc, char *argv[]) { using NumericType = double; - constexpr int D = 2; + constexpr int D = 3; // Parse the parameters ps::utils::Parameters params; @@ -19,17 +19,15 @@ int main(int argc, char *argv[]) { return 1; } - auto geometry = ps::SmartPointer>::New(); - ps::MakeTrench( - geometry, params.get("gridDelta") /* grid delta */, - params.get("xExtent") /*x extent*/, params.get("yExtent") /*y extent*/, - params.get("trenchWidth") /*trench width*/, - params.get("trenchHeight") /*trench height*/, - params.get("taperAngle") /* tapering angle */) + auto geometry = ps::SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + ps::MakeTrench(geometry, params.get("trenchWidth"), + params.get("trenchHeight"), + params.get("taperAngle")) .apply(); // copy top layer to capture deposition - geometry->duplicateTopLevelSet(); + geometry->duplicateTopLevelSet(ps::Material::SiO2); auto model = ps::SmartPointer>::New( params.get("rate") /*deposition rate*/, diff --git a/examples/trenchDeposition/trenchDeposition.py b/examples/trenchDeposition/trenchDeposition.py index 5483dc61..31a790f8 100644 --- a/examples/trenchDeposition/trenchDeposition.py +++ b/examples/trenchDeposition/trenchDeposition.py @@ -19,19 +19,16 @@ params = vps.ReadConfigFile(args.filename) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], trenchDepth=params["trenchHeight"], - taperingAngle=params["taperAngle"], - baseHeight=0.0, - periodicBoundary=False, - makeMask=False, - material=vps.Material.Si, + trenchTaperAngle=params["taperAngle"], ).apply() geometry.duplicateTopLevelSet(vps.Material.SiO2) diff --git a/examples/trenchDepositionGeometric/trenchDepositionGeometric.cpp b/examples/trenchDepositionGeometric/trenchDepositionGeometric.cpp index 2d025000..fdb578c2 100644 --- a/examples/trenchDepositionGeometric/trenchDepositionGeometric.cpp +++ b/examples/trenchDepositionGeometric/trenchDepositionGeometric.cpp @@ -19,15 +19,15 @@ int main(int argc, char *argv[]) { return 1; } - auto geometry = ps::SmartPointer>::New(); - ps::MakeTrench(geometry, params.get("gridDelta"), - params.get("xExtent"), params.get("yExtent"), - params.get("trenchWidth"), - params.get("trenchHeight")) + auto geometry = ps::SmartPointer>::New( + params.get("gridDelta"), params.get("xExtent"), params.get("yExtent")); + ps::MakeTrench(geometry, params.get("trenchWidth"), + params.get("trenchHeight"), + params.get("taperAngle")) .apply(); // copy top layer to capture deposition - geometry->duplicateTopLevelSet(); + geometry->duplicateTopLevelSet(ps::Material::SiO2); auto model = ps::SmartPointer>::New( params.get("layerThickness"), params.get("gridDelta")); diff --git a/examples/trenchDepositionGeometric/trenchDepositionGeometric.py b/examples/trenchDepositionGeometric/trenchDepositionGeometric.py index 680ac76a..88e23c93 100644 --- a/examples/trenchDepositionGeometric/trenchDepositionGeometric.py +++ b/examples/trenchDepositionGeometric/trenchDepositionGeometric.py @@ -19,21 +19,19 @@ params = vps.ReadConfigFile(args.filename) -geometry = vps.Domain() -vps.MakeTrench( - domain=geometry, +geometry = vps.Domain( gridDelta=params["gridDelta"], xExtent=params["xExtent"], yExtent=params["yExtent"], +) +vps.MakeTrench( + domain=geometry, trenchWidth=params["trenchWidth"], trenchDepth=params["trenchHeight"], - taperingAngle=params["taperAngle"], - baseHeight=0.0, - periodicBoundary=False, - makeMask=False, - material=vps.Material.Si, + trenchTaperAngle=params["taperAngle"], ).apply() + # copy top layer to capture deposition geometry.duplicateTopLevelSet(vps.Material.SiO2) diff --git a/include/viennaps/geometries/psGeometryFactory.hpp b/include/viennaps/geometries/psGeometryFactory.hpp new file mode 100644 index 00000000..443873fa --- /dev/null +++ b/include/viennaps/geometries/psGeometryFactory.hpp @@ -0,0 +1,212 @@ +#pragma once + +#include "../psDomain.hpp" + +#include +#include +#include +#include + +#include + +namespace viennaps { + +using namespace viennacore; + +template class GeometryFactory { +protected: + using lsDomainType = SmartPointer>; + + const DomainSetup &setup_; + const std::string name_; + +public: + GeometryFactory(const DomainSetup &domainSetup, + const std::string &name = "GeometryFactory") + : setup_(domainSetup), name_(name) {} + + lsDomainType makeSubstrate(NumericType base) { + + auto substrate = lsDomainType::New(setup_.grid()); + + NumericType normal[D] = {0.}; + NumericType origin[D] = {0.}; + + normal[D - 1] = 1.; + origin[D - 1] = base; + viennals::MakeGeometry( + substrate, + SmartPointer>::New(origin, normal)) + .apply(); + + if (Logger::getInstance().getLogLevel() >= 5) { + saveSurfaceMesh(substrate, "_Substrate"); + } + + return substrate; + } + + lsDomainType makeMask(NumericType base, NumericType height) { + assert(setup_.isValid()); + + auto mask = lsDomainType::New(setup_.grid()); + + NumericType normal[D] = {0.}; + NumericType origin[D] = {0.}; + + normal[D - 1] = 1.; + origin[D - 1] = base + height; + viennals::MakeGeometry( + mask, + SmartPointer>::New(origin, normal)) + .apply(); + + auto maskAdd = lsDomainType::New(setup_.grid()); + origin[D - 1] = base; + normal[D - 1] = -1.; + viennals::MakeGeometry( + maskAdd, + SmartPointer>::New(origin, normal)) + .apply(); + + viennals::BooleanOperation( + mask, maskAdd, viennals::BooleanOperationEnum::INTERSECT) + .apply(); + + if (Logger::getInstance().getLogLevel() >= 5) { + saveSurfaceMesh(mask, "_Mask"); + } + + return mask; + } + + lsDomainType makeCylinderStencil(std::array position, + NumericType radius, NumericType height, + NumericType angle) { + assert(setup_.isValid()); + + auto cutout = lsDomainType::New(setup_.grid()); + + NumericType normal[D] = {0.}; + normal[D - 1] = 1.; + + NumericType topRadius = radius + std::tan(angle * M_PI / 180.) * height; + viennals::MakeGeometry( + cutout, SmartPointer>::New( + position.data(), normal, height, radius, topRadius)) + .apply(); + + if (Logger::getInstance().getLogLevel() >= 5) { + static int count = 0; + saveSurfaceMesh(cutout, "_Cylinder" + std::to_string(count++)); + } + + return cutout; + } + + lsDomainType makeBoxStencil(std::array position, + NumericType width, NumericType height, + NumericType angle) { + if (angle >= 90 || angle <= -90) { + Logger::getInstance() + .addError(name_ + + ": Taper angle must be between -90 and 90 " + "degrees: " + + std::to_string(angle)) + .print(); + } + + auto cutout = lsDomainType::New(setup_.grid()); + auto gridDelta = setup_.gridDelta(); + auto yExt = setup_.yExtent() / 2 + gridDelta; + + auto mesh = SmartPointer>::New(); + const NumericType offSet = height * std::tan(angle * M_PI / 180.); + + if constexpr (D == 2) { + auto const x = position[0]; + auto const y = position[1]; + mesh->insertNextNode({x - width / 2, y, 0.}); + mesh->insertNextNode({x + width / 2, y, 0.}); + mesh->insertNextLine({1, 0}); + + if (offSet >= width / 2) { // single top node + NumericType top = y + width * height / (2 * offSet); + mesh->insertNextNode({x, top, 0.}); + mesh->insertNextLine({2, 1}); + mesh->insertNextLine({0, 2}); + } else { + mesh->insertNextNode({x + width / 2 - offSet, y + height, 0.}); + mesh->insertNextNode({x - width / 2 + offSet, y + height, 0.}); + mesh->insertNextLine({2, 1}); + mesh->insertNextLine({3, 2}); + mesh->insertNextLine({0, 3}); + } + } else { // 3D + auto const x = position[0]; + auto const base = position[2]; + mesh->insertNextNode({x - width / 2, yExt, base}); + mesh->insertNextNode({x + width / 2, yExt, base}); + + if (offSet >= width / 2) { // single top node + NumericType top = base + width * height / (2 * offSet); + mesh->insertNextNode({x, yExt, top}); + + // shifted nodes by y extent + mesh->insertNextNode({x - width / 2, -yExt, base}); + mesh->insertNextNode({x + width / 2, -yExt, base}); + mesh->insertNextNode({x, -yExt, top}); + + // triangles + mesh->insertNextTriangle({0, 2, 1}); // front + mesh->insertNextTriangle({3, 4, 5}); // back + mesh->insertNextTriangle({0, 1, 3}); // bottom + mesh->insertNextTriangle({1, 4, 3}); // bottom + mesh->insertNextTriangle({1, 2, 5}); // right + mesh->insertNextTriangle({1, 5, 4}); // right + mesh->insertNextTriangle({0, 3, 2}); // left + mesh->insertNextTriangle({3, 5, 2}); // left + } else { + mesh->insertNextNode({x + width / 2 - offSet, yExt, base + height}); + mesh->insertNextNode({x - width / 2 + offSet, yExt, base + height}); + + // shifted nodes by y extent + mesh->insertNextNode({x - width / 2, -yExt, base}); + mesh->insertNextNode({x + width / 2, -yExt, base}); + mesh->insertNextNode({x + width / 2 - offSet, -yExt, base + height}); + mesh->insertNextNode({x - width / 2 + offSet, -yExt, base + height}); + + // triangles + mesh->insertNextTriangle({0, 3, 1}); // front + mesh->insertNextTriangle({1, 3, 2}); // front + mesh->insertNextTriangle({4, 5, 6}); // back + mesh->insertNextTriangle({4, 6, 7}); // back + mesh->insertNextTriangle({0, 1, 4}); // bottom + mesh->insertNextTriangle({1, 5, 4}); // bottom + mesh->insertNextTriangle({1, 2, 5}); // right + mesh->insertNextTriangle({2, 6, 5}); // right + mesh->insertNextTriangle({0, 4, 3}); // left + mesh->insertNextTriangle({3, 4, 7}); // left + mesh->insertNextTriangle({3, 7, 2}); // top + mesh->insertNextTriangle({2, 7, 6}); // top + } + } + viennals::FromSurfaceMesh(cutout, mesh).apply(); + + if (Logger::getInstance().getLogLevel() >= 5) { + static int count = 0; + saveSurfaceMesh(cutout, "_Trench" + std::to_string(count++)); + } + + return cutout; + } + +private: + void saveSurfaceMesh(lsDomainType levelSet, const std::string &name) { + auto mesh = SmartPointer>::New(); + viennals::ToSurfaceMesh(levelSet, mesh).apply(); + viennals::VTKWriter(mesh, name_ + name).apply(); + } +}; + +} // namespace viennaps diff --git a/include/viennaps/geometries/psMakeFin.hpp b/include/viennaps/geometries/psMakeFin.hpp index 8a5a497e..3a893cfe 100644 --- a/include/viennaps/geometries/psMakeFin.hpp +++ b/include/viennaps/geometries/psMakeFin.hpp @@ -1,6 +1,7 @@ #pragma once #include "../psDomain.hpp" +#include "psGeometryFactory.hpp" #include #include @@ -19,243 +20,82 @@ using namespace viennacore; /// with the specified material exclusively applied to the bottom of the fin, /// while the upper portion adopts the mask material. template class MakeFin { - using lsDomainType = SmartPointer>; using psDomainType = SmartPointer>; - using BoundaryEnum = typename viennals::Domain::BoundaryType; - psDomainType pDomain_ = nullptr; - - const NumericType gridDelta_; - const NumericType xExtent_; - const NumericType yExtent_; + psDomainType domain_; + GeometryFactory geometryFactory_; + static constexpr NumericType eps_ = 1e-4; const NumericType finWidth_; const NumericType finHeight_; - const NumericType taperAngle_; // taper angle in degrees - const NumericType baseHeight_; + const NumericType finTaperAngle_; // taper angle in degrees + + const NumericType maskHeight_; + const NumericType maskTaperAngle_; - const bool periodicBoundary_; - const bool makeMask_; + const NumericType base_; const Material material_; + const Material maskMaterial_ = Material::Mask; public: + MakeFin(psDomainType domain, NumericType finWidth, NumericType finHeight, + NumericType finTaperAngle = 0., NumericType maskHeight = 0., + NumericType maskTaperAngle = 0., bool halfFin = false, + Material material = Material::Si, + Material maskMaterial = Material::Mask) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + finWidth_(finWidth), finHeight_(finHeight), + finTaperAngle_(finTaperAngle), maskHeight_(maskHeight), + maskTaperAngle_(maskTaperAngle), base_(0.0), material_(material), + maskMaterial_(maskMaterial) { + if (halfFin) + domain_->getSetup().halveXAxis(); + } + MakeFin(psDomainType domain, NumericType gridDelta, NumericType xExtent, NumericType yExtent, NumericType finWidth, NumericType finHeight, NumericType taperAngle = 0., NumericType baseHeight = 0., bool periodicBoundary = false, bool makeMask = false, - Material material = Material::None) - : pDomain_(domain), gridDelta_(gridDelta), xExtent_(xExtent), - yExtent_(yExtent), finWidth_(finWidth), finHeight_(finHeight), - taperAngle_(taperAngle), baseHeight_(baseHeight), - periodicBoundary_(periodicBoundary), makeMask_(makeMask), - material_(material) {} + Material material = Material::Si) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + finWidth_(finWidth), finHeight_(makeMask ? 0 : finHeight), + finTaperAngle_(makeMask ? 0 : taperAngle), + maskHeight_(makeMask ? finHeight : 0), + maskTaperAngle_(makeMask ? taperAngle : 0), base_(baseHeight), + material_(material) { + domain_->setup(gridDelta, xExtent, yExtent, + periodicBoundary ? BoundaryType::PERIODIC_BOUNDARY + : BoundaryType::REFLECTIVE_BOUNDARY); + } void apply() { - pDomain_->clear(); - - if constexpr (D == 3) { - double bounds[2 * D] = {-xExtent_ / 2, xExtent_ / 2, -yExtent_ / 2, - yExtent_ / 2, -1., 1.}; - - BoundaryEnum boundaryConds[D] = {BoundaryEnum::REFLECTIVE_BOUNDARY, - BoundaryEnum::REFLECTIVE_BOUNDARY, - BoundaryEnum::INFINITE_BOUNDARY}; - if (periodicBoundary_) { - boundaryConds[0] = BoundaryEnum::PERIODIC_BOUNDARY; - boundaryConds[1] = BoundaryEnum::PERIODIC_BOUNDARY; - } - - auto substrate = lsDomainType::New(bounds, boundaryConds, gridDelta_); - NumericType normal[D] = {0., 0., 1.}; - NumericType origin[D] = {0., 0., baseHeight_}; - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin, normal)) - .apply(); - - auto mask = lsDomainType::New(bounds, boundaryConds, gridDelta_); - - if (taperAngle_ == 0.) { - NumericType minPoint[D] = {-finWidth_ / 2.f, - -yExtent_ / 2.f - gridDelta_, - baseHeight_ - gridDelta_}; - NumericType maxPoint[D] = {finWidth_ / 2.f, yExtent_ / 2.f + gridDelta_, - baseHeight_ + finHeight_}; - - viennals::MakeGeometry geo( - mask, SmartPointer>::New(minPoint, - maxPoint)); - geo.setIgnoreBoundaryConditions(true); - geo.apply(); - - } else { - if (taperAngle_ >= 90 || taperAngle_ <= -90) { - Logger::getInstance() - .addError("MakeFin: Taper angle must be between -90 and 90 " - "degrees!") - .print(); - return; - } - - auto boxMesh = SmartPointer>::New(); - boxMesh->insertNextNode({-finWidth_ / 2, yExtent_ / 2 + gridDelta_, - baseHeight_ - gridDelta_}); - boxMesh->insertNextNode({finWidth_ / 2, yExtent_ / 2 + gridDelta_, - baseHeight_ - gridDelta_}); - - NumericType taperAngleRad = taperAngle_ * M_PI / 180.; - NumericType offSet = finHeight_ * std::tan(taperAngleRad); - if (offSet >= finWidth_ / 2) { - boxMesh->insertNextNode( - {0., yExtent_ / 2 + gridDelta_, - baseHeight_ + finWidth_ / 2 / std::tan(taperAngleRad)}); - - // shifted nodes by y extent - boxMesh->insertNextNode({-finWidth_ / 2, -yExtent_ / 2 - gridDelta_, - baseHeight_ - gridDelta_}); - boxMesh->insertNextNode({finWidth_ / 2, -yExtent_ / 2 - gridDelta_, - baseHeight_ - gridDelta_}); - boxMesh->insertNextNode( - {0., -yExtent_ / 2 - gridDelta_, - baseHeight_ + finWidth_ / 2 / std::tan(taperAngleRad)}); - - // triangles - boxMesh->insertNextTriangle({0, 2, 1}); // front - boxMesh->insertNextTriangle({3, 4, 5}); // back - boxMesh->insertNextTriangle({0, 1, 3}); // bottom - boxMesh->insertNextTriangle({1, 4, 3}); // bottom - boxMesh->insertNextTriangle({1, 2, 5}); // right - boxMesh->insertNextTriangle({1, 5, 4}); // right - boxMesh->insertNextTriangle({0, 3, 2}); // left - boxMesh->insertNextTriangle({3, 5, 2}); // left - } else { - boxMesh->insertNextNode({finWidth_ / 2 - offSet, - yExtent_ / 2 + gridDelta_, - baseHeight_ + finHeight_}); - boxMesh->insertNextNode({-finWidth_ / 2 + offSet, - yExtent_ / 2 + gridDelta_, - baseHeight_ + finHeight_}); - - // shifted nodes by y extent - boxMesh->insertNextNode({-finWidth_ / 2, -yExtent_ / 2 - gridDelta_, - baseHeight_ - gridDelta_}); - boxMesh->insertNextNode({finWidth_ / 2, -yExtent_ / 2 - gridDelta_, - baseHeight_ - gridDelta_}); - boxMesh->insertNextNode({finWidth_ / 2 - offSet, - -yExtent_ / 2 - gridDelta_, - baseHeight_ + finHeight_}); - boxMesh->insertNextNode({-finWidth_ / 2 + offSet, - -yExtent_ / 2 - gridDelta_, - baseHeight_ + finHeight_}); + domain_->clear(); // this does not clear the setup + domain_->getSetup().check(); + + if (maskHeight_ > 0.) { + auto position = std::array{0.}; + position[D - 1] = base_ + finHeight_ - eps_; + auto mask = geometryFactory_.makeBoxStencil(position, finWidth_, + maskHeight_, maskTaperAngle_); + domain_->insertNextLevelSetAsMaterial(mask, maskMaterial_); + } - // triangles - boxMesh->insertNextTriangle({0, 3, 1}); // front - boxMesh->insertNextTriangle({1, 3, 2}); // front - boxMesh->insertNextTriangle({4, 5, 6}); // back - boxMesh->insertNextTriangle({4, 6, 7}); // back - boxMesh->insertNextTriangle({0, 1, 4}); // bottom - boxMesh->insertNextTriangle({1, 5, 4}); // bottom - boxMesh->insertNextTriangle({1, 2, 5}); // right - boxMesh->insertNextTriangle({2, 6, 5}); // right - boxMesh->insertNextTriangle({0, 4, 3}); // left - boxMesh->insertNextTriangle({3, 4, 7}); // left - boxMesh->insertNextTriangle({3, 7, 2}); // top - boxMesh->insertNextTriangle({2, 7, 6}); // top - } - viennals::FromSurfaceMesh(mask, boxMesh).apply(); - } + auto substrate = geometryFactory_.makeSubstrate(base_); + if (finHeight_ > 0.) { + auto position = std::array{0.}; + position[D - 1] = base_ + finHeight_; + auto fin = geometryFactory_.makeBoxStencil( + position, finWidth_, -finHeight_ - eps_, finTaperAngle_); viennals::BooleanOperation( - substrate, mask, viennals::BooleanOperationEnum::UNION) - .apply(); - - if (material_ == Material::None) { - if (makeMask_) - pDomain_->insertNextLevelSet(mask); - pDomain_->insertNextLevelSet(substrate, false); - } else { - if (makeMask_) - pDomain_->insertNextLevelSetAsMaterial(mask, Material::Mask); - pDomain_->insertNextLevelSetAsMaterial(substrate, material_, false); - } - } else if constexpr (D == 2) { - - double bounds[2 * D] = {-xExtent_ / 2, xExtent_ / 2, - baseHeight_ - gridDelta_, - baseHeight_ + finHeight_ + gridDelta_}; - - BoundaryEnum boundaryConds[D] = {BoundaryEnum::REFLECTIVE_BOUNDARY, - BoundaryEnum::INFINITE_BOUNDARY}; - if (periodicBoundary_) { - boundaryConds[0] = BoundaryEnum::PERIODIC_BOUNDARY; - } - - auto substrate = lsDomainType::New(bounds, boundaryConds, gridDelta_); - NumericType normal[D] = {0., 1.}; - NumericType origin[D] = {0., baseHeight_}; - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin, normal)) + fin, viennals::BooleanOperationEnum::INVERT) .apply(); - - auto mask = lsDomainType::New(bounds, boundaryConds, gridDelta_); - - if (taperAngle_ == 0.) { - NumericType minPoint[D] = {-finWidth_ / 2, baseHeight_ - gridDelta_}; - NumericType maxPoint[D] = {finWidth_ / 2, baseHeight_ + finHeight_}; - viennals::MakeGeometry geo( - mask, SmartPointer>::New(minPoint, - maxPoint)); - geo.setIgnoreBoundaryConditions(true); - geo.apply(); - } else { - if (taperAngle_ >= 90 || taperAngle_ <= -90) { - Logger::getInstance() - .addError("MakeFin: Taper angle must be between -90 and 90 " - "degrees!") - .print(); - return; - } - - auto boxMesh = SmartPointer>::New(); - boxMesh->insertNextNode({-finWidth_ / 2, baseHeight_ - gridDelta_}); - boxMesh->insertNextNode({finWidth_ / 2, baseHeight_ - gridDelta_}); - boxMesh->insertNextLine({1, 0}); - - NumericType taperAngleRad = taperAngle_ * M_PI / 180.; - NumericType offSet = finHeight_ * std::tan(taperAngleRad); - if (offSet >= finWidth_ / 2) { - boxMesh->insertNextNode( - {0., baseHeight_ + finWidth_ / 2 / std::tan(taperAngleRad)}); - boxMesh->insertNextLine({2, 1}); - boxMesh->insertNextLine({0, 2}); - } else { - boxMesh->insertNextNode( - {finWidth_ / 2 - offSet, baseHeight_ + finHeight_}); - boxMesh->insertNextNode( - {-finWidth_ / 2 + offSet, baseHeight_ + finHeight_}); - boxMesh->insertNextLine({2, 1}); - boxMesh->insertNextLine({3, 2}); - boxMesh->insertNextLine({0, 3}); - } - - viennals::FromSurfaceMesh(mask, boxMesh).apply(); - } - viennals::BooleanOperation( - substrate, mask, viennals::BooleanOperationEnum::UNION) + substrate, fin, viennals::BooleanOperationEnum::UNION) .apply(); - - if (material_ == Material::None) { - if (makeMask_) - pDomain_->insertNextLevelSet(mask); - pDomain_->insertNextLevelSet(substrate, false); - } else { - if (makeMask_) - pDomain_->insertNextLevelSetAsMaterial(mask, Material::Mask); - pDomain_->insertNextLevelSetAsMaterial(substrate, material_, false); - } } + + domain_->insertNextLevelSetAsMaterial(substrate, material_); } }; diff --git a/include/viennaps/geometries/psMakeHole.hpp b/include/viennaps/geometries/psMakeHole.hpp index b7fb6f89..3e0998fd 100644 --- a/include/viennaps/geometries/psMakeHole.hpp +++ b/include/viennaps/geometries/psMakeHole.hpp @@ -1,7 +1,8 @@ #pragma once -#include "../geometries/psMakeTrench.hpp" #include "../psDomain.hpp" +#include "psGeometryFactory.hpp" +#include "psMakeTrench.hpp" #include #include @@ -23,152 +24,111 @@ using namespace viennacore; /// applied to the bottom of the hole, while the remainder adopts the mask /// material. template class MakeHole { - using lsDomainType = SmartPointer>; using psDomainType = SmartPointer>; - using BoundaryEnum = typename viennals::Domain::BoundaryType; - psDomainType domain_ = nullptr; - - const NumericType gridDelta_; - const NumericType xExtent_; - const NumericType yExtent_; + psDomainType domain_; + GeometryFactory geometryFactory_; + static constexpr NumericType eps_ = 1e-4; const NumericType holeRadius_; const NumericType holeDepth_; - const NumericType taperAngle_; // taper angle in degrees - const NumericType baseHeight_; + const NumericType holeTaperAngle_; // angle in degrees + + const NumericType maskHeight_; + const NumericType maskTaperAngle_; - const bool makeMask_; - const bool periodicBoundary_; + const NumericType base_; const Material material_; + const Material maskMaterial_ = Material::Mask; - const HoleShape shape_; + HoleShape shape_; public: + MakeHole(psDomainType domain, NumericType holeRadius, NumericType holeDepth, + NumericType holeTaperAngle = 0., NumericType maskHeight = 0., + NumericType maskTaperAngle = 0., HoleShape shape = HoleShape::Full, + Material material = Material::Si, + Material maskMaterial = Material::Mask) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + holeRadius_(holeRadius), holeDepth_(holeDepth), + holeTaperAngle_(holeTaperAngle), maskHeight_(maskHeight), + maskTaperAngle_(maskTaperAngle), base_(0.0), material_(material), + shape_(shape), maskMaterial_(maskMaterial) {} + MakeHole(psDomainType domain, NumericType gridDelta, NumericType xExtent, NumericType yExtent, NumericType holeRadius, NumericType holeDepth, NumericType taperAngle = 0., NumericType baseHeight = 0., bool periodicBoundary = false, bool makeMask = false, - Material material = Material::None, - HoleShape shape = HoleShape::Full) - : domain_(domain), gridDelta_(gridDelta), xExtent_(xExtent), - yExtent_(yExtent), holeRadius_(holeRadius), holeDepth_(holeDepth), - shape_(shape), taperAngle_(taperAngle), baseHeight_(baseHeight), - periodicBoundary_(periodicBoundary && (shape != HoleShape::Half && - shape != HoleShape::Quarter)), - makeMask_(makeMask), material_(material) { - if (periodicBoundary && - (shape == HoleShape::Half || shape == HoleShape::Quarter)) { - Logger::getInstance() - .addWarning("MakeHole: 'Half' or 'Quarter' shapes do not support " - "periodic boundaries! " - "Defaulting to reflective boundaries!") - .print(); - } + Material material = Material::Si, HoleShape shape = HoleShape::Full) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + holeRadius_(holeRadius), holeDepth_(makeMask ? 0 : holeDepth), + holeTaperAngle_(makeMask ? 0 : taperAngle), + maskHeight_(makeMask ? holeDepth : 0), + maskTaperAngle_(makeMask ? taperAngle : 0), base_(baseHeight), + material_(material), shape_(shape) { + domain_->setup(gridDelta, xExtent, yExtent, + periodicBoundary ? BoundaryType::PERIODIC_BOUNDARY + : BoundaryType::REFLECTIVE_BOUNDARY); } void apply() { - if constexpr (D != 3) { Logger::getInstance() .addWarning("MakeHole: Hole geometry can only be created in 3D! " "Falling back to trench geometry.") .print(); - MakeTrench( - domain_, gridDelta_, xExtent_, yExtent_, 2 * holeRadius_, holeDepth_, - taperAngle_, baseHeight_, periodicBoundary_, makeMask_, material_) + bool halfTrench = + shape_ == HoleShape::Half || shape_ == HoleShape::Quarter; + MakeTrench(domain_, 2 * holeRadius_, holeDepth_, + holeTaperAngle_, maskHeight_, maskTaperAngle_, + halfTrench, material_) .apply(); - return; } - domain_->clear(); - double bounds[2 * D]; - bounds[0] = (shape_ != HoleShape::Full) ? 0. : -xExtent_ / 2.; - bounds[1] = xExtent_ / 2.; - - if constexpr (D == 3) { - bounds[2] = (shape_ == HoleShape::Quarter) ? 0. : -yExtent_ / 2.; - bounds[3] = yExtent_ / 2.; - bounds[4] = baseHeight_ - gridDelta_; - bounds[5] = baseHeight_ + holeDepth_ + gridDelta_; - } else { - bounds[2] = baseHeight_ - gridDelta_; - bounds[3] = baseHeight_ + holeDepth_ + gridDelta_; + domain_->clear(); // this does not clear the setup + domain_->getSetup().check(); + + auto &setup = domain_->getSetup(); + + if (setup.hasPeriodicBoundary() && + (shape_ == HoleShape::Half || shape_ == HoleShape::Quarter)) { + Logger::getInstance() + .addWarning("MakeHole: 'Half' or 'Quarter' shapes do not support " + "periodic boundaries! Creating full hole.") + .print(); + shape_ = HoleShape::Full; } - BoundaryEnum boundaryCons[D]; - for (int i = 0; i < D - 1; i++) { - if (periodicBoundary_) { - boundaryCons[i] = BoundaryEnum::PERIODIC_BOUNDARY; - } else { - boundaryCons[i] = BoundaryEnum::REFLECTIVE_BOUNDARY; - } + if (shape_ == HoleShape::Half) { + setup.halveXAxis(); + } else if (shape_ == HoleShape::Quarter) { + setup.halveXAxis(); + setup.halveYAxis(); } - boundaryCons[D - 1] = BoundaryEnum::INFINITE_BOUNDARY; - - // substrate - auto substrate = lsDomainType::New(bounds, boundaryCons, gridDelta_); - NumericType normal[D] = {0.}; - NumericType origin[D] = {0.}; - normal[D - 1] = 1.; - origin[D - 1] = baseHeight_; - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin, normal)) - .apply(); - - // mask layer - auto mask = lsDomainType::New(bounds, boundaryCons, gridDelta_); - origin[D - 1] = holeDepth_ + baseHeight_; - viennals::MakeGeometry( - mask, - SmartPointer>::New(origin, normal)) - .apply(); - - auto maskAdd = lsDomainType::New(bounds, boundaryCons, gridDelta_); - origin[D - 1] = baseHeight_; - normal[D - 1] = -1.; - viennals::MakeGeometry( - maskAdd, - SmartPointer>::New(origin, normal)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::INTERSECT) - .apply(); - - // cylinder cutout - normal[D - 1] = 1.; - origin[D - 1] = baseHeight_; - - NumericType topRadius = holeRadius_; - if (taperAngle_) { - topRadius += std::tan(taperAngle_ * M_PI / 180.) * holeDepth_; + + auto substrate = geometryFactory_.makeSubstrate(base_); + + if (maskHeight_ > 0.) { + auto mask = geometryFactory_.makeMask(base_ - eps_, maskHeight_); + domain_->insertNextLevelSetAsMaterial(mask, maskMaterial_); + std::array position = {0.}; + position[D - 1] = base_ - 2 * eps_; + auto cutout = geometryFactory_.makeCylinderStencil( + position, holeRadius_, maskHeight_ + 3 * eps_, maskTaperAngle_); + domain_->applyBooleanOperation( + cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); } - viennals::MakeGeometry( - maskAdd, SmartPointer>::New( - origin, normal, holeDepth_ + 2 * gridDelta_, holeRadius_, - topRadius)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT) - .apply(); - - viennals::BooleanOperation( - substrate, mask, viennals::BooleanOperationEnum::UNION) - .apply(); - - if (material_ == Material::None) { - if (makeMask_) - domain_->insertNextLevelSet(mask); - domain_->insertNextLevelSet(substrate, false); - } else { - if (makeMask_) - domain_->insertNextLevelSetAsMaterial(mask, Material::Mask); - domain_->insertNextLevelSetAsMaterial(substrate, material_, false); + domain_->insertNextLevelSetAsMaterial(substrate, material_); + + if (holeDepth_ > 0.) { + std::array position = {0.}; + position[D - 1] = base_; + auto cutout = geometryFactory_.makeCylinderStencil( + position, holeRadius_, -holeDepth_, holeTaperAngle_); + domain_->applyBooleanOperation(cutout, + viennals::BooleanOperationEnum::INTERSECT); } } }; diff --git a/include/viennaps/geometries/psMakePlane.hpp b/include/viennaps/geometries/psMakePlane.hpp index cfd7c78d..200ed598 100644 --- a/include/viennaps/geometries/psMakePlane.hpp +++ b/include/viennaps/geometries/psMakePlane.hpp @@ -1,6 +1,7 @@ #pragma once #include "../psDomain.hpp" +#include "psGeometryFactory.hpp" #include @@ -18,54 +19,36 @@ using namespace viennacore; /// specified extent and height. The plane can have a periodic boundary in the x /// and y (only 3D) direction. template class MakePlane { - using LSPtrType = SmartPointer>; using psDomainType = SmartPointer>; - using BoundaryEnum = typename viennals::Domain::BoundaryType; - psDomainType pDomain_ = nullptr; + psDomainType domain_; + GeometryFactory geometryFactory_; - const NumericType gridDelta_ = 0.; - const NumericType xExtent_ = 0.; - const NumericType yExtent_ = 0.; const NumericType baseHeight_; - double bounds_[2 * D] = {0.}; - bool useBounds_ = false; - - const bool periodicBoundary_ = false; const Material material_; - const bool add_; public: // Adds a plane to an already existing geometry. MakePlane(psDomainType domain, NumericType baseHeight = 0., - Material material = Material::None) - : pDomain_(domain), baseHeight_(baseHeight), material_(material), - add_(true) {} + Material material = Material::Si, bool addToExisting = false) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + baseHeight_(baseHeight), material_(material), add_(addToExisting) {} // Creates a new geometry with a plane. MakePlane(psDomainType domain, NumericType gridDelta, NumericType xExtent, NumericType yExtent, NumericType baseHeight, - bool periodicBoundary = false, Material material = Material::None) - : pDomain_(domain), gridDelta_(gridDelta), xExtent_(xExtent), - yExtent_(yExtent), baseHeight_(baseHeight), - periodicBoundary_(periodicBoundary), material_(material), add_(false) {} - - // Creates a new geometry with a plane and custom bounds. - MakePlane(psDomainType domain, NumericType gridDelta, double bounds[2 * D], - NumericType baseHeight, bool periodicBoundary = false, - Material material = Material::None) - : pDomain_(domain), gridDelta_(gridDelta), useBounds_(true), - baseHeight_(baseHeight), periodicBoundary_(periodicBoundary), - material_(material), add_(false) { - for (int i = 0; i < 2 * D; ++i) { - bounds_[i] = bounds[i]; - } + bool periodicBoundary = false, Material material = Material::Si) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + baseHeight_(baseHeight), material_(material), add_(false) { + domain_->setup(gridDelta, xExtent, yExtent, + periodicBoundary ? BoundaryType::PERIODIC_BOUNDARY + : BoundaryType::REFLECTIVE_BOUNDARY); } void apply() { if (add_) { - if (!pDomain_->getLevelSets().back()) { + if (!domain_->getLevelSets().back()) { Logger::getInstance() .addWarning("MakePlane: Plane can only be added to already " "existing geometry.") @@ -73,61 +56,12 @@ template class MakePlane { return; } } else { - pDomain_->clear(); - } - - if (!useBounds_) { - bounds_[0] = -xExtent_ / 2.; - bounds_[1] = xExtent_ / 2.; - if constexpr (D == 3) { - bounds_[2] = -yExtent_ / 2.; - bounds_[3] = yExtent_ / 2.; - bounds_[4] = -gridDelta_; - bounds_[5] = gridDelta_; - } else { - bounds_[2] = -gridDelta_; - bounds_[3] = gridDelta_; - } - } - - BoundaryEnum boundaryCons[D]; - for (int i = 0; i < D - 1; i++) { - if (periodicBoundary_) { - boundaryCons[i] = BoundaryEnum::PERIODIC_BOUNDARY; - } else { - boundaryCons[i] = BoundaryEnum::REFLECTIVE_BOUNDARY; - } + domain_->clear(); } - boundaryCons[D - 1] = BoundaryEnum::INFINITE_BOUNDARY; - NumericType normal[D] = {0.}; - NumericType origin[D] = {0.}; - normal[D - 1] = 1.; - origin[D - 1] = baseHeight_; - - if (add_) { - auto substrate = LSPtrType::New(pDomain_->getGrid()); - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin, normal)) - .apply(); - if (material_ == Material::None) { - pDomain_->insertNextLevelSet(substrate); - } else { - pDomain_->insertNextLevelSetAsMaterial(substrate, material_); - } - } else { - auto substrate = LSPtrType::New(bounds_, boundaryCons, gridDelta_); - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin, normal)) - .apply(); - if (material_ == Material::None) { - pDomain_->insertNextLevelSet(substrate); - } else { - pDomain_->insertNextLevelSetAsMaterial(substrate, material_); - } - } + domain_->getSetup().check(); + auto substrate = geometryFactory_.makeSubstrate(baseHeight_); + domain_->insertNextLevelSetAsMaterial(substrate, material_); } }; diff --git a/include/viennaps/geometries/psMakeStack.hpp b/include/viennaps/geometries/psMakeStack.hpp index b22f5138..160396b1 100644 --- a/include/viennaps/geometries/psMakeStack.hpp +++ b/include/viennaps/geometries/psMakeStack.hpp @@ -1,6 +1,7 @@ #pragma once #include "../psDomain.hpp" +#include "psGeometryFactory.hpp" #include #include @@ -19,291 +20,130 @@ using namespace viennacore; /// users to create diverse and customized structures for simulation scenarios. template class MakeStack { using psDomainType = SmartPointer>; - using lsDomainType = SmartPointer>; - using BoundaryEnum = typename viennals::Domain::BoundaryType; - psDomainType pDomain_ = nullptr; - - const NumericType gridDelta_; - const NumericType xExtent_; - const NumericType yExtent_; - double bounds_[2 * D]; - NumericType normal_[D]; - NumericType origin_[D] = {0.}; + psDomainType domain_; + GeometryFactory geometryFactory_; + static constexpr NumericType eps_ = 1e-4; const int numLayers_; const NumericType layerHeight_; const NumericType substrateHeight_; + NumericType holeRadius_; const NumericType trenchWidth_; const NumericType maskHeight_; - const bool periodicBoundary_ = false; - - BoundaryEnum boundaryConds_[D]; + const NumericType taperAngle_ = 0.; + const Material maskMaterial_ = Material::Mask; public: + MakeStack(psDomainType domain, int numLayers, NumericType layerHeight, + NumericType substrateHeight, NumericType holeRadius, + NumericType trenchWidth, NumericType maskHeight, + NumericType taperAngle, bool halfStack = false, + Material maskMaterial = Material::Mask) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + numLayers_(numLayers), layerHeight_(layerHeight), + substrateHeight_(substrateHeight), holeRadius_(holeRadius), + trenchWidth_(trenchWidth), maskHeight_(maskHeight), + taperAngle_(taperAngle), maskMaterial_(maskMaterial) { + if (halfStack) + domain_->getSetup().halveXAxis(); + } + MakeStack(psDomainType domain, NumericType gridDelta, NumericType xExtent, NumericType yExtent, int numLayers, NumericType layerHeight, NumericType substrateHeight, NumericType holeRadius, NumericType trenchWidth, NumericType maskHeight, bool periodicBoundary = false) - : pDomain_(domain), gridDelta_(gridDelta), xExtent_(xExtent), - yExtent_(yExtent), numLayers_(numLayers), layerHeight_(layerHeight), + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + numLayers_(numLayers), layerHeight_(layerHeight), substrateHeight_(substrateHeight), holeRadius_(holeRadius), - trenchWidth_(trenchWidth), maskHeight_(maskHeight), - periodicBoundary_(periodicBoundary) { - init(); + trenchWidth_(trenchWidth), maskHeight_(maskHeight) { + domain_->setup(gridDelta, xExtent, yExtent, + periodicBoundary ? BoundaryType::PERIODIC_BOUNDARY + : BoundaryType::REFLECTIVE_BOUNDARY); } void apply() { - if constexpr (D == 2) { - create2DGeometry(); - } else { - create3DGeometry(); - } - } - - int getTopLayer() const { return numLayers_; } - - NumericType getHeight() const { - return substrateHeight_ + numLayers_ * layerHeight_; - } - -private: - void create2DGeometry() { - pDomain_->clear(); + domain_->clear(); + domain_->getSetup().check(); if (maskHeight_ > 0.) { - // mask on top - auto mask = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = - substrateHeight_ + layerHeight_ * numLayers_ + maskHeight_; - viennals::MakeGeometry( - mask, - SmartPointer>::New(origin_, normal_)) - .apply(); - - auto maskAdd = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = substrateHeight_ + layerHeight_ * numLayers_; - normal_[D - 1] = -1; - viennals::MakeGeometry( - maskAdd, - SmartPointer>::New(origin_, normal_)) - .apply(); - normal_[D - 1] = 1.; - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::INTERSECT) - .apply(); - - if (holeRadius_ == 0.) { - holeRadius_ = trenchWidth_ / 2.; + NumericType maskBase = substrateHeight_ + layerHeight_ * numLayers_; + auto mask = geometryFactory_.makeMask(maskBase - eps_, maskHeight_); + domain_->insertNextLevelSetAsMaterial(mask, maskMaterial_); + + std::array position = {0.}; + position[D - 1] = maskBase - 2 * eps_; + + if (holeRadius_ > 0. && D == 3) { + auto cutout = geometryFactory_.makeCylinderStencil( + position, holeRadius_, maskHeight_ + 3 * eps_, taperAngle_); + domain_->applyBooleanOperation( + cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); + } else { + NumericType trenchWidth = trenchWidth_; + if (trenchWidth == 0.) { + trenchWidth = 2 * holeRadius_; + } + if (trenchWidth == 0.) { + Logger::getInstance() + .addError( + "MakeStack: Trench width or hole radius must be greater " + "0 to create mask.") + .print(); + } + auto cutout = geometryFactory_.makeBoxStencil( + position, trenchWidth, maskHeight_ + 3 * eps_, -taperAngle_); + domain_->applyBooleanOperation( + cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); } - NumericType minPoint[D] = {-holeRadius_, substrateHeight_ + - layerHeight_ * numLayers_ - - gridDelta_}; - NumericType maxPoint[D] = {holeRadius_, substrateHeight_ + - layerHeight_ * numLayers_ + - maskHeight_ + gridDelta_}; - viennals::MakeGeometry( - maskAdd, - SmartPointer>::New(minPoint, maxPoint)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT) - .apply(); - - pDomain_->insertNextLevelSetAsMaterial(mask, Material::Mask); } // Silicon substrate - auto substrate = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = substrateHeight_; - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin_, normal_)) - .apply(); - pDomain_->insertNextLevelSetAsMaterial(substrate, Material::Si); + auto substrate = geometryFactory_.makeSubstrate(substrateHeight_); + domain_->insertNextLevelSetAsMaterial(substrate, Material::Si); // Si3N4/SiO2 layers NumericType current = substrateHeight_ + layerHeight_; for (int i = 0; i < numLayers_; ++i) { - auto ls = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = substrateHeight_ + layerHeight_ * (i + 1); - viennals::MakeGeometry( - ls, - SmartPointer>::New(origin_, normal_)) - .apply(); + auto ls = geometryFactory_.makeSubstrate(current); if (i % 2 == 0) { - pDomain_->insertNextLevelSetAsMaterial(ls, Material::SiO2); + domain_->insertNextLevelSetAsMaterial(ls, Material::SiO2); } else { - pDomain_->insertNextLevelSetAsMaterial(ls, Material::Si3N4); + domain_->insertNextLevelSetAsMaterial(ls, Material::Si3N4); } + current += layerHeight_; } if ((holeRadius_ > 0. || trenchWidth_ > 0.) && maskHeight_ == 0.) { - if (holeRadius_ == 0.) { - holeRadius_ = trenchWidth_ / 2.; - } - // cut out middle - auto cutOut = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - NumericType minPoint[D] = {-holeRadius_, 0.}; - NumericType maxPoint[D] = {holeRadius_, substrateHeight_ + - layerHeight_ * numLayers_ + - maskHeight_ + gridDelta_}; - viennals::MakeGeometry( - cutOut, - SmartPointer>::New(minPoint, maxPoint)) - .apply(); - - pDomain_->applyBooleanOperation( - cutOut, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); - } - } - - void create3DGeometry() { - pDomain_->clear(); - - if (maskHeight_ > 0.) { - auto mask = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = - substrateHeight_ + layerHeight_ * numLayers_ + maskHeight_; - viennals::MakeGeometry( - mask, - SmartPointer>::New(origin_, normal_)) - .apply(); - - auto maskAdd = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = substrateHeight_ + layerHeight_ * numLayers_; - normal_[D - 1] = -1; - viennals::MakeGeometry( - maskAdd, - SmartPointer>::New(origin_, normal_)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::INTERSECT) - .apply(); - - if (holeRadius_ > 0.) { - normal_[D - 1] = 1.; - viennals::MakeGeometry( - maskAdd, - SmartPointer>::New( - origin_, normal_, maskHeight_ + gridDelta_, holeRadius_)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT) - .apply(); - } else if (trenchWidth_ > 0.) { - NumericType minPoint[D] = { - static_cast(-trenchWidth_ / 2.), - static_cast(-yExtent_ / 2. - gridDelta_), - origin_[D - 1]}; - NumericType maxPoint[D] = { - static_cast(trenchWidth_ / 2.), - static_cast(yExtent_ / 2. + gridDelta_), - origin_[D - 1] + maskHeight_ + gridDelta_}; - viennals::MakeGeometry( - maskAdd, SmartPointer>::New(minPoint, - maxPoint)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT) - .apply(); - } - - pDomain_->insertNextLevelSetAsMaterial(mask, Material::Mask); - } - - // Silicon substrate - auto substrate = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = substrateHeight_; - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin_, normal_)) - .apply(); - pDomain_->insertNextLevelSetAsMaterial(substrate, Material::Si); - - // Si3N4/SiO2 layers - for (int i = 0; i < numLayers_; ++i) { - auto ls = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = substrateHeight_ + layerHeight_ * (i + 1); - viennals::MakeGeometry( - ls, - SmartPointer>::New(origin_, normal_)) - .apply(); - if (i % 2 == 0) { - pDomain_->insertNextLevelSetAsMaterial(ls, Material::SiO2); + std::array position = {0.}; + position[D - 1] = substrateHeight_; + + if (holeRadius_ > 0. && D == 3) { + auto cutout = geometryFactory_.makeCylinderStencil( + position, holeRadius_, numLayers_ * layerHeight_ + eps_, + -taperAngle_); + domain_->applyBooleanOperation( + cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); } else { - pDomain_->insertNextLevelSetAsMaterial(ls, Material::Si3N4); + NumericType trenchWidth = trenchWidth_; + if (trenchWidth == 0.) { + trenchWidth = 2 * holeRadius_; + } + auto cutout = geometryFactory_.makeBoxStencil( + position, trenchWidth, numLayers_ * layerHeight_ + eps_, + -taperAngle_); + domain_->applyBooleanOperation( + cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); } } - - if (holeRadius_ > 0. && maskHeight_ == 0.) { - // cut out middle - auto cutOut = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - origin_[D - 1] = 0.; - viennals::MakeGeometry( - cutOut, - SmartPointer>::New( - origin_, normal_, (numLayers_ + 1) * layerHeight_, holeRadius_)) - .apply(); - - pDomain_->applyBooleanOperation( - cutOut, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); - - } else if (trenchWidth_ > 0. && maskHeight_ == 0.) { - auto cutOut = lsDomainType::New(bounds_, boundaryConds_, gridDelta_); - NumericType minPoint[D] = { - static_cast(-trenchWidth_ / 2.), - static_cast(-yExtent_ / 2. - gridDelta_), - (NumericType)0.}; - NumericType maxPoint[D] = { - static_cast(trenchWidth_ / 2.), - static_cast(yExtent_ / 2. + gridDelta_), - substrateHeight_ + layerHeight_ * numLayers_ + maskHeight_ + - gridDelta_}; - viennals::MakeGeometry( - cutOut, - SmartPointer>::New(minPoint, maxPoint)) - .apply(); - - pDomain_->applyBooleanOperation( - cutOut, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); - } } - void init() { - bounds_[0] = -xExtent_ / 2.; - bounds_[1] = xExtent_ / 2.; - normal_[0] = 0.; - if (periodicBoundary_) - boundaryConds_[0] = BoundaryEnum::PERIODIC_BOUNDARY; - else - boundaryConds_[0] = BoundaryEnum::REFLECTIVE_BOUNDARY; + int getTopLayer() const { return numLayers_; } - if constexpr (D == 2) { - normal_[1] = 1.; - bounds_[2] = 0; - bounds_[3] = layerHeight_ * numLayers_ + gridDelta_; - boundaryConds_[1] = BoundaryEnum::INFINITE_BOUNDARY; - } else { - normal_[1] = 0.; - normal_[2] = 1.; - bounds_[2] = -yExtent_ / 2.; - bounds_[3] = yExtent_ / 2.; - bounds_[4] = 0; - bounds_[5] = layerHeight_ * numLayers_ + gridDelta_; - if (periodicBoundary_) - boundaryConds_[1] = BoundaryEnum::PERIODIC_BOUNDARY; - else - boundaryConds_[1] = BoundaryEnum::REFLECTIVE_BOUNDARY; - boundaryConds_[2] = BoundaryEnum::INFINITE_BOUNDARY; - } + NumericType getHeight() const { + return substrateHeight_ + numLayers_ * layerHeight_ + maskHeight_; } }; diff --git a/include/viennaps/geometries/psMakeTrench.hpp b/include/viennaps/geometries/psMakeTrench.hpp index 273aac94..c93a442c 100644 --- a/include/viennaps/geometries/psMakeTrench.hpp +++ b/include/viennaps/geometries/psMakeTrench.hpp @@ -1,6 +1,7 @@ #pragma once #include "../psDomain.hpp" +#include "psGeometryFactory.hpp" #include #include @@ -19,214 +20,79 @@ using namespace viennacore; /// exclusively to the bottom while the remaining portion adopts the mask /// material_. template class MakeTrench { - using lsDomainType = SmartPointer>; using psDomainType = SmartPointer>; - using BoundaryEnum = typename viennals::Domain::BoundaryType; - psDomainType pDomain_ = nullptr; - - const NumericType gridDelta_; - const NumericType xExtent_; - const NumericType yExtent_; + psDomainType domain_; + GeometryFactory geometryFactory_; + static constexpr NumericType eps_ = 1e-4; const NumericType trenchWidth_; const NumericType trenchDepth_; - const NumericType taperAngle_; // taper angle in degrees - const NumericType baseHeight_; + const NumericType trenchTaperAngle_; // angle in degrees + + const NumericType maskHeight_; + const NumericType maskTaperAngle_; - const bool periodicBoundary_; - const bool makeMask_; - Material material_; + const NumericType base_; + const Material material_; + const Material maskMaterial_ = Material::Mask; public: + MakeTrench(psDomainType domain, NumericType trenchWidth, + NumericType trenchDepth, NumericType trenchTaperAngle = 0, + NumericType maskHeight = 0, NumericType maskTaperAngle = 0, + bool halfTrench = false, Material material = Material::Si, + Material maskMaterial = Material::Mask) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + trenchWidth_(trenchWidth), trenchDepth_(trenchDepth), + trenchTaperAngle_(trenchTaperAngle), maskHeight_(maskHeight), + maskTaperAngle_(maskTaperAngle), base_(0.0), material_(material), + maskMaterial_(maskMaterial) { + if (halfTrench) + domain_->getSetup().halveXAxis(); + } + MakeTrench(psDomainType domain, NumericType gridDelta, NumericType xExtent, NumericType yExtent, NumericType trenchWidth, NumericType trenchDepth, NumericType taperAngle = 0., - NumericType baseHeight = 0., bool periodicBoundary = false, - bool makeMask = false, Material material = Material::None) - : pDomain_(domain), gridDelta_(gridDelta), xExtent_(xExtent), - yExtent_(yExtent), trenchWidth_(trenchWidth), trenchDepth_(trenchDepth), - taperAngle_(taperAngle), baseHeight_(baseHeight), - periodicBoundary_(periodicBoundary), makeMask_(makeMask), - material_(material) {} + NumericType base = 0., bool periodicBoundary = false, + bool makeMask = false, Material material = Material::Si) + : domain_(domain), geometryFactory_(domain->getSetup(), __func__), + trenchWidth_(trenchWidth), trenchDepth_(makeMask ? 0 : trenchDepth), + trenchTaperAngle_(makeMask ? 0 : taperAngle), + maskHeight_(makeMask ? trenchDepth : 0), + maskTaperAngle_(makeMask ? taperAngle : 0), base_(base), + material_(material) { + domain_->setup(gridDelta, xExtent, yExtent, + periodicBoundary ? BoundaryType::PERIODIC_BOUNDARY + : BoundaryType::REFLECTIVE_BOUNDARY); + } void apply() { - pDomain_->clear(); - double bounds[2 * D]; - bounds[0] = -xExtent_ / 2.; - bounds[1] = xExtent_ / 2.; - - if constexpr (D == 3) { - bounds[2] = -yExtent_ / 2.; - bounds[3] = yExtent_ / 2.; - bounds[4] = -gridDelta_; - bounds[5] = trenchDepth_ + gridDelta_; - } else { - bounds[2] = -gridDelta_; - bounds[3] = trenchDepth_ + gridDelta_; + domain_->clear(); // this does not clear the setup + domain_->getSetup().check(); + + if (maskHeight_ > 0.) { + auto mask = geometryFactory_.makeMask(base_ - eps_, maskHeight_); + domain_->insertNextLevelSetAsMaterial(mask, maskMaterial_); + std::array position = {0.}; + position[D - 1] = base_ - 2 * eps_; + auto cutout = geometryFactory_.makeBoxStencil( + position, trenchWidth_, maskHeight_ + 3 * eps_, -maskTaperAngle_); + domain_->applyBooleanOperation( + cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT); } - BoundaryEnum boundaryCons[D]; - for (int i = 0; i < D - 1; i++) { - if (periodicBoundary_) { - boundaryCons[i] = BoundaryEnum::PERIODIC_BOUNDARY; - } else { - boundaryCons[i] = BoundaryEnum::REFLECTIVE_BOUNDARY; - } - } - boundaryCons[D - 1] = BoundaryEnum::INFINITE_BOUNDARY; - - auto substrate = lsDomainType::New(bounds, boundaryCons, gridDelta_); - NumericType normal[D] = {0.}; - NumericType origin[D] = {0.}; - normal[D - 1] = 1.; - origin[D - 1] = baseHeight_; - viennals::MakeGeometry( - substrate, - SmartPointer>::New(origin, normal)) - .apply(); - - auto mask = lsDomainType::New(bounds, boundaryCons, gridDelta_); - origin[D - 1] = trenchDepth_ + baseHeight_; - viennals::MakeGeometry( - mask, - SmartPointer>::New(origin, normal)) - .apply(); - - auto maskAdd = lsDomainType::New(bounds, boundaryCons, gridDelta_); - origin[D - 1] = baseHeight_; - normal[D - 1] = -1.; - viennals::MakeGeometry( - maskAdd, - SmartPointer>::New(origin, normal)) - .apply(); - - viennals::BooleanOperation( - mask, maskAdd, viennals::BooleanOperationEnum::INTERSECT) - .apply(); - - auto cutout = lsDomainType::New(bounds, boundaryCons, gridDelta_); - - if (taperAngle_) { - auto mesh = SmartPointer>::New(); - const NumericType offset = - std::tan(taperAngle_ * M_PI / 180.) * trenchDepth_; - if constexpr (D == 2) { - for (int i = 0; i < 4; i++) { - std::array node = {0., 0., 0.}; - mesh->insertNextNode(node); - } - mesh->nodes[0][0] = -trenchWidth_ / 2.; - mesh->nodes[1][0] = trenchWidth_ / 2.; - mesh->nodes[2][0] = trenchWidth_ / 2. + offset; - mesh->nodes[3][0] = -trenchWidth_ / 2. - offset; - - mesh->nodes[0][1] = baseHeight_; - mesh->nodes[1][1] = baseHeight_; - mesh->nodes[2][1] = trenchDepth_ + baseHeight_; - mesh->nodes[3][1] = trenchDepth_ + baseHeight_; - - mesh->insertNextLine(std::array{0, 3}); - mesh->insertNextLine(std::array{3, 2}); - mesh->insertNextLine(std::array{2, 1}); - mesh->insertNextLine(std::array{1, 0}); - viennals::FromSurfaceMesh(cutout, mesh).apply(); - } else { - for (int i = 0; i < 8; i++) { - std::array node = {0., 0., 0.}; - mesh->insertNextNode(node); - } - mesh->nodes[0][0] = -trenchWidth_ / 2.; - mesh->nodes[0][1] = -yExtent_ / 2. - gridDelta_; - mesh->nodes[0][2] = baseHeight_; - - mesh->nodes[1][0] = trenchWidth_ / 2.; - mesh->nodes[1][1] = -yExtent_ / 2. - gridDelta_; - mesh->nodes[1][2] = baseHeight_; - - mesh->nodes[2][0] = trenchWidth_ / 2.; - mesh->nodes[2][1] = yExtent_ / 2. + gridDelta_; - mesh->nodes[2][2] = baseHeight_; - - mesh->nodes[3][0] = -trenchWidth_ / 2.; - mesh->nodes[3][1] = yExtent_ / 2. + gridDelta_; - mesh->nodes[3][2] = baseHeight_; - - mesh->nodes[4][0] = -trenchWidth_ / 2. - offset; - mesh->nodes[4][1] = -yExtent_ / 2. - gridDelta_; - mesh->nodes[4][2] = trenchDepth_ + baseHeight_; - - mesh->nodes[5][0] = trenchWidth_ / 2. + offset; - mesh->nodes[5][1] = -yExtent_ / 2. - gridDelta_; - mesh->nodes[5][2] = trenchDepth_ + baseHeight_; - - mesh->nodes[6][0] = trenchWidth_ / 2. + offset; - mesh->nodes[6][1] = yExtent_ / 2. + gridDelta_; - mesh->nodes[6][2] = trenchDepth_ + baseHeight_; - - mesh->nodes[7][0] = -trenchWidth_ / 2. - offset; - mesh->nodes[7][1] = yExtent_ / 2. + gridDelta_; - mesh->nodes[7][2] = trenchDepth_ + baseHeight_; - - mesh->insertNextTriangle(std::array{0, 3, 1}); - mesh->insertNextTriangle(std::array{1, 3, 2}); - - mesh->insertNextTriangle(std::array{5, 6, 4}); - mesh->insertNextTriangle(std::array{6, 7, 4}); - - mesh->insertNextTriangle(std::array{0, 1, 5}); - mesh->insertNextTriangle(std::array{0, 5, 4}); - - mesh->insertNextTriangle(std::array{2, 3, 6}); - mesh->insertNextTriangle(std::array{6, 3, 7}); - - mesh->insertNextTriangle(std::array{0, 7, 3}); - mesh->insertNextTriangle(std::array{0, 4, 7}); - - mesh->insertNextTriangle(std::array{1, 2, 6}); - mesh->insertNextTriangle(std::array{1, 6, 5}); - - viennals::FromSurfaceMesh(cutout, mesh).apply(); - } - } else { - NumericType minPoint[D]; - NumericType maxPoint[D]; - - minPoint[0] = -trenchWidth_ / 2; - maxPoint[0] = trenchWidth_ / 2; - - if constexpr (D == 3) { - minPoint[1] = -yExtent_ / 2. - gridDelta_ / 2.; - maxPoint[1] = yExtent_ / 2. + gridDelta_ / 2.; - minPoint[2] = baseHeight_; - maxPoint[2] = trenchDepth_ + baseHeight_; - } else { - minPoint[1] = baseHeight_; - maxPoint[1] = trenchDepth_ + baseHeight_; - } - viennals::MakeGeometry geo( - cutout, - SmartPointer>::New(minPoint, maxPoint)); - geo.setIgnoreBoundaryConditions(true); - geo.apply(); - } + auto substrate = geometryFactory_.makeSubstrate(base_); + domain_->insertNextLevelSetAsMaterial(substrate, material_); - viennals::BooleanOperation( - mask, cutout, viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT) - .apply(); - - viennals::BooleanOperation( - substrate, mask, viennals::BooleanOperationEnum::UNION) - .apply(); - - if (material_ == Material::None) { - if (makeMask_) - pDomain_->insertNextLevelSet(mask); - pDomain_->insertNextLevelSet(substrate, false); - } else { - if (makeMask_) - pDomain_->insertNextLevelSetAsMaterial(mask, Material::Mask); - pDomain_->insertNextLevelSetAsMaterial(substrate, material_, false); + if (trenchDepth_ > 0.) { + std::array position = {0.}; + position[D - 1] = base_; + auto cutout = geometryFactory_.makeBoxStencil( + position, trenchWidth_, -trenchDepth_, -trenchTaperAngle_); + domain_->applyBooleanOperation(cutout, + viennals::BooleanOperationEnum::INTERSECT); } } }; diff --git a/include/viennaps/models/psIsotropicProcess.hpp b/include/viennaps/models/psIsotropicProcess.hpp index e9b001aa..a74ecf78 100644 --- a/include/viennaps/models/psIsotropicProcess.hpp +++ b/include/viennaps/models/psIsotropicProcess.hpp @@ -53,7 +53,7 @@ template class IsotropicProcess : public ProcessModel { public: IsotropicProcess(const NumericType isotropicRate, - const Material maskMaterial = Material::None) { + const Material maskMaterial = Material::Undefined) { // default surface model auto surfModel = SmartPointer>::New(); diff --git a/include/viennaps/models/psSingleParticleProcess.hpp b/include/viennaps/models/psSingleParticleProcess.hpp index de05c605..195ac5ae 100644 --- a/include/viennaps/models/psSingleParticleProcess.hpp +++ b/include/viennaps/models/psSingleParticleProcess.hpp @@ -92,7 +92,7 @@ class SingleParticleProcess : public ProcessModel { SingleParticleProcess(NumericType rate = 1., NumericType stickingProbability = 1., NumericType sourceDistributionPower = 1., - Material maskMaterial = Material::None) { + Material maskMaterial = Material::Undefined) { std::unordered_map maskMaterialMap = { {maskMaterial, 0.}}; initialize(rate, stickingProbability, sourceDistributionPower, diff --git a/include/viennaps/psAtomicLayerProcess.hpp b/include/viennaps/psAtomicLayerProcess.hpp index b43bb836..50728d2a 100644 --- a/include/viennaps/psAtomicLayerProcess.hpp +++ b/include/viennaps/psAtomicLayerProcess.hpp @@ -156,7 +156,7 @@ template class AtomicLayerProcess { // Map the domain boundary to the ray tracing boundaries for (unsigned i = 0; i < D; ++i) - rayBoundaryCondition[i] = utils::convertBoundaryCondition( + rayBoundaryCondition[i] = utils::convertBoundaryCondition( pDomain_->getGrid().getBoundaryConditions(i)); rayTracer.setSourceDirection(sourceDirection_); diff --git a/include/viennaps/psDomain.hpp b/include/viennaps/psDomain.hpp index 230337e9..cf6c014d 100644 --- a/include/viennaps/psDomain.hpp +++ b/include/viennaps/psDomain.hpp @@ -1,5 +1,6 @@ #pragma once +#include "psDomainSetup.hpp" #include "psMaterials.hpp" #include "psSurfacePointValuesToLevelSet.hpp" @@ -40,10 +41,12 @@ template class Domain { using lsDomainsType = std::vector; using csDomainType = SmartPointer>; using materialMapType = SmartPointer; + using Setup = DomainSetup; static constexpr char materialIdsLabel[] = "MaterialIds"; private: + Setup setup_; lsDomainsType levelSets_; csDomainType cellSet_ = nullptr; materialMapType materialMap_ = nullptr; @@ -56,15 +59,46 @@ template class Domain { Domain(SmartPointer domain) { deepCopy(domain); } // Constructor for domain with a single initial Level-Set. - Domain(lsDomainType levelSet) { levelSets_.push_back(levelSet); } + Domain(lsDomainType levelSet) { + setup_.init(levelSet->getGrid()); + levelSets_.push_back(levelSet); + } // Constructor for domain with multiple initial Level-Sets. - Domain(lsDomainsType levelSets) : levelSets_(levelSets) {} + Domain(lsDomainsType levelSets) : levelSets_(levelSets) { + setup_.init(levelSets.back()->getGrid()); + } + + // Sets up domain in with primary direction y in 2D and z in 3D + Domain(NumericType gridDelta, NumericType xExtent, + BoundaryType boundary = BoundaryType::REFLECTIVE_BOUNDARY) + : setup_(gridDelta, xExtent, 0.0, boundary) { + static_assert(D == 2, "Domain setup only valid for 2D."); + } + + // Sets up domain in with primary direction y in 2D and z in 3D + // In 2D yExtent is ignored. + Domain(NumericType gridDelta, NumericType xExtent, NumericType yExtent = 0.0, + BoundaryType boundary = BoundaryType::REFLECTIVE_BOUNDARY) + : setup_(gridDelta, xExtent, yExtent, boundary) {} + + Domain(const Setup &setup) : setup_(setup) {} + + void setup(const Setup &setup) { setup_ = setup; } + + void setup(NumericType gridDelta, NumericType xExtent, + NumericType yExtent = 0, + BoundaryType boundary = BoundaryType::REFLECTIVE_BOUNDARY) { + setup_ = Setup(gridDelta, xExtent, yExtent, boundary); + } // Create a deep copy of all Level-Sets and the Cell-Set from the passed // domain. void deepCopy(SmartPointer domain) { + clear(); + setup_ = domain->setup_; + // Copy all Level-Sets. for (auto &ls : domain->levelSets_) { levelSets_.push_back(lsDomainType::New(ls)); @@ -91,8 +125,13 @@ template class Domain { } } + // Will be deprecated in the future. Please use insertNextLevelSetAsMaterial + // instead. void insertNextLevelSet(lsDomainType levelSet, bool wrapLowerLevelSet = true) { + if (levelSets_.empty()) { + setup_.init(levelSet->getGrid()); + } if (!levelSets_.empty() && wrapLowerLevelSet) { viennals::BooleanOperation( levelSet, levelSets_.back(), viennals::BooleanOperationEnum::UNION) @@ -111,6 +150,9 @@ template class Domain { void insertNextLevelSetAsMaterial(lsDomainType levelSet, const Material material, bool wrapLowerLevelSet = true) { + if (levelSets_.empty()) { + setup_.init(levelSet->getGrid()); + } if (!levelSets_.empty() && wrapLowerLevelSet) { viennals::BooleanOperation( levelSet, levelSets_.back(), viennals::BooleanOperationEnum::UNION) @@ -126,17 +168,16 @@ template class Domain { // Copy the top Level-Set and insert it in the domain (e.g. in order to // capture depositing material on top of the surface). - void duplicateTopLevelSet(const Material material = Material::None) { + void duplicateTopLevelSet(const Material material) { if (levelSets_.empty()) { + Logger::getInstance() + .addWarning("Trying to duplicate non-existing Level-Set in domain.") + .print(); return; } auto copy = lsDomainType::New(levelSets_.back()); - if (material == Material::None) { - insertNextLevelSet(copy, false); - } else { - insertNextLevelSetAsMaterial(copy, material, false); - } + insertNextLevelSetAsMaterial(copy, material, false); } // Remove the top (last inserted) Level-Set. @@ -260,11 +301,11 @@ template class Domain { auto &getCellSet() const { return cellSet_; } // Returns the underlying HRLE grid of the top Level-Set in the domain. - auto &getGrid() const { return levelSets_.back()->getGrid(); } + auto &getGrid() const { return setup_.grid(); } - auto getGridDelta() const { - return levelSets_.back()->getGrid().getGridDelta(); - } + auto getGridDelta() const { return setup_.gridDelta(); } + + auto &getSetup() { return setup_; } // Returns the bounding box of the top Level-Set in the domain. // [min, max][x, y, z] diff --git a/include/viennaps/psDomainSetup.hpp b/include/viennaps/psDomainSetup.hpp new file mode 100644 index 00000000..c965a3eb --- /dev/null +++ b/include/viennaps/psDomainSetup.hpp @@ -0,0 +1,169 @@ +#pragma once + +#include "psUtils.hpp" +#include +#include + +namespace viennaps { + +using namespace viennacore; +using BoundaryType = hrleBoundaryType; + +template class DomainSetup { + NumericType gridDelta_; + double bounds_[2 * D]; + BoundaryType boundaryCons_[D]; + hrleGrid grid_; + +public: + DomainSetup() : gridDelta_(0.0) { + for (int i = 0; i < D; i++) { + bounds_[2 * i] = 0.0; + bounds_[2 * i + 1] = 0.0; + boundaryCons_[i] = BoundaryType::INFINITE_BOUNDARY; + } + } + + DomainSetup(NumericType gridDelta, NumericType xExtent, NumericType yExtent, + BoundaryType boundary = BoundaryType::REFLECTIVE_BOUNDARY) + : gridDelta_(gridDelta) { + if (xExtent <= 0.0) { + Logger::getInstance() + .addWarning("Invalid 'x' extent for domain setup.") + .print(); + } + + bounds_[0] = -xExtent / 2.; + bounds_[1] = xExtent / 2.; + + if constexpr (D == 3) { + if (yExtent <= 0.0) { + Logger::getInstance() + .addWarning("Invalid 'y' extent for domain setup.") + .print(); + } + bounds_[2] = -yExtent / 2.; + bounds_[3] = yExtent / 2.; + bounds_[4] = -gridDelta; + bounds_[5] = gridDelta; + } else { + bounds_[2] = -gridDelta; + bounds_[3] = gridDelta; + } + + for (int i = 0; i < D - 1; i++) { + boundaryCons_[i] = boundary; + } + boundaryCons_[D - 1] = BoundaryType::INFINITE_BOUNDARY; + init(); + } + + auto &grid() const { + check(); + return grid_; + } + + NumericType gridDelta() const { + check(); + return gridDelta_; + } + + std::array bounds() const { + check(); + std::array boundsArray; + for (int i = 0; i < 2 * D; i++) { + boundsArray[i] = bounds_[i]; + } + return boundsArray; + } + + std::array boundaryCons() const { + check(); + std::array boundaryConsArray; + for (int i = 0; i < D; i++) { + boundaryConsArray[i] = boundaryCons_[i]; + } + return boundaryConsArray; + } + + NumericType xExtent() const { return bounds_[1] - bounds_[0]; } + + NumericType yExtent() const { return bounds_[3] - bounds_[2]; } + + bool hasPeriodicBoundary() const { + return boundaryCons_[0] == BoundaryType::PERIODIC_BOUNDARY || + boundaryCons_[1] == BoundaryType::PERIODIC_BOUNDARY; + } + + bool isValid() const { + return gridDelta_ > 0.0 && xExtent() > 0.0 && + (D == 2 || (D == 3 && yExtent() > 0.0)); + } + + void print() const { + std::cout << "Domain setup:" << std::endl; + std::cout << "\tGrid delta: " << gridDelta_ << std::endl; + std::cout << "\tX extent: " << xExtent() << std::endl; + if constexpr (D == 3) + std::cout << "\tY extent: " << yExtent() << std::endl; + std::cout << "\tPeriodic boundary: " + << utils::boolString(hasPeriodicBoundary()) << std::endl; + } + + void halveXAxis() { + check(); + if (hasPeriodicBoundary()) { + Logger::getInstance() + .addWarning("Half geometry cannot be created with " + "periodic boundaries!") + .print(); + } else { + bounds_[0] = 0.0; + init(); + } + } + + void halveYAxis() { + check(); + if (hasPeriodicBoundary()) { + Logger::getInstance() + .addWarning("Half geometry cannot be created with " + "periodic boundaries!") + .print(); + } else { + bounds_[2] = 0.0; + init(); + } + } + + void init() { + check(); + hrleIndexType gridMin[D], gridMax[D]; + for (unsigned i = 0; i < D; ++i) { + gridMin[i] = std::floor(bounds_[2 * i] / gridDelta_); + gridMax[i] = std::ceil(bounds_[2 * i + 1] / gridDelta_); + } + grid_ = hrleGrid(gridMin, gridMax, gridDelta_, boundaryCons_); + } + + void init(hrleGrid grid) { + gridDelta_ = grid.getGridDelta(); + for (int i = 0; i < D; i++) { + bounds_[2 * i] = grid.getMinBounds(i) * gridDelta_; + bounds_[2 * i + 1] = grid.getMaxBounds(i) * gridDelta_; + boundaryCons_[i] = grid.getBoundaryConditions(i); + } + grid_ = grid; + } + + void check() const { + if (!isValid()) { + print(); + Logger::getInstance() + .addError("Domain setup is not correctly initialized.") + .print(); + } + } +}; + +} // namespace viennaps \ No newline at end of file diff --git a/include/viennaps/psMaterials.hpp b/include/viennaps/psMaterials.hpp index ca0c932d..f0b9a504 100644 --- a/include/viennaps/psMaterials.hpp +++ b/include/viennaps/psMaterials.hpp @@ -12,7 +12,7 @@ namespace viennaps { using namespace viennacore; enum class Material : int { - None = -1, + Undefined = -1, Mask = 0, Si = 1, SiO2 = 2, @@ -44,7 +44,7 @@ class MaterialMap { public: MaterialMap() { map_ = SmartPointer::New(); }; - void insertNextMaterial(Material material = Material::None) { + void insertNextMaterial(Material material = Material::Undefined) { map_->insertNextMaterial(static_cast(material)); } @@ -72,7 +72,7 @@ class MaterialMap { static inline Material mapToMaterial(const int matId) { if (matId > 19 || matId < -1) - return Material::None; + return Material::Undefined; return static_cast(matId); } @@ -88,7 +88,7 @@ class MaterialMap { template static inline std::string getMaterialName(const T matId) { auto material = mapToMaterial(matId); switch (material) { - case Material::None: + case Material::Undefined: return "None"; case Material::Mask: return "Mask"; diff --git a/include/viennaps/psProcess.hpp b/include/viennaps/psProcess.hpp index e5fc9d99..c6e6e10c 100644 --- a/include/viennaps/psProcess.hpp +++ b/include/viennaps/psProcess.hpp @@ -849,7 +849,7 @@ template class Process { rayBoundaryCondition[i] = viennaray::BoundaryCondition::IGNORE; } else { for (unsigned i = 0; i < D; ++i) - rayBoundaryCondition[i] = utils::convertBoundaryCondition( + rayBoundaryCondition[i] = utils::convertBoundaryCondition( domain->getGrid().getBoundaryConditions(i)); } tracer.setBoundaryConditions(rayBoundaryCondition); diff --git a/include/viennaps/psUtils.hpp b/include/viennaps/psUtils.hpp index fc2cc630..b8945b0a 100644 --- a/include/viennaps/psUtils.hpp +++ b/include/viennaps/psUtils.hpp @@ -249,8 +249,7 @@ struct Parameters { } }; -template -[[nodiscard]] viennaray::BoundaryCondition convertBoundaryCondition( +[[nodiscard]] inline viennaray::BoundaryCondition convertBoundaryCondition( viennals::BoundaryConditionEnum originalBoundaryCondition) { switch (originalBoundaryCondition) { case viennals::BoundaryConditionEnum::REFLECTIVE_BOUNDARY: @@ -271,5 +270,9 @@ template return viennaray::BoundaryCondition::IGNORE; } +inline std::string boolString(const int in) { + return in == 0 ? "false" : "true"; +} + }; // namespace utils } // namespace viennaps diff --git a/python/__init__.py.in b/python/__init__.py.in index 8262f763..32f854f3 100644 --- a/python/__init__.py.in +++ b/python/__init__.py.in @@ -27,9 +27,10 @@ def _windows_dll_path(): if sys.platform == "win32": _windows_dll_path() -from .@NAME@ import * -from @LSNAME@ import IntegrationSchemeEnum as IntegrationScheme import @LSNAME@ as ls +from @LSNAME@ import IntegrationSchemeEnum as IntegrationScheme +from @LSNAME@ import BoundaryConditionEnum as BoundaryType +from .@NAME@ import * # Config file reader helper function def ReadConfigFile(fileName: str): diff --git a/python/generateStubs.py b/python/generateStubs.py index 9a9a6a39..bd89fafb 100644 --- a/python/generateStubs.py +++ b/python/generateStubs.py @@ -7,8 +7,8 @@ # parse dim parser = argparse.ArgumentParser() parser.add_argument("-D", type=int, default=2) + parser.add_argument("-dir", type=str, default=".") args = parser.parse_args() - dim = args.D # Don't create __pycache__ directory sys.dont_write_bytecode = True @@ -17,9 +17,9 @@ options = stubgen.parse_options( [ "-o", - ".", + args.dir, "-p", - "viennaps" + str(dim) + "d", + "viennaps" + str(args.D) + "d", ] ) diff --git a/python/pyWrap.cpp b/python/pyWrap.cpp index 7b53032e..14da064c 100644 --- a/python/pyWrap.cpp +++ b/python/pyWrap.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include // geometries +#include #include #include #include @@ -586,7 +588,7 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { // Enum Material pybind11::enum_(module, "Material") - .value("Undefined", Material::None) // 1 + .value("Undefined", Material::Undefined) // 1 .value("Mask", Material::Mask) .value("Si", Material::Si) .value("SiO2", Material::SiO2) @@ -619,7 +621,7 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { pybind11::arg("rate") = 1., pybind11::arg("stickingProbability") = 1., pybind11::arg("sourceExponent") = 1., - pybind11::arg("maskMaterial") = Material::None) + pybind11::arg("maskMaterial") = Material::Undefined) .def(pybind11::init([](const T rate, const T sticking, const T power, const std::vector mask) { return SmartPointer>::New( @@ -925,7 +927,7 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { return SmartPointer>::New(rate, mask); }), pybind11::arg("rate") = 1., - pybind11::arg("maskMaterial") = Material::None) + pybind11::arg("maskMaterial") = Material::Undefined) .def(pybind11::init([](const T rate, const std::vector mask) { return SmartPointer>::New(rate, mask); }), @@ -952,7 +954,7 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { &DirectionalEtching::RateSet::calculateVisibility) .def("print", &DirectionalEtching::RateSet::print); - // Expose DirectionalEtching class to Python + // DirectionalEtching pybind11::class_, SmartPointer>>( module, "DirectionalEtching", processModel) @@ -1057,26 +1059,49 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { // GEOMETRIES // *************************************************************************** + // Geometry Base + pybind11::class_>(module, "GeometryFactory") + .def(pybind11::init &, const std::string &>(), + pybind11::arg("domainSetup"), + pybind11::arg("name") = "GeometryFactory") + .def("makeMask", &GeometryFactory::makeMask, pybind11::arg("base"), + pybind11::arg("height")) + .def("makeSubstrate", &GeometryFactory::makeSubstrate, + pybind11::arg("base")) + .def("makeCylinderStencil", &GeometryFactory::makeCylinderStencil, + pybind11::arg("position"), pybind11::arg("radius"), + pybind11::arg("height"), pybind11::arg("angle")) + .def("makeBoxStencil", &GeometryFactory::makeBoxStencil, + pybind11::arg("position"), pybind11::arg("width"), + pybind11::arg("height"), pybind11::arg("angle")); + // Plane pybind11::class_>(module, "MakePlane") - .def(pybind11::init(), + .def(pybind11::init(), + pybind11::arg("domain"), pybind11::arg("height") = 0., + pybind11::arg("material") = Material::Si, + pybind11::arg("addToExisting") = false) + .def(pybind11::init(), pybind11::arg("domain"), pybind11::arg("gridDelta"), pybind11::arg("xExtent"), pybind11::arg("yExtent"), pybind11::arg("height") = 0., pybind11::arg("periodicBoundary") = false, - pybind11::arg("material") = Material::None) - .def(pybind11::init(), - pybind11::arg("domain"), pybind11::arg("height") = 0., - pybind11::arg("material") = Material::None) + pybind11::arg("material") = Material::Si) .def("apply", &MakePlane::apply, "Create a plane geometry or add plane to existing geometry."); // Trench pybind11::class_>(module, "MakeTrench") - .def(pybind11::init(), + .def( + pybind11::init(), + pybind11::arg("domain"), pybind11::arg("trenchWidth"), + pybind11::arg("trenchDepth"), pybind11::arg("trenchTaperAngle") = 0, + pybind11::arg("maskHeight") = 0, pybind11::arg("maskTaperAngle") = 0, + pybind11::arg("halfTrench") = false, + pybind11::arg("material") = Material::Si, + pybind11::arg("maskMaterial") = Material::Mask) + .def(pybind11::init(), pybind11::arg("domain"), pybind11::arg("gridDelta"), pybind11::arg("xExtent"), pybind11::arg("yExtent"), pybind11::arg("trenchWidth"), pybind11::arg("trenchDepth"), @@ -1084,7 +1109,7 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { pybind11::arg("baseHeight") = 0., pybind11::arg("periodicBoundary") = false, pybind11::arg("makeMask") = false, - pybind11::arg("material") = Material::None) + pybind11::arg("material") = Material::Si) .def("apply", &MakeTrench::apply, "Create a trench geometry."); // Hole @@ -1094,8 +1119,16 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { .value("Quarter", HoleShape::Quarter); pybind11::class_>(module, "MakeHole") - .def(pybind11::init(), + pybind11::arg("domain"), pybind11::arg("holeRadius"), + pybind11::arg("holeDepth"), pybind11::arg("holeTaperAngle") = 0., + pybind11::arg("maskHeight") = 0., + pybind11::arg("maskTaperAngle") = 0., + pybind11::arg("holeShape") = HoleShape::Full, + pybind11::arg("material") = Material::Si, + pybind11::arg("maskMaterial") = Material::Mask) + .def(pybind11::init(), pybind11::arg("domain"), pybind11::arg("gridDelta"), pybind11::arg("xExtent"), pybind11::arg("yExtent"), @@ -1104,43 +1137,41 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { pybind11::arg("baseHeight") = 0., pybind11::arg("periodicBoundary") = false, pybind11::arg("makeMask") = false, - pybind11::arg("material") = Material::None, - pybind11::arg("holeShape") = HoleShape::Full) // New argument + pybind11::arg("material") = Material::Si, + pybind11::arg("holeShape") = HoleShape::Full) .def("apply", &MakeHole::apply, "Create a hole geometry."); - // pybind11::class_>(module, "MakeHole") - // .def(pybind11::init(), - // pybind11::arg("domain"), pybind11::arg("gridDelta"), - // pybind11::arg("xExtent"), pybind11::arg("yExtent"), - // pybind11::arg("holeRadius"), pybind11::arg("holeDepth"), - // pybind11::arg("taperingAngle") = 0., - // pybind11::arg("baseHeight") = 0., - // pybind11::arg("periodicBoundary") = false, - // pybind11::arg("makeMask") = false, - // pybind11::arg("material") = Material::None) - // .def("apply", &MakeHole::apply, "Create a hole geometry."); - // Fin pybind11::class_>(module, "MakeFin") - .def(pybind11::init(), + .def( + pybind11::init(), + pybind11::arg("domain"), pybind11::arg("finWidth"), + pybind11::arg("finHeight"), pybind11::arg("finTaperAngle") = 0., + pybind11::arg("maskHeight") = 0, pybind11::arg("maskTaperAngle") = 0, + pybind11::arg("halfFin") = false, + pybind11::arg("material") = Material::Si, + pybind11::arg("maskMaterial") = Material::Mask) + .def(pybind11::init(), pybind11::arg("domain"), pybind11::arg("gridDelta"), pybind11::arg("xExtent"), pybind11::arg("yExtent"), pybind11::arg("finWidth"), pybind11::arg("finHeight"), pybind11::arg("taperAngle") = 0., pybind11::arg("baseHeight") = 0., pybind11::arg("periodicBoundary") = false, pybind11::arg("makeMask") = false, - pybind11::arg("material") = Material::None) + pybind11::arg("material") = Material::Si) .def("apply", &MakeFin::apply, "Create a fin geometry."); // Stack pybind11::class_>(module, "MakeStack") - .def(pybind11::init(), + .def(pybind11::init(), + pybind11::arg("domain"), pybind11::arg("numLayers"), + pybind11::arg("layerHeight"), pybind11::arg("substrateHeight") = 0, + pybind11::arg("holeRadius") = 0, pybind11::arg("trenchWidth") = 0, + pybind11::arg("maskHeight") = 0, pybind11::arg("taperAngle") = 0, + pybind11::arg("halfStack") = false, + pybind11::arg("maskMaterial") = Material::Mask) + .def(pybind11::init(), pybind11::arg("domain"), pybind11::arg("gridDelta"), pybind11::arg("xExtent"), pybind11::arg("yExtent"), pybind11::arg("numLayers"), pybind11::arg("layerHeight"), @@ -1318,7 +1349,37 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { pybind11::class_, DomainType>(module, "Domain") // constructors .def(pybind11::init(&DomainType::New<>)) + .def(pybind11::init( + [](DomainType &domain) { return DomainType::New(domain); }), + pybind11::arg("domain"), "Deep copy constructor.") + .def(pybind11::init( + [](T gridDelta, T xExtent, T yExtent, BoundaryType boundary) { + return DomainType::New(gridDelta, xExtent, yExtent, boundary); + }), + pybind11::arg("gridDelta"), pybind11::arg("xExtent"), + pybind11::arg("yExtent"), + pybind11::arg("boundary") = BoundaryType::REFLECTIVE_BOUNDARY) +#if VIENNAPS_PYTHON_DIMENSION == 2 + .def(pybind11::init([](T gridDelta, T xExtent, BoundaryType boundary) { + return DomainType::New(gridDelta, xExtent, boundary); + }), + pybind11::arg("gridDelta"), pybind11::arg("xExtent"), + pybind11::arg("boundary") = BoundaryType::REFLECTIVE_BOUNDARY) +#endif + .def(pybind11::init(&DomainType::New &>), + pybind11::arg("setup")) // methods + .def("setup", + pybind11::overload_cast &>( + &Domain::setup), + "Setup the domain.") + .def("setup", + pybind11::overload_cast(&Domain::setup), + pybind11::arg("gridDelta"), pybind11::arg("xExtent"), + pybind11::arg("yExtent") = 0., + pybind11::arg("boundary") = BoundaryType::REFLECTIVE_BOUNDARY, + "Setup the domain.") + .def("getSetup", &Domain::getSetup, "Get the domain setup.") .def("deepCopy", &Domain::deepCopy) .def("insertNextLevelSet", &Domain::insertNextLevelSet, pybind11::arg("levelset"), pybind11::arg("wrapLowerLevelSet") = true, @@ -1366,12 +1427,31 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { pybind11::arg("filename")) .def("clear", &Domain::clear); + // Domain Setup + pybind11::class_>(module, "DomainSetup") + .def(pybind11::init<>()) + .def(pybind11::init(), pybind11::arg("gridDelta"), + pybind11::arg("xExtent"), pybind11::arg("yExtent"), + pybind11::arg("boundary") = BoundaryType::REFLECTIVE_BOUNDARY) + .def("grid", &DomainSetup::grid) + .def("gridDelta", &DomainSetup::gridDelta) + .def("bounds", &DomainSetup::bounds) + .def("boundaryCons", &DomainSetup::boundaryCons) + .def("xExtent", &DomainSetup::xExtent) + .def("yExtent", &DomainSetup::yExtent) + .def("hasPeriodicBoundary", &DomainSetup::hasPeriodicBoundary) + .def("isValid", &DomainSetup::isValid) + .def("print", &DomainSetup::print) + .def("check", &DomainSetup::check) + .def("halveXAxis", &DomainSetup::halveXAxis) + .def("halveYAxis", &DomainSetup::halveYAxis); + // MaterialMap pybind11::class_>(module, "MaterialMap") .def(pybind11::init<>()) .def("insertNextMaterial", &MaterialMap::insertNextMaterial, - pybind11::arg("material") = Material::None) + pybind11::arg("material") = Material::Undefined) .def("getMaterialAtIdx", &MaterialMap::getMaterialAtIdx) .def("getMaterialMap", &MaterialMap::getMaterialMap) .def("size", &MaterialMap::size) @@ -1493,7 +1573,27 @@ PYBIND11_MODULE(VIENNAPS_MODULE_NAME, module) { pybind11::class_, SmartPointer>>(module, "Domain3D") // constructors .def(pybind11::init(&SmartPointer>::New<>)) + .def(pybind11::init([](SmartPointer> &domain) { + return SmartPointer>::New(domain); + }), + pybind11::arg("domain"), "Deep copy constructor.") + .def(pybind11::init( + [](T gridDelta, T xExtent, T yExtent, BoundaryType boundary) { + return SmartPointer>::New(gridDelta, xExtent, + yExtent, boundary); + }), + pybind11::arg("gridDelta"), pybind11::arg("xExtent"), + pybind11::arg("yExtent"), + pybind11::arg("boundary") = BoundaryType::REFLECTIVE_BOUNDARY) + // methods + .def("setup", + pybind11::overload_cast(&Domain::setup), + pybind11::arg("gridDelta"), pybind11::arg("xExtent"), + pybind11::arg("yExtent"), + pybind11::arg("boundary") = BoundaryType::REFLECTIVE_BOUNDARY, + "Setup the domain.") // methods + .def("getSetup", &Domain::getSetup, "Get the domain setup.") .def("deepCopy", &Domain::deepCopy) .def("insertNextLevelSet", &Domain::insertNextLevelSet, pybind11::arg("levelset"), pybind11::arg("wrapLowerLevelSet") = true, diff --git a/python/test/viennaps2d/__init__.pyi b/python/test/viennaps2d/__init__.pyi new file mode 100644 index 00000000..54dabb1e --- /dev/null +++ b/python/test/viennaps2d/__init__.pyi @@ -0,0 +1,3 @@ +from .viennaps2d import * + +def ReadConfigFile(fileName: str): ... diff --git a/python/test/viennaps2d/viennaps2d.pyi b/python/test/viennaps2d/viennaps2d.pyi new file mode 100644 index 00000000..9fe25ead --- /dev/null +++ b/python/test/viennaps2d/viennaps2d.pyi @@ -0,0 +1,675 @@ +import viennals2d.viennals2d +from _typeshed import Incomplete +from typing import Callable, ClassVar, overload + +D: int +__version__: str +version: str + +class AdvectionCallback: + domain: Incomplete + def __init__(self) -> None: ... + def applyPostAdvect(self, arg0: float) -> bool: ... + def applyPreAdvect(self, arg0: float) -> bool: ... + +class AdvectionParameters: + checkDissipation: bool + dissipationAlpha: float + ignoreVoids: bool + integrationScheme: viennals2d.viennals2d.IntegrationSchemeEnum + timeStepRatio: float + velocityOutput: bool + def __init__(self) -> None: ... + +class AnisotropicProcess(ProcessModel): + @overload + def __init__(self, materials: list[tuple[Material, float]]) -> None: ... + @overload + def __init__(self, direction100, direction010, rate100: float, rate110: float, rate111: float, rate311: float, materials: list[tuple[Material, float]]) -> None: ... + +class AtomicLayerProcess: + def __init__(self) -> None: ... + def apply(self) -> None: ... + def disableRandomSeeds(self) -> None: ... + def enableRandomSeeds(self) -> None: ... + def setCoverageTimeStep(self, arg0: float) -> None: ... + def setDesorptionRates(self, arg0: list[float]) -> None: ... + def setDomain(self, *args, **kwargs): ... + def setIntegrationScheme(self, arg0: viennals2d.viennals2d.IntegrationSchemeEnum) -> None: ... + def setNumCycles(self, arg0: int) -> None: ... + def setNumberOfRaysPerPoint(self, arg0: int) -> None: ... + def setProcessModel(self, arg0: ProcessModel) -> None: ... + def setPulseTime(self, arg0: float) -> None: ... + def setSourceDirection(self, arg0: rayTraceDirection) -> None: ... + +class BoxDistribution(ProcessModel): + @overload + def __init__(self, halfAxes, gridDelta: float, mask: viennals2d.viennals2d.Domain) -> None: ... + @overload + def __init__(self, halfAxes, gridDelta: float) -> None: ... + +class DirectionalEtching(ProcessModel): + @overload + def __init__(self, direction, directionalVelocity: float, isotropicVelocity: float = ..., maskMaterial: Material = ..., calculateVisibility: bool = ...) -> None: ... + @overload + def __init__(self, direction, directionalVelocity: float, isotropicVelocity: float, maskMaterial: list[Material], calculateVisibility: bool = ...) -> None: ... + @overload + def __init__(self, rateSets: list[RateSet]) -> None: ... + @overload + def __init__(self, rateSet: RateSet) -> None: ... + +class Domain: + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, domain: Domain) -> None: ... + @overload + def __init__(self, gridDelta: float, xExtent: float, boundary: viennals2d.viennals2d.BoundaryConditionEnum = ...) -> None: ... + def applyBooleanOperation(self, arg0: viennals2d.viennals2d.Domain, arg1: viennals2d.viennals2d.BooleanOperationEnum) -> None: ... + def clear(self) -> None: ... + def deepCopy(self, arg0: Domain) -> None: ... + def duplicateTopLevelSet(self, arg0: Material) -> None: ... + def generateCellSet(self, arg0: float, arg1: Material, arg2: bool) -> None: ... + def getBoundaryConditions(self, *args, **kwargs): ... + def getBoundingBox(self, *args, **kwargs): ... + def getCellSet(self, *args, **kwargs): ... + def getGrid(self, *args, **kwargs): ... + def getGridDelta(self) -> float: ... + def getLevelSets(self) -> list[viennals2d.viennals2d.Domain]: ... + def getMaterialMap(self, *args, **kwargs): ... + def insertNextLevelSet(self, levelset: viennals2d.viennals2d.Domain, wrapLowerLevelSet: bool = ...) -> None: ... + def insertNextLevelSetAsMaterial(self, levelSet: viennals2d.viennals2d.Domain, material: Material, wrapLowerLevelSet: bool = ...) -> None: ... + def print(self) -> None: ... + def removeLevelSet(self, arg0: int, arg1: bool) -> None: ... + def removeMaterial(self, arg0: Material) -> None: ... + def removeTopLevelSet(self) -> None: ... + def saveHullMesh(self, filename: str, wrappingLayerEpsilon: float = ...) -> None: ... + def saveLevelSetMesh(self, filename: str, width: int = ...) -> None: ... + def saveLevelSets(self, filename: str) -> None: ... + def saveSurfaceMesh(self, filename: str, addMaterialIds: bool = ...) -> None: ... + def saveVolumeMesh(self, filename: str, wrappingLayerEpsilon: float = ...) -> None: ... + def setMaterialMap(self, arg0) -> None: ... + def setup(self, gridDelta: float, xExtent: float, yExtent: float = ..., boundary: viennals2d.viennals2d.BoundaryConditionEnum = ...) -> None: ... + +class Domain3D: + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, domain: Domain3D) -> None: ... + @overload + def __init__(self, gridDelta: float, xExtent: float, yExtent: float, boundary: viennals2d.viennals2d.BoundaryConditionEnum = ...) -> None: ... + def applyBooleanOperation(self, *args, **kwargs): ... + def clear(self) -> None: ... + def deepCopy(self, arg0: Domain3D) -> None: ... + def duplicateTopLevelSet(self, arg0: Material) -> None: ... + def generateCellSet(self, arg0: float, arg1: Material, arg2: bool) -> None: ... + def getBoundaryConditions(self, *args, **kwargs): ... + def getBoundingBox(self, *args, **kwargs): ... + def getCellSet(self, *args, **kwargs): ... + def getGrid(self, *args, **kwargs): ... + def getGridDelta(self) -> float: ... + def getLevelSets(self, *args, **kwargs): ... + def getMaterialMap(self) -> MaterialMap: ... + def insertNextLevelSet(self, *args, **kwargs): ... + def insertNextLevelSetAsMaterial(self, *args, **kwargs): ... + def print(self) -> None: ... + def removeLevelSet(self, arg0: int, arg1: bool) -> None: ... + def removeMaterial(self, arg0: Material) -> None: ... + def removeTopLevelSet(self) -> None: ... + def saveHullMesh(self, filename: str, wrappingLayerEpsilon: float = ...) -> None: ... + def saveLevelSetMesh(self, filename: str, width: int = ...) -> None: ... + def saveLevelSets(self, arg0: str) -> None: ... + def saveSurfaceMesh(self, filename: str, addMaterialIds: bool = ...) -> None: ... + def saveVolumeMesh(self, filename: str, wrappingLayerEpsilon: float = ...) -> None: ... + def setMaterialMap(self, arg0: MaterialMap) -> None: ... + def setup(self, gridDelta: float, xExtent: float, yExtent: float, boundary: viennals2d.viennals2d.BoundaryConditionEnum = ...) -> None: ... + +class DomainSetup: + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, gridDelta: float, xExtent: float, yExtent: float, boundary: viennals2d.viennals2d.BoundaryConditionEnum = ...) -> None: ... + def boundaryCons(self, *args, **kwargs): ... + def bounds(self, *args, **kwargs): ... + def check(self) -> None: ... + def grid(self, *args, **kwargs): ... + def gridDelta(self) -> float: ... + def halveXAxis(self) -> None: ... + def halveYAxis(self) -> None: ... + def hasPeriodicBoundary(self) -> bool: ... + def isValid(self) -> bool: ... + def print(self) -> None: ... + def xExtent(self) -> float: ... + def yExtent(self) -> float: ... + +class Extrude: + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, inputDomain: Domain, outputDomain: Domain3D, extent, extrudeDimension: int, boundaryConditions) -> None: ... + def apply(self) -> None: ... + def setBoundaryConditions(self, arg0) -> None: ... + def setExtent(self, arg0) -> None: ... + def setExtrudeDimension(self, arg0: int) -> None: ... + def setInputDomain(self, arg0: Domain) -> None: ... + def setOutputDomain(self, arg0: Domain3D) -> None: ... + +class FaradayCageEtching(ProcessModel): + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, maskMaterials: list[Material]) -> None: ... + @overload + def __init__(self, maskMaterials: list[Material], parameters: FaradayCageParameters) -> None: ... + def getParameters(self) -> FaradayCageParameters: ... + def setParameters(self, arg0: FaradayCageParameters) -> None: ... + +class FaradayCageParameters: + cageAngle: float + ibeParams: IBEParameters + def __init__(self) -> None: ... + +class FluorocarbonEtching(ProcessModel): + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, ionFlux: float, etchantFlux: float, polyFlux: float, meanIonEnergy: float = ..., sigmaIonEnergy: float = ..., ionExponent: float = ..., deltaP: float = ..., etchStopDepth: float = ...) -> None: ... + @overload + def __init__(self, parameters: FluorocarbonParameters) -> None: ... + def getParameters(self) -> FluorocarbonParameters: ... + def setParameters(self, arg0: FluorocarbonParameters) -> None: ... + +class FluorocarbonParameters: + Ions: FluorocarbonParametersIons + Mask: FluorocarbonParametersMask + Polymer: FluorocarbonParametersPolymer + Si: FluorocarbonParametersSi + Si3N4: FluorocarbonParametersSi3N4 + SiO2: FluorocarbonParametersSiO2 + delta_p: float + etchStopDepth: float + etchantFlux: float + ionFlux: float + polyFlux: float + def __init__(self) -> None: ... + +class FluorocarbonParametersIons: + exponent: float + inflectAngle: float + meanEnergy: float + minAngle: float + n_l: float + sigmaEnergy: float + def __init__(self) -> None: ... + +class FluorocarbonParametersMask: + A_sp: float + B_sp: float + Eth_sp: float + beta_e: float + beta_p: float + rho: float + def __init__(self) -> None: ... + +class FluorocarbonParametersPolymer: + A_ie: float + Eth_ie: float + rho: float + def __init__(self) -> None: ... + +class FluorocarbonParametersSi: + A_ie: float + A_sp: float + B_sp: float + E_a: float + Eth_ie: float + Eth_sp: float + K: float + rho: float + def __init__(self) -> None: ... + +class FluorocarbonParametersSi3N4: + A_ie: float + A_sp: float + B_sp: float + E_a: float + Eth_ie: float + Eth_sp: float + K: float + rho: float + def __init__(self) -> None: ... + +class FluorocarbonParametersSiO2: + A_ie: float + A_sp: float + B_sp: float + E_a: float + Eth_ie: float + Eth_sp: float + K: float + rho: float + def __init__(self) -> None: ... + +class GeometryFactory: + def __init__(self, *args, **kwargs) -> None: ... + def makeBoxStencil(self, arg0, arg1: float, arg2: float, arg3: float) -> viennals2d.viennals2d.Domain: ... + def makeCylinderStencil(self, arg0, arg1: float, arg2: float, arg3: float) -> viennals2d.viennals2d.Domain: ... + def makeMask(self, arg0: float, arg1: float) -> viennals2d.viennals2d.Domain: ... + def makeSubstrate(self, arg0: float) -> viennals2d.viennals2d.Domain: ... + +class HoleShape: + __members__: ClassVar[dict] = ... # read-only + Full: ClassVar[HoleShape] = ... + Half: ClassVar[HoleShape] = ... + Quarter: ClassVar[HoleShape] = ... + __entries: ClassVar[dict] = ... + def __init__(self, value: int) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + def __ne__(self, other: object) -> bool: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +class IBEParameters: + exponent: float + inflectAngle: float + meanEnergy: float + minAngle: float + n_l: float + planeWaferRate: float + redepositionRate: float + redepositionThreshold: float + sigmaEnergy: float + thresholdEnergy: float + tiltAngle: float + yieldFunction: Callable[[float], float] + def __init__(self) -> None: ... + +class IonBeamEtching(ProcessModel): + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, maskMaterials: list[Material]) -> None: ... + @overload + def __init__(self, maskMaterials: list[Material], parameters: IBEParameters) -> None: ... + def getParameters(self) -> IBEParameters: ... + def setParameters(self, arg0: IBEParameters) -> None: ... + +class IsotropicProcess(ProcessModel): + @overload + def __init__(self, rate: float = ..., maskMaterial: Material = ...) -> None: ... + @overload + def __init__(self, rate: float, maskMaterial: list[Material]) -> None: ... + +class Length: + def __init__(self, *args, **kwargs) -> None: ... + def convertAngstrom(self) -> float: ... + def convertCentimeter(self) -> float: ... + def convertMeter(self) -> float: ... + def convertMicrometer(self) -> float: ... + def convertMillimeter(self) -> float: ... + def convertNanometer(self) -> float: ... + @staticmethod + def getInstance() -> Length: ... + @staticmethod + def setUnit(arg0: str) -> None: ... + def toShortString(self) -> str: ... + def toString(self) -> str: ... + +class LogLevel: + __members__: ClassVar[dict] = ... # read-only + DEBUG: ClassVar[LogLevel] = ... + ERROR: ClassVar[LogLevel] = ... + INFO: ClassVar[LogLevel] = ... + INTERMEDIATE: ClassVar[LogLevel] = ... + TIMING: ClassVar[LogLevel] = ... + WARNING: ClassVar[LogLevel] = ... + __entries: ClassVar[dict] = ... + def __init__(self, value: int) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + def __ne__(self, other: object) -> bool: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +class Logger: + def __init__(self, *args, **kwargs) -> None: ... + def addDebug(self, arg0: str) -> Logger: ... + def addError(self, s: str, shouldAbort: bool = ...) -> Logger: ... + def addInfo(self, arg0: str) -> Logger: ... + @overload + def addTiming(self, arg0: str, arg1: float) -> Logger: ... + @overload + def addTiming(self, arg0: str, arg1: float, arg2: float) -> Logger: ... + def addWarning(self, arg0: str) -> Logger: ... + @staticmethod + def getInstance() -> Logger: ... + @staticmethod + def getLogLevel() -> int: ... + def print(self) -> None: ... + @staticmethod + def setLogLevel(arg0: LogLevel) -> None: ... + +class MakeFin: + def __init__(self, *args, **kwargs) -> None: ... + def apply(self) -> None: ... + +class MakeHole: + def __init__(self, *args, **kwargs) -> None: ... + def apply(self) -> None: ... + +class MakePlane: + def __init__(self, *args, **kwargs) -> None: ... + def apply(self) -> None: ... + +class MakeStack: + def __init__(self, *args, **kwargs) -> None: ... + def apply(self) -> None: ... + def getHeight(self) -> float: ... + def getTopLayer(self) -> int: ... + +class MakeTrench: + def __init__(self, *args, **kwargs) -> None: ... + def apply(self) -> None: ... + +class Material: + __members__: ClassVar[dict] = ... # read-only + Air: ClassVar[Material] = ... + Al2O3: ClassVar[Material] = ... + Cu: ClassVar[Material] = ... + Dielectric: ClassVar[Material] = ... + GAS: ClassVar[Material] = ... + GaN: ClassVar[Material] = ... + Mask: ClassVar[Material] = ... + Metal: ClassVar[Material] = ... + PolySi: ClassVar[Material] = ... + Polymer: ClassVar[Material] = ... + Si: ClassVar[Material] = ... + Si3N4: ClassVar[Material] = ... + SiC: ClassVar[Material] = ... + SiGe: ClassVar[Material] = ... + SiN: ClassVar[Material] = ... + SiO2: ClassVar[Material] = ... + SiON: ClassVar[Material] = ... + TiN: ClassVar[Material] = ... + Undefined: ClassVar[Material] = ... + W: ClassVar[Material] = ... + __entries: ClassVar[dict] = ... + def __init__(self, value: int) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + def __ne__(self, other: object) -> bool: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +class MaterialMap: + def __init__(self) -> None: ... + def getMaterialAtIdx(self, arg0: int) -> Material: ... + def getMaterialMap(self) -> viennals2d.viennals2d.MaterialMap: ... + @staticmethod + def getMaterialName(arg0: Material) -> str: ... + def insertNextMaterial(self, material: Material = ...) -> None: ... + @staticmethod + def isMaterial(arg0: float, arg1: Material) -> bool: ... + @staticmethod + def mapToMaterial(arg0: float) -> Material: ... + def size(self) -> int: ... + +class MultiParticleProcess(ProcessModel): + def __init__(self) -> None: ... + def addIonParticle(self, sourcePower: float, thetaRMin: float = ..., thetaRMax: float = ..., minAngle: float = ..., B_sp: float = ..., meanEnergy: float = ..., sigmaEnergy: float = ..., thresholdEnergy: float = ..., inflectAngle: float = ..., n: float = ..., label: str = ...) -> None: ... + @overload + def addNeutralParticle(self, stickingProbability: float, label: str = ...) -> None: ... + @overload + def addNeutralParticle(self, materialSticking: dict[Material, float], defaultStickingProbability: float = ..., label: str = ...) -> None: ... + def setRateFunction(self, arg0: Callable[[list[float], Material], float]) -> None: ... + +class NormalizationType: + __members__: ClassVar[dict] = ... # read-only + MAX: ClassVar[NormalizationType] = ... + SOURCE: ClassVar[NormalizationType] = ... + __entries: ClassVar[dict] = ... + def __init__(self, value: int) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + def __ne__(self, other: object) -> bool: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +class OxideRegrowth(ProcessModel): + def __init__(self, nitrideEtchRate: float, oxideEtchRate: float, redepositionRate: float, redepositionThreshold: float, redepositionTimeInt: float, diffusionCoefficient: float, sinkStrength: float, scallopVelocity: float, centerVelocity: float, topHeight: float, centerWidth: float, stabilityFactor: float) -> None: ... + +class Particle: + def __init__(self, *args, **kwargs) -> None: ... + def getLocalDataLabels(self) -> list[str]: ... + def getSourceDistributionPower(self) -> float: ... + def initNew(self, *args, **kwargs): ... + def surfaceCollision(self, *args, **kwargs): ... + def surfaceReflection(self, *args, **kwargs): ... + +class Planarize: + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, geometry: Domain, cutoffHeight: float = ...) -> None: ... + def apply(self) -> None: ... + def setCutoffPosition(self, arg0: float) -> None: ... + def setDomain(self, arg0: Domain) -> None: ... + +class Process: + def __init__(self) -> None: ... + def apply(self) -> None: ... + def calculateFlux(self) -> viennals2d.viennals2d.Mesh: ... + def disableAdvectionVelocityOutput(self) -> None: ... + def disableFluxSmoothing(self) -> None: ... + def disableRandomSeeds(self) -> None: ... + def enableAdvectionVelocityOutput(self) -> None: ... + def enableFluxSmoothing(self) -> None: ... + def enableRandomSeeds(self) -> None: ... + def getAdvectionParameters(self) -> AdvectionParameters: ... + def getProcessDuration(self) -> float: ... + def getRayTracingParameters(self) -> RayTracingParameters: ... + def setAdvectionParameters(self, arg0: AdvectionParameters) -> None: ... + def setDomain(self, *args, **kwargs): ... + def setIntegrationScheme(self, arg0: viennals2d.viennals2d.IntegrationSchemeEnum) -> None: ... + def setMaxCoverageInitIterations(self, arg0: int) -> None: ... + def setNumberOfRaysPerPoint(self, arg0: int) -> None: ... + def setProcessDuration(self, arg0: float) -> None: ... + def setProcessModel(self, arg0: ProcessModel) -> None: ... + def setRayTracingDiskRadius(self, arg0: float) -> None: ... + def setRayTracingParameters(self, arg0: RayTracingParameters) -> None: ... + def setSourceDirection(self, arg0: rayTraceDirection) -> None: ... + def setTimeStepRatio(self, arg0: float) -> None: ... + +class ProcessModel: + def __init__(self) -> None: ... + def getAdvectionCallback(self, *args, **kwargs): ... + def getGeometricModel(self, *args, **kwargs): ... + def getParticleLogSize(self, arg0: int) -> int: ... + def getParticleTypes(self, *args, **kwargs): ... + def getPrimaryDirection(self, *args, **kwargs): ... + def getProcessName(self) -> str | None: ... + def getSurfaceModel(self, *args, **kwargs): ... + def getVelocityField(self, *args, **kwargs): ... + def insertNextParticleType(self, arg0) -> None: ... + def setAdvectionCallback(self, *args, **kwargs): ... + def setGeometricModel(self, *args, **kwargs): ... + def setPrimaryDirection(self, arg0) -> None: ... + def setProcessName(self, arg0: str) -> None: ... + def setSurfaceModel(self, arg0) -> None: ... + def setVelocityField(self, *args, **kwargs): ... + +class ProcessParams: + def __init__(self) -> None: ... + @overload + def getScalarData(self, arg0: int) -> float: ... + @overload + def getScalarData(self, arg0: int) -> float: ... + @overload + def getScalarData(self, arg0: str) -> float: ... + @overload + def getScalarData(self) -> list[float]: ... + @overload + def getScalarData(self) -> list[float]: ... + def getScalarDataIndex(self, arg0: str) -> int: ... + def getScalarDataLabel(self, arg0: int) -> str: ... + def insertNextScalar(self, arg0: float, arg1: str) -> None: ... + +class RateSet: + calculateVisibility: bool + direction: Incomplete + directionalVelocity: float + isotropicVelocity: float + maskMaterials: list[Material] + def __init__(self, direction=..., directionalVelocity: float = ..., isotropicVelocity: float = ..., maskMaterials: list[Material] = ..., calculateVisibility: bool = ...) -> None: ... + def print(self) -> None: ... + +class RayTracingParameters: + diskRadius: float + ignoreFluxBoundaries: bool + normalizationType: NormalizationType + raysPerPoint: int + smoothingNeighbors: int + sourceDirection: rayTraceDirection + useRandomSeeds: bool + def __init__(self) -> None: ... + +class SF6O2Etching(ProcessModel): + @overload + def __init__(self) -> None: ... + @overload + def __init__(self, ionFlux: float, etchantFlux: float, oxygenFlux: float, meanIonEnergy: float = ..., sigmaIonEnergy: float = ..., ionExponent: float = ..., oxySputterYield: float = ..., etchStopDepth: float = ...) -> None: ... + @overload + def __init__(self, parameters: SF6O2Parameters) -> None: ... + def getParameters(self) -> SF6O2Parameters: ... + def setParameters(self, arg0: SF6O2Parameters) -> None: ... + +class SF6O2Parameters: + Ions: SF6O2ParametersIons + Mask: SF6O2ParametersMask + Passivation: SF6O2ParametersPassivation + Si: SF6O2ParametersSi + beta_F: dict[int, float] + beta_O: dict[int, float] + etchStopDepth: float + etchantFlux: float + fluxIncludeSticking: bool + ionFlux: float + oxygenFlux: float + def __init__(self) -> None: ... + +class SF6O2ParametersIons: + exponent: float + inflectAngle: float + meanEnergy: float + minAngle: float + n_l: float + sigmaEnergy: float + def __init__(self) -> None: ... + +class SF6O2ParametersMask: + A_sp: float + B_sp: float + Eth_sp: float + rho: float + def __init__(self) -> None: ... + +class SF6O2ParametersPassivation: + A_ie: float + Eth_ie: float + def __init__(self) -> None: ... + +class SF6O2ParametersSi: + A_ie: float + A_sp: float + B_ie: float + B_sp: float + Eth_ie: float + Eth_sp: float + beta_sigma: float + k_sigma: float + rho: float + theta_g_ie: float + theta_g_sp: float + def __init__(self) -> None: ... + +class SingleParticleALD(ProcessModel): + def __init__(self, stickingProbability: float, numCycles: float, growthPerCycle: float, totalCycles: float, coverageTimeStep: float, evFlux: float, inFlux: float, s0: float, gasMFP: float) -> None: ... + +class SingleParticleProcess(ProcessModel): + @overload + def __init__(self, rate: float = ..., stickingProbability: float = ..., sourceExponent: float = ..., maskMaterial: Material = ...) -> None: ... + @overload + def __init__(self, rate: float, stickingProbability: float, sourceExponent: float, maskMaterials: list[Material]) -> None: ... + @overload + def __init__(self, materialRates: dict[Material, float], stickingProbability: float, sourceExponent: float) -> None: ... + +class SphereDistribution(ProcessModel): + @overload + def __init__(self, radius: float, gridDelta: float, mask: viennals2d.viennals2d.Domain) -> None: ... + @overload + def __init__(self, radius: float, gridDelta: float) -> None: ... + +class TEOSDeposition(ProcessModel): + def __init__(self, stickingProbabilityP1: float, rateP1: float, orderP1: float, stickingProbabilityP2: float = ..., rateP2: float = ..., orderP2: float = ...) -> None: ... + +class TEOSPECVD(ProcessModel): + def __init__(self, stickingProbabilityRadical: float, depositionRateRadical: float, depositionRateIon: float, exponentIon: float, stickingProbabilityIon: float = ..., reactionOrderRadical: float = ..., reactionOrderIon: float = ..., minAngleIon: float = ...) -> None: ... + +class Time: + def __init__(self, *args, **kwargs) -> None: ... + def convertMillisecond(self) -> float: ... + def convertMinute(self) -> float: ... + def convertSecond(self) -> float: ... + @staticmethod + def getInstance() -> Time: ... + @staticmethod + def setUnit(arg0: str) -> None: ... + def toShortString(self) -> str: ... + def toString(self) -> str: ... + +class ToDiskMesh: + @overload + def __init__(self, domain: Domain, mesh: viennals2d.viennals2d.Mesh) -> None: ... + @overload + def __init__(self) -> None: ... + def setDomain(self, arg0: Domain) -> None: ... + def setMesh(self, arg0: viennals2d.viennals2d.Mesh) -> None: ... + +class rayTraceDirection: + __members__: ClassVar[dict] = ... # read-only + NEG_X: ClassVar[rayTraceDirection] = ... + NEG_Y: ClassVar[rayTraceDirection] = ... + NEG_Z: ClassVar[rayTraceDirection] = ... + POS_X: ClassVar[rayTraceDirection] = ... + POS_Y: ClassVar[rayTraceDirection] = ... + POS_Z: ClassVar[rayTraceDirection] = ... + __entries: ClassVar[dict] = ... + def __init__(self, value: int) -> None: ... + def __eq__(self, other: object) -> bool: ... + def __hash__(self) -> int: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + def __ne__(self, other: object) -> bool: ... + @property + def name(self) -> str: ... + @property + def value(self) -> int: ... + +def setNumThreads(arg0: int) -> None: ... diff --git a/python/viennaps2d/viennaps2d.pyi b/python/viennaps2d/viennaps2d.pyi index 3b5a1980..7791234d 100644 --- a/python/viennaps2d/viennaps2d.pyi +++ b/python/viennaps2d/viennaps2d.pyi @@ -1,11 +1,13 @@ +import viennals2d.viennals2d from _typeshed import Incomplete from typing import Callable, ClassVar, overload D: int __version__: str +version: str class AdvectionCallback: - domain: Incomplete + domain: Domain def __init__(self) -> None: ... def applyPostAdvect(self, arg0: float) -> bool: ... def applyPreAdvect(self, arg0: float) -> bool: ... @@ -14,7 +16,7 @@ class AdvectionParameters: checkDissipation: bool dissipationAlpha: float ignoreVoids: bool - integrationScheme: Incomplete + integrationScheme: viennals2d.viennals2d.IntegrationSchemeEnum timeStepRatio: float velocityOutput: bool def __init__(self) -> None: ... @@ -42,7 +44,9 @@ class AtomicLayerProcess: def setCoverageTimeStep(self, arg0: float) -> None: ... def setDesorptionRates(self, arg0: list[float]) -> None: ... def setDomain(self, *args, **kwargs): ... - def setIntegrationScheme(self, arg0) -> None: ... + def setIntegrationScheme( + self, arg0: viennals2d.viennals2d.IntegrationSchemeEnum + ) -> None: ... def setNumCycles(self, arg0: int) -> None: ... def setNumberOfRaysPerPoint(self, arg0: int) -> None: ... def setProcessModel(self, arg0: ProcessModel) -> None: ... @@ -50,13 +54,18 @@ class AtomicLayerProcess: def setSourceDirection(self, arg0: rayTraceDirection) -> None: ... class BoxDistribution(ProcessModel): + @overload + def __init__( + self, halfAxes, gridDelta: float, mask: viennals2d.viennals2d.Domain + ) -> None: ... + @overload def __init__(self, halfAxes, gridDelta: float) -> None: ... class DirectionalEtching(ProcessModel): @overload def __init__( self, - direction: list[float], + direction, directionalVelocity: float, isotropicVelocity: float = ..., maskMaterial: Material = ..., @@ -65,10 +74,10 @@ class DirectionalEtching(ProcessModel): @overload def __init__( self, - direction: list[float], + direction, directionalVelocity: float, - isotropicVelocity: float = ..., - maskMaterial: list[Material] = ..., + isotropicVelocity: float, + maskMaterial: list[Material], calculateVisibility: bool = ..., ) -> None: ... @overload @@ -77,21 +86,43 @@ class DirectionalEtching(ProcessModel): def __init__(self, rateSet: RateSet) -> None: ... class Domain: + @overload def __init__(self) -> None: ... - def applyBooleanOperation(self, *args, **kwargs): ... + @overload + def __init__(self, domain: Domain) -> None: ... + @overload + def __init__( + self, + gridDelta: float, + xExtent: float, + boundary: viennals2d.viennals2d.BoundaryConditionEnum = ..., + ) -> None: ... + def applyBooleanOperation( + self, + arg0: viennals2d.viennals2d.Domain, + arg1: viennals2d.viennals2d.BooleanOperationEnum, + ) -> None: ... def clear(self) -> None: ... def deepCopy(self, arg0: Domain) -> None: ... def duplicateTopLevelSet(self, arg0: Material) -> None: ... def generateCellSet(self, arg0: float, arg1: Material, arg2: bool) -> None: ... def getBoundaryConditions(self, *args, **kwargs): ... - def getBoundingBox(self) -> list[list[float], list[float]]: ... - def getCellSet(self): ... - def getGrid(self): ... + def getBoundingBox(self, *args, **kwargs): ... + def getCellSet(self, *args, **kwargs): ... + def getGrid(self, *args, **kwargs): ... def getGridDelta(self) -> float: ... - def getLevelSets(self, *args, **kwargs): ... + def getLevelSets(self) -> list[viennals2d.viennals2d.Domain]: ... def getMaterialMap(self, *args, **kwargs): ... - def insertNextLevelSet(self, *args, **kwargs): ... - def insertNextLevelSetAsMaterial(self, *args, **kwargs): ... + def getSetup(self, *args, **kwargs): ... + def insertNextLevelSet( + self, levelset: viennals2d.viennals2d.Domain, wrapLowerLevelSet: bool = ... + ) -> None: ... + def insertNextLevelSetAsMaterial( + self, + levelSet: viennals2d.viennals2d.Domain, + material: Material, + wrapLowerLevelSet: bool = ..., + ) -> None: ... def print(self) -> None: ... def removeLevelSet(self, arg0: int, arg1: bool) -> None: ... def removeMaterial(self, arg0: Material) -> None: ... @@ -105,22 +136,41 @@ class Domain: def saveVolumeMesh( self, filename: str, wrappingLayerEpsilon: float = ... ) -> None: ... - def setMaterialMap(self, arg0: MaterialMap) -> None: ... + def setMaterialMap(self, arg0) -> None: ... + def setup( + self, + gridDelta: float, + xExtent: float, + yExtent: float = ..., + boundary: viennals2d.viennals2d.BoundaryConditionEnum = ..., + ) -> None: ... class Domain3D: + @overload def __init__(self) -> None: ... + @overload + def __init__(self, domain: Domain3D) -> None: ... + @overload + def __init__( + self, + gridDelta: float, + xExtent: float, + yExtent: float, + boundary: viennals2d.viennals2d.BoundaryConditionEnum = ..., + ) -> None: ... def applyBooleanOperation(self, *args, **kwargs): ... def clear(self) -> None: ... def deepCopy(self, arg0: Domain3D) -> None: ... def duplicateTopLevelSet(self, arg0: Material) -> None: ... def generateCellSet(self, arg0: float, arg1: Material, arg2: bool) -> None: ... def getBoundaryConditions(self, *args, **kwargs): ... - def getBoundingBox(self) -> list[list[float], list[float]]: ... - def getCellSet(self): ... - def getGrid(self): ... + def getBoundingBox(self, *args, **kwargs): ... + def getCellSet(self, *args, **kwargs): ... + def getGrid(self, *args, **kwargs): ... def getGridDelta(self) -> float: ... def getLevelSets(self, *args, **kwargs): ... def getMaterialMap(self) -> MaterialMap: ... + def getSetup(self, *args, **kwargs): ... def insertNextLevelSet(self, *args, **kwargs): ... def insertNextLevelSetAsMaterial(self, *args, **kwargs): ... def print(self) -> None: ... @@ -137,6 +187,37 @@ class Domain3D: self, filename: str, wrappingLayerEpsilon: float = ... ) -> None: ... def setMaterialMap(self, arg0: MaterialMap) -> None: ... + def setup( + self, + gridDelta: float, + xExtent: float, + yExtent: float, + boundary: viennals2d.viennals2d.BoundaryConditionEnum = ..., + ) -> None: ... + +class DomainSetup: + @overload + def __init__(self) -> None: ... + @overload + def __init__( + self, + gridDelta: float, + xExtent: float, + yExtent: float, + boundary: viennals2d.viennals2d.BoundaryConditionEnum = ..., + ) -> None: ... + def boundaryCons(self, *args, **kwargs): ... + def bounds(self, *args, **kwargs): ... + def check(self) -> None: ... + def grid(self, *args, **kwargs): ... + def gridDelta(self) -> float: ... + def halveXAxis(self) -> None: ... + def halveYAxis(self) -> None: ... + def hasPeriodicBoundary(self) -> bool: ... + def isValid(self) -> bool: ... + def print(self) -> None: ... + def xExtent(self) -> float: ... + def yExtent(self) -> float: ... class Extrude: @overload @@ -265,6 +346,17 @@ class FluorocarbonParametersSiO2: rho: float def __init__(self) -> None: ... +class GeometryFactory: + def __init__(self, *args, **kwargs) -> None: ... + def makeBoxStencil( + self, position, width: float, height: float, angle: float + ) -> viennals2d.viennals2d.Domain: ... + def makeCylinderStencil( + self, position, radius: float, height: float, angle: float + ) -> viennals2d.viennals2d.Domain: ... + def makeMask(self, base: float, height: float) -> viennals2d.viennals2d.Domain: ... + def makeSubstrate(self, base: float) -> viennals2d.viennals2d.Domain: ... + class HoleShape: __members__: ClassVar[dict] = ... # read-only Full: ClassVar[HoleShape] = ... @@ -289,8 +381,8 @@ class IBEParameters: minAngle: float n_l: float planeWaferRate: float - redepositionThreshold: float redepositionRate: float + redepositionThreshold: float sigmaEnergy: float thresholdEnergy: float tiltAngle: float @@ -369,6 +461,20 @@ class Logger: def setLogLevel(arg0: LogLevel) -> None: ... class MakeFin: + @overload + def __init__( + self, + domain: Domain, + finWidth: float, + finHeight: float, + finTaperAngle: float = 0.0, + maskHeight: float = 0.0, + maskTaperAngle: float = 0.0, + halfFin: bool = False, + material: Material = Material.Si, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -381,11 +487,25 @@ class MakeFin: baseHeight: float = 0.0, periodicBoundary: bool = False, makeMask: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, ) -> None: ... def apply(self) -> None: ... class MakeHole: + @overload + def __init__( + self, + domain: Domain, + holeRadius: float, + holeDepth: float, + holeTaperAngle: float = 0.0, + maskHeight: float = 0.0, + maskTaperAngle: float = 0.0, + holeShape: HoleShape = HoleShape.Full, + material: Material = Material.Si, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -398,7 +518,8 @@ class MakeHole: baseHeight: float = 0.0, periodicBoundary: bool = False, makeMask: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, + holeShape: HoleShape = HoleShape.Full, ) -> None: ... def apply(self) -> None: ... @@ -412,18 +533,34 @@ class MakePlane: yExtent: float, height: float = 0.0, periodicBoundary: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, ) -> None: ... @overload def __init__( self, domain: Domain, height: float = 0.0, - material: Material = Material.Undefined, + material: Material = Material.Si, + addToExisting: bool = False, ) -> None: ... def apply(self) -> None: ... class MakeStack: + @overload + def __init__( + self, + domain: Domain, + numLayers: int, + layerHeight: float, + substrateHeight: float = 0, + holeRadius: float = 0, + trenchWidth: float = 0, + maskHeight: float = 0, + taperAngle: float = 0, + halfStack: bool = False, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -443,6 +580,20 @@ class MakeStack: def getTopLayer(self) -> int: ... class MakeTrench: + @overload + def __init__( + self, + domain: Domain, + trenchWidth: float, + trenchDepth: float, + trenchTaperAngle: float = 0.0, + maskHeight: float = 0.0, + maskTaperAngle: float = 0.0, + halfTrench: bool = False, + material: Material = Material.Si, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -455,7 +606,7 @@ class MakeTrench: baseHeight: float = 0.0, periodicBoundary: bool = False, makeMask: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, ) -> None: ... def apply(self) -> None: ... @@ -496,7 +647,7 @@ class Material: class MaterialMap: def __init__(self) -> None: ... def getMaterialAtIdx(self, arg0: int) -> Material: ... - def getMaterialMap(self, *args, **kwargs): ... + def getMaterialMap(self) -> viennals2d.viennals2d.MaterialMap: ... @staticmethod def getMaterialName(arg0: Material) -> str: ... def insertNextMaterial(self, material: Material = ...) -> None: ... @@ -590,7 +741,7 @@ class Planarize: class Process: def __init__(self) -> None: ... def apply(self) -> None: ... - def calculateFlux(self): ... + def calculateFlux(self) -> viennals2d.viennals2d.Mesh: ... def disableAdvectionVelocityOutput(self) -> None: ... def disableFluxSmoothing(self) -> None: ... def disableRandomSeeds(self) -> None: ... @@ -601,8 +752,10 @@ class Process: def getProcessDuration(self) -> float: ... def getRayTracingParameters(self) -> RayTracingParameters: ... def setAdvectionParameters(self, arg0: AdvectionParameters) -> None: ... - def setDomain(self, arg0: Domain): ... - def setIntegrationScheme(self, arg0) -> None: ... + def setDomain(self, *args, **kwargs): ... + def setIntegrationScheme( + self, arg0: viennals2d.viennals2d.IntegrationSchemeEnum + ) -> None: ... def setMaxCoverageInitIterations(self, arg0: int) -> None: ... def setNumberOfRaysPerPoint(self, arg0: int) -> None: ... def setProcessDuration(self, arg0: float) -> None: ... @@ -648,13 +801,13 @@ class ProcessParams: class RateSet: calculateVisibility: bool - direction: list[float] + direction: Incomplete directionalVelocity: float isotropicVelocity: float maskMaterials: list[Material] def __init__( self, - direction: list[float] = ..., + direction=..., directionalVelocity: float = ..., isotropicVelocity: float = ..., maskMaterials: list[Material] = ..., @@ -781,6 +934,11 @@ class SingleParticleProcess(ProcessModel): ) -> None: ... class SphereDistribution(ProcessModel): + @overload + def __init__( + self, radius: float, gridDelta: float, mask: viennals2d.viennals2d.Domain + ) -> None: ... + @overload def __init__(self, radius: float, gridDelta: float) -> None: ... class TEOSDeposition(ProcessModel): @@ -821,11 +979,11 @@ class Time: class ToDiskMesh: @overload - def __init__(self, domain: Domain, mesh) -> None: ... + def __init__(self, domain: Domain, mesh: viennals2d.viennals2d.Mesh) -> None: ... @overload def __init__(self) -> None: ... def setDomain(self, arg0: Domain) -> None: ... - def setMesh(self, arg0) -> None: ... + def setMesh(self, arg0: viennals2d.viennals2d.Mesh) -> None: ... class rayTraceDirection: __members__: ClassVar[dict] = ... # read-only diff --git a/python/viennaps3d/viennaps3d.pyi b/python/viennaps3d/viennaps3d.pyi index 63ecfaba..79be024f 100644 --- a/python/viennaps3d/viennaps3d.pyi +++ b/python/viennaps3d/viennaps3d.pyi @@ -1,11 +1,13 @@ +import viennals3d.viennals3d from _typeshed import Incomplete from typing import Callable, ClassVar, overload D: int __version__: str +version: str class AdvectionCallback: - domain: Incomplete + domain: Domain def __init__(self) -> None: ... def applyPostAdvect(self, arg0: float) -> bool: ... def applyPreAdvect(self, arg0: float) -> bool: ... @@ -14,7 +16,7 @@ class AdvectionParameters: checkDissipation: bool dissipationAlpha: float ignoreVoids: bool - integrationScheme: Incomplete + integrationScheme: viennals3d.viennals3d.IntegrationSchemeEnum timeStepRatio: float velocityOutput: bool def __init__(self) -> None: ... @@ -42,7 +44,9 @@ class AtomicLayerProcess: def setCoverageTimeStep(self, arg0: float) -> None: ... def setDesorptionRates(self, arg0: list[float]) -> None: ... def setDomain(self, *args, **kwargs): ... - def setIntegrationScheme(self, arg0) -> None: ... + def setIntegrationScheme( + self, arg0: viennals3d.viennals3d.IntegrationSchemeEnum + ) -> None: ... def setNumCycles(self, arg0: int) -> None: ... def setNumberOfRaysPerPoint(self, arg0: int) -> None: ... def setProcessModel(self, arg0: ProcessModel) -> None: ... @@ -50,6 +54,11 @@ class AtomicLayerProcess: def setSourceDirection(self, arg0: rayTraceDirection) -> None: ... class BoxDistribution(ProcessModel): + @overload + def __init__( + self, halfAxes, gridDelta: float, mask: viennals3d.viennals3d.Domain + ) -> None: ... + @overload def __init__(self, halfAxes, gridDelta: float) -> None: ... class DirectionalEtching(ProcessModel): @@ -67,8 +76,8 @@ class DirectionalEtching(ProcessModel): self, direction, directionalVelocity: float, - isotropicVelocity: float = ..., - maskMaterial: list[Material] = ..., + isotropicVelocity: float, + maskMaterial: list[Material], calculateVisibility: bool = ..., ) -> None: ... @overload @@ -77,21 +86,44 @@ class DirectionalEtching(ProcessModel): def __init__(self, rateSet: RateSet) -> None: ... class Domain: + @overload def __init__(self) -> None: ... - def applyBooleanOperation(self, *args, **kwargs): ... + @overload + def __init__(self, domain: Domain) -> None: ... + @overload + def __init__( + self, + gridDelta: float, + xExtent: float, + yExtent: float, + boundary: viennals3d.viennals3d.BoundaryConditionEnum = ..., + ) -> None: ... + def applyBooleanOperation( + self, + arg0: viennals3d.viennals3d.Domain, + arg1: viennals3d.viennals3d.BooleanOperationEnum, + ) -> None: ... def clear(self) -> None: ... def deepCopy(self, arg0: Domain) -> None: ... def duplicateTopLevelSet(self, arg0: Material) -> None: ... def generateCellSet(self, arg0: float, arg1: Material, arg2: bool) -> None: ... def getBoundaryConditions(self, *args, **kwargs): ... - def getBoundingBox(self) -> list[list[float], list[float]]: ... - def getCellSet(self): ... - def getGrid(self): ... + def getBoundingBox(self, *args, **kwargs): ... + def getCellSet(self, *args, **kwargs): ... + def getGrid(self, *args, **kwargs): ... def getGridDelta(self) -> float: ... - def getLevelSets(self, *args, **kwargs): ... + def getLevelSets(self) -> list[viennals3d.viennals3d.Domain]: ... def getMaterialMap(self, *args, **kwargs): ... - def insertNextLevelSet(self, *args, **kwargs): ... - def insertNextLevelSetAsMaterial(self, *args, **kwargs): ... + def getSetup(self, *args, **kwargs): ... + def insertNextLevelSet( + self, levelset: viennals3d.viennals3d.Domain, wrapLowerLevelSet: bool = ... + ) -> None: ... + def insertNextLevelSetAsMaterial( + self, + levelSet: viennals3d.viennals3d.Domain, + material: Material, + wrapLowerLevelSet: bool = ..., + ) -> None: ... def print(self) -> None: ... def removeLevelSet(self, arg0: int, arg1: bool) -> None: ... def removeMaterial(self, arg0: Material) -> None: ... @@ -105,7 +137,38 @@ class Domain: def saveVolumeMesh( self, filename: str, wrappingLayerEpsilon: float = ... ) -> None: ... - def setMaterialMap(self, arg0: MaterialMap) -> None: ... + def setMaterialMap(self, arg0) -> None: ... + def setup( + self, + gridDelta: float, + xExtent: float, + yExtent: float = ..., + boundary: viennals3d.viennals3d.BoundaryConditionEnum = ..., + ) -> None: ... + +class DomainSetup: + @overload + def __init__(self) -> None: ... + @overload + def __init__( + self, + gridDelta: float, + xExtent: float, + yExtent: float, + boundary: viennals3d.viennals3d.BoundaryConditionEnum = ..., + ) -> None: ... + def boundaryCons(self, *args, **kwargs): ... + def bounds(self, *args, **kwargs): ... + def check(self) -> None: ... + def grid(self, *args, **kwargs): ... + def gridDelta(self) -> float: ... + def halveXAxis(self) -> None: ... + def halveYAxis(self) -> None: ... + def hasPeriodicBoundary(self) -> bool: ... + def isValid(self) -> bool: ... + def print(self) -> None: ... + def xExtent(self) -> float: ... + def yExtent(self) -> float: ... class FaradayCageEtching(ProcessModel): @overload @@ -222,10 +285,12 @@ class GDSGeometry: def __init__(self, gridDelta: float) -> None: ... def getBounds(self, *args, **kwargs): ... def layerToLevelSet( - self, arg0: int, arg1: float, arg2: float, arg3: bool = ... - ): ... + self, layer: int, baseHeight: float, height: float, mask: bool = ... + ) -> viennals3d.viennals3d.Domain: ... def print(self) -> None: ... - def setBoundaryConditions(self, arg0) -> None: ... + def setBoundaryConditions( + self, arg0: list[viennals3d.viennals3d.BoundaryConditionEnum] + ) -> None: ... def setBoundaryPadding(self, arg0: float, arg1: float) -> None: ... def setGridDelta(self, arg0: float) -> None: ... @@ -238,6 +303,17 @@ class GDSReader: def setFileName(self, arg0: str) -> None: ... def setGeometry(self, arg0: GDSGeometry) -> None: ... +class GeometryFactory: + def __init__(self, *args, **kwargs) -> None: ... + def makeBoxStencil( + self, position, width: float, height: float, angle: float + ) -> viennals3d.viennals3d.Domain: ... + def makeCylinderStencil( + self, position, radius: float, height: float, angle: float + ) -> viennals3d.viennals3d.Domain: ... + def makeMask(self, base: float, height: float) -> viennals3d.viennals3d.Domain: ... + def makeSubstrate(self, base: float) -> viennals3d.viennals3d.Domain: ... + class HoleShape: __members__: ClassVar[dict] = ... # read-only Full: ClassVar[HoleShape] = ... @@ -262,8 +338,8 @@ class IBEParameters: minAngle: float n_l: float planeWaferRate: float - redepositionThreshold: float redepositionRate: float + redepositionThreshold: float sigmaEnergy: float thresholdEnergy: float tiltAngle: float @@ -342,6 +418,20 @@ class Logger: def setLogLevel(arg0: LogLevel) -> None: ... class MakeFin: + @overload + def __init__( + self, + domain: Domain, + finWidth: float, + finHeight: float, + finTaperAngle: float = 0.0, + maskHeight: float = 0.0, + maskTaperAngle: float = 0.0, + halfFin: bool = False, + material: Material = Material.Si, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -354,11 +444,25 @@ class MakeFin: baseHeight: float = 0.0, periodicBoundary: bool = False, makeMask: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, ) -> None: ... def apply(self) -> None: ... class MakeHole: + @overload + def __init__( + self, + domain: Domain, + holeRadius: float, + holeDepth: float, + holeTaperAngle: float = 0.0, + maskHeight: float = 0.0, + maskTaperAngle: float = 0.0, + holeShape: HoleShape = HoleShape.Full, + material: Material = Material.Si, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -371,7 +475,8 @@ class MakeHole: baseHeight: float = 0.0, periodicBoundary: bool = False, makeMask: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, + holeShape: HoleShape = HoleShape.Full, ) -> None: ... def apply(self) -> None: ... @@ -385,18 +490,34 @@ class MakePlane: yExtent: float, height: float = 0.0, periodicBoundary: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, ) -> None: ... @overload def __init__( self, domain: Domain, height: float = 0.0, - material: Material = Material.Undefined, + material: Material = Material.Si, + addToExisting: bool = False, ) -> None: ... def apply(self) -> None: ... class MakeStack: + @overload + def __init__( + self, + domain: Domain, + numLayers: int, + layerHeight: float, + substrateHeight: float = 0, + holeRadius: float = 0, + trenchWidth: float = 0, + maskHeight: float = 0, + taperAngle: float = 0, + halfStack: bool = False, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -416,6 +537,20 @@ class MakeStack: def getTopLayer(self) -> int: ... class MakeTrench: + @overload + def __init__( + self, + domain: Domain, + trenchWidth: float, + trenchDepth: float, + trenchTaperAngle: float = 0.0, + maskHeight: float = 0.0, + maskTaperAngle: float = 0.0, + halfTrench: bool = False, + material: Material = Material.Si, + maskMaterial: Material = Material.Mask, + ) -> None: ... + @overload def __init__( self, domain: Domain, @@ -428,7 +563,7 @@ class MakeTrench: baseHeight: float = 0.0, periodicBoundary: bool = False, makeMask: bool = False, - material: Material = Material.Undefined, + material: Material = Material.Si, ) -> None: ... def apply(self) -> None: ... @@ -469,7 +604,7 @@ class Material: class MaterialMap: def __init__(self) -> None: ... def getMaterialAtIdx(self, arg0: int) -> Material: ... - def getMaterialMap(self, *args, **kwargs): ... + def getMaterialMap(self) -> viennals3d.viennals3d.MaterialMap: ... @staticmethod def getMaterialName(arg0: Material) -> str: ... def insertNextMaterial(self, material: Material = ...) -> None: ... @@ -563,7 +698,7 @@ class Planarize: class Process: def __init__(self) -> None: ... def apply(self) -> None: ... - def calculateFlux(self): ... + def calculateFlux(self) -> viennals3d.viennals3d.Mesh: ... def disableAdvectionVelocityOutput(self) -> None: ... def disableFluxSmoothing(self) -> None: ... def disableRandomSeeds(self) -> None: ... @@ -574,8 +709,10 @@ class Process: def getProcessDuration(self) -> float: ... def getRayTracingParameters(self) -> RayTracingParameters: ... def setAdvectionParameters(self, arg0: AdvectionParameters) -> None: ... - def setDomain(self, arg0: Domain): ... - def setIntegrationScheme(self, arg0) -> None: ... + def setDomain(self, *args, **kwargs): ... + def setIntegrationScheme( + self, arg0: viennals3d.viennals3d.IntegrationSchemeEnum + ) -> None: ... def setMaxCoverageInitIterations(self, arg0: int) -> None: ... def setNumberOfRaysPerPoint(self, arg0: int) -> None: ... def setProcessDuration(self, arg0: float) -> None: ... @@ -621,13 +758,13 @@ class ProcessParams: class RateSet: calculateVisibility: bool - direction: list[float] + direction: Incomplete directionalVelocity: float isotropicVelocity: float maskMaterials: list[Material] def __init__( self, - direction: list[float] = ..., + direction=..., directionalVelocity: float = ..., isotropicVelocity: float = ..., maskMaterials: list[Material] = ..., @@ -754,6 +891,11 @@ class SingleParticleProcess(ProcessModel): ) -> None: ... class SphereDistribution(ProcessModel): + @overload + def __init__( + self, radius: float, gridDelta: float, mask: viennals3d.viennals3d.Domain + ) -> None: ... + @overload def __init__(self, radius: float, gridDelta: float) -> None: ... class TEOSDeposition(ProcessModel): @@ -794,11 +936,11 @@ class Time: class ToDiskMesh: @overload - def __init__(self, domain: Domain, mesh) -> None: ... + def __init__(self, domain: Domain, mesh: viennals3d.viennals3d.Mesh) -> None: ... @overload def __init__(self) -> None: ... def setDomain(self, arg0: Domain) -> None: ... - def setMesh(self, arg0) -> None: ... + def setMesh(self, arg0: viennals3d.viennals3d.Mesh) -> None: ... class rayTraceDirection: __members__: ClassVar[dict] = ... # read-only diff --git a/tests/fin/fin.cpp b/tests/fin/fin.cpp index 6dc1bed0..fc54fe4e 100644 --- a/tests/fin/fin.cpp +++ b/tests/fin/fin.cpp @@ -10,7 +10,9 @@ using namespace viennaps; template void RunTest() { auto domain = SmartPointer>::New(); - MakeFin(domain, 1., 10., 10., 5., 5., 10., 1., false, true, + // Logger::getInstance().setLogLevel(LogLevel::DEBUG); + + MakeFin(domain, .5, 10., 10., 5., 5., 10., 1., false, true, Material::Si) .apply(); @@ -19,8 +21,29 @@ template void RunTest() { VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); -} + domain->setup(.5, 10, 10, BoundaryType::REFLECTIVE_BOUNDARY); + MakeFin(domain, 5., 5., 5., 2., 0., true, Material::Si) + .apply(); + + VC_TEST_ASSERT(domain->getLevelSets().size() == 2); + VC_TEST_ASSERT(domain->getMaterialMap()); + VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); + + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + + domain->setup(.5, 10, 10, BoundaryType::PERIODIC_BOUNDARY); + MakeFin(domain, 5., 5., -10., 5., 10., false, Material::Si, + Material::Si) + .apply(); + // domain->saveSurfaceMesh("fin_1_" + std::to_string(D) + "D"); + + VC_TEST_ASSERT(domain->getLevelSets().size() == 2); + VC_TEST_ASSERT(domain->getMaterialMap()); + VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); + + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); +} } // namespace viennacore int main() { VC_RUN_ALL_TESTS } diff --git a/tests/hole/hole.cpp b/tests/hole/hole.cpp index c79669c4..10e861ca 100644 --- a/tests/hole/hole.cpp +++ b/tests/hole/hole.cpp @@ -8,10 +8,11 @@ namespace viennacore { using namespace viennaps; template void RunTest() { + omp_set_num_threads(1); auto domain = SmartPointer>::New(); // Test with HoleShape::Full - MakeHole(domain, 1., 10., 10., 2.5, 5., 10., 1., false, true, + MakeHole(domain, 1.0, 10., 10., 2.5, 5., 10., 1., false, true, Material::Si, HoleShape::Full) .apply(); @@ -21,9 +22,9 @@ template void RunTest() { LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); - // Test with HoleShape::Quarter + // // Test with HoleShape::Quarter domain->clear(); // Reset the domain for a new test - MakeHole(domain, 1., 10., 10., 2.5, 5., 10., 1., false, true, + MakeHole(domain, .5, 10., 10., 2.5, 5., 10., 1., false, true, Material::Si, HoleShape::Quarter) .apply(); @@ -43,6 +44,19 @@ template void RunTest() { VC_TEST_ASSERT(domain->getMaterialMap()); VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + // Logger::getInstance().setLogLevel(LogLevel::DEBUG); + + domain->setup(0.5, 10., 10., BoundaryType::REFLECTIVE_BOUNDARY); + MakeHole(domain, 2.5, 3., 10, 3., 10., HoleShape::Quarter, + Material::Si) + .apply(); + // domain->saveSurfaceMesh("hole" + std::to_string(D) + "D"); + + VC_TEST_ASSERT(domain->getLevelSets().size() == 2); + VC_TEST_ASSERT(domain->getMaterialMap()); + VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); } diff --git a/tests/materialMap/materialMap.cpp b/tests/materialMap/materialMap.cpp index 2edd93b4..21cb0427 100644 --- a/tests/materialMap/materialMap.cpp +++ b/tests/materialMap/materialMap.cpp @@ -26,7 +26,7 @@ int main() { // MapToMaterial test assert(MaterialMap::mapToMaterial(1) == Material::Si); assert(MaterialMap::mapToMaterial(2) == Material::SiO2); - assert(MaterialMap::mapToMaterial(20) == Material::None); + assert(MaterialMap::mapToMaterial(20) == Material::Undefined); // IsMaterial test assert(MaterialMap::isMaterial(1, Material::Si)); diff --git a/tests/plane/plane.cpp b/tests/plane/plane.cpp index 73f12bac..65c085b0 100644 --- a/tests/plane/plane.cpp +++ b/tests/plane/plane.cpp @@ -17,12 +17,17 @@ template void RunTest() { VC_TEST_ASSERT(domain->getMaterialMap()); VC_TEST_ASSERT(domain->getMaterialMap()->size() == 1); - MakePlane(domain, 5., Material::Si).apply(); + MakePlane(domain, 5., Material::Si, true).apply(); VC_TEST_ASSERT(domain->getLevelSets().size() == 2); VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + + MakePlane(domain, 5., Material::Si, false).apply(); + + VC_TEST_ASSERT(domain->getLevelSets().size() == 1); + VC_TEST_ASSERT(domain->getMaterialMap()->size() == 1); } } // namespace viennacore diff --git a/tests/stack/stack.cpp b/tests/stack/stack.cpp index abdbc99f..0bae17ba 100644 --- a/tests/stack/stack.cpp +++ b/tests/stack/stack.cpp @@ -8,13 +8,24 @@ namespace viennacore { using namespace viennaps; template void RunTest() { - auto domain = SmartPointer>::New(); + Logger::getInstance().setLogLevel(LogLevel::DEBUG); + omp_set_num_threads(1); - MakeStack(domain, 1., 10., 10., 3 /*num layers*/, 3., 2., 0., - 0., 10, true) + auto domain = SmartPointer>::New(); + MakeStack(domain, 1.0, 10., 10., 5 /*num layers*/, 3., 2., 2., + 2., 0., true) .apply(); - VC_TEST_ASSERT(domain->getLevelSets().size() == 5); + VC_TEST_ASSERT(domain->getLevelSets().size() == 6); + VC_TEST_ASSERT(domain->getMaterialMap()); + + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + + domain->setup(1.0, 10., 10., BoundaryType::REFLECTIVE_BOUNDARY); + MakeStack(domain, 5, 1., 2., 0., 5., 3., 10., true).apply(); + // domain->saveHullMesh("stack_2_" + std::to_string(D) + "D"); + + VC_TEST_ASSERT(domain->getLevelSets().size() == 7); VC_TEST_ASSERT(domain->getMaterialMap()); LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); diff --git a/tests/trench/trench.cpp b/tests/trench/trench.cpp index 11e7fa26..9bd8a2e8 100644 --- a/tests/trench/trench.cpp +++ b/tests/trench/trench.cpp @@ -8,17 +8,37 @@ namespace viennacore { using namespace viennaps; template void RunTest() { - auto domain = SmartPointer>::New(); + { + auto domain = SmartPointer>::New(); - MakeTrench(domain, 1., 10., 10., 5., 5., 10., 1., false, true, - Material::Si) - .apply(); + MakeTrench(domain, .5, 10., 10., 5., 5., 10., 1., false, + true, Material::Si) + .apply(); + domain->saveSurfaceMesh("trench_1_" + std::to_string(D) + "D"); - VC_TEST_ASSERT(domain->getLevelSets().size() == 2); - VC_TEST_ASSERT(domain->getMaterialMap()); - VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); + VC_TEST_ASSERT(domain->getLevelSets().size() == 2); + VC_TEST_ASSERT(domain->getMaterialMap()); + VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); - LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + } + + { + // Logger::getInstance().setLogLevel(LogLevel::DEBUG); + + auto domain = SmartPointer>::New( + .5, 10., 10., BoundaryType::PERIODIC_BOUNDARY); + MakeTrench(domain, 5., 15., 40., 5., -10., false, + Material::SiO2) + .apply(); + // domain->saveSurfaceMesh("trench_2_" + std::to_string(D) + "D"); + + VC_TEST_ASSERT(domain->getLevelSets().size() == 2); + VC_TEST_ASSERT(domain->getMaterialMap()); + VC_TEST_ASSERT(domain->getMaterialMap()->size() == 2); + + LSTEST_ASSERT_VALID_LS(domain->getLevelSets().back(), NumericType, D); + } } } // namespace viennacore