Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/viennaps/models/psGeometricDistributionModels.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ class SphereDistribution : public ProcessModelCPU<NumericType, D> {
assert(geomModel != nullptr);
geomModel->addMaskMaterial(material);
}

void applyToSingleMaterial(const Material material) {
auto geomModel = this->getGeometricModel();
assert(geomModel != nullptr);
geomModel->setSingleMaterial(true);
geomModel->addMaskMaterial(material);
}
};

template <typename NumericType, int D>
Expand Down Expand Up @@ -66,6 +73,13 @@ class BoxDistribution : public ProcessModelCPU<NumericType, D> {
assert(geomModel != nullptr);
geomModel->addMaskMaterial(material);
}

void applyToSingleMaterial(const Material material) {
auto geomModel = this->getGeometricModel();
assert(geomModel != nullptr);
geomModel->setSingleMaterial(true);
geomModel->addMaskMaterial(material);
}
};

template <typename NumericType, int D>
Expand Down
5 changes: 5 additions & 0 deletions include/viennaps/process/psGeometricModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class GeometricModel {
SmartPointer<viennals::Domain<NumericType, D>> mask = nullptr;
std::vector<Material> maskMaterials;
bool isDepo = false;
bool applySingleMaterial = false;

public:
GeometricModel() = default;
Expand Down Expand Up @@ -49,6 +50,10 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class GeometricModel {
auto &getMaskMaterials() const { return maskMaterials; }
auto isDeposition() const { return isDepo; }
void setDeposition(bool deposition) { isDepo = deposition; }
auto isSingleMaterial() const { return applySingleMaterial; }
void setSingleMaterial(bool singleMaterial) {
applySingleMaterial = singleMaterial;
}
};

} // namespace viennaps
106 changes: 61 additions & 45 deletions include/viennaps/process/psGeometricProcessStrategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,54 +44,71 @@ class GeometricProcessStrategy : public ProcessStrategy<NumericType, D> {
return ProcessResult::INVALID_INPUT;
}

auto maskLevelSet = SmartPointer<viennals::Domain<NumericType, D>>::New(
domain->getGrid());
bool foundMaterial = false;

auto const &levelSets = domain->getLevelSets();
for (auto &material : maskMaterials) {
for (int j = 0; j < levelSets.size(); ++j) {
if (materialMap->getMaterialAtIdx(j) == material) {
auto lsCopy = SmartPointer<viennals::Domain<NumericType, D>>::New(
levelSets[j]);

// remove all lower level sets that are not mask materials
for (int k = j - 1; k >= 0; --k) {
if (MaterialMap::isMaterial(materialMap->getMaterialAtIdx(k),
maskMaterials))
continue;

viennals::BooleanOperation<NumericType, D>(
lsCopy, levelSets[k],
viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT)
.apply();
}

if (foundMaterial) {
// union with mask level set
viennals::BooleanOperation<NumericType, D>(
maskLevelSet, lsCopy, viennals::BooleanOperationEnum::UNION)
.apply();
} else {
maskLevelSet = lsCopy;
foundMaterial = true;
if (geometricModel->isSingleMaterial() && maskMaterials.size() == 1) {
// operation should be applied to a single material, so we use the
// surface as mask and exclude the material from the surface
mask = viennals::Domain<NumericType, D>::New(domain->getSurface());
auto materialLS = domain->getMaterialLevelSet(maskMaterials[0]);
if (materialLS) {
viennals::BooleanOperation<NumericType, D>(
mask, materialLS,
viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT)
.apply();
VIENNACORE_LOG_DEBUG(
"Created mask level set from single mask material: " +
materialMap->toString(maskMaterials[0]));
}
} else {
auto maskLevelSet =
viennals::Domain<NumericType, D>::New(domain->getGrid());
bool foundMaterial = false;
auto const &levelSets = domain->getLevelSets();
for (auto &material : maskMaterials) {
for (int j = 0; j < levelSets.size(); ++j) {
if (materialMap->getMaterialAtIdx(j) == material) {
auto lsCopy =
viennals::Domain<NumericType, D>::New(levelSets[j]);

// remove all lower level sets that are not mask materials
for (int k = j - 1; k >= 0; --k) {
if (MaterialMap::isMaterial(materialMap->getMaterialAtIdx(k),
maskMaterials))
continue;

viennals::BooleanOperation<NumericType, D>(
lsCopy, levelSets[k],
viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT)
.apply();
}

if (foundMaterial) {
// union with mask level set
viennals::BooleanOperation<NumericType, D>(
maskLevelSet, lsCopy,
viennals::BooleanOperationEnum::UNION)
.apply();
} else {
maskLevelSet = lsCopy;
foundMaterial = true;
}
}
}
}
}

if (maskLevelSet->getNumberOfPoints() > 0) {
mask = maskLevelSet;
if (Logger::hasDebug()) {
auto dbgMesh = viennals::Mesh<NumericType>::New();
viennals::ToMesh<NumericType, D>(mask, dbgMesh).apply();
viennals::VTKWriter<NumericType>(dbgMesh, "geometric_mask_debug")
.apply();
if (maskLevelSet->getNumberOfPoints() > 0) {
mask = maskLevelSet;
if (Logger::hasDebug()) {
auto dbgMesh = viennals::Mesh<NumericType>::New();
viennals::ToMesh<NumericType, D>(mask, dbgMesh).apply();
viennals::VTKWriter<NumericType>(dbgMesh, "geometric_mask_debug")
.apply();
}
} else {
VIENNACORE_LOG_WARNING(
"None of the specified mask materials were found in the "
"domain, "
"cannot create mask level set from mask materials.");
}
} else {
VIENNACORE_LOG_WARNING(
"None of the specified mask materials were found in the domain, "
"cannot create mask level set from mask materials.");
}
}
}
Expand All @@ -104,8 +121,7 @@ class GeometricProcessStrategy : public ProcessStrategy<NumericType, D> {
// last level set.
for (int i = context.domain->getNumberOfLevelSets() - 1; i >= 0; --i) {
viennals::BooleanOperation<NumericType, D>(
context.domain->getLevelSets()[i],
context.domain->getLevelSets().back(),
context.domain->getLevelSets()[i], context.domain->getSurface(),
viennals::BooleanOperationEnum::INTERSECT)
.apply();
}
Expand Down
42 changes: 40 additions & 2 deletions include/viennaps/psDomain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class Domain {
return levelSets_.back()->getGrid().getBoundaryConditions();
}

// Returns a set of all materials present in the domain.
auto getMaterialsInDomain() const {
std::set<Material> materials;
for (std::size_t i = 0; i < materialMap_->size(); i++) {
Expand All @@ -455,6 +456,43 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class Domain {
return materials;
}

// Returns a Level-Set representing the specified material in the domain. If
// the material is not present in the domain, it returns an empty Level-Set.
auto getMaterialLevelSet(const Material material) const {
lsDomainType levelSet = nullptr;

for (int i = 0; i < levelSets_.size(); i++) {
if (materialMap_->getMaterialAtIdx(i) == material) {
auto lsCopy =
SmartPointer<viennals::Domain<NumericType, D>>::New(levelSets_[i]);

// remove lower level set
if (i > 0) {
viennals::BooleanOperation<NumericType, D>(
lsCopy, levelSets_[i - 1],
viennals::BooleanOperationEnum::RELATIVE_COMPLEMENT)
.apply();
}

if (levelSet) {
// add to level set
viennals::BooleanOperation<NumericType, D>(
levelSet, lsCopy, viennals::BooleanOperationEnum::UNION)
.apply();
} else {
levelSet = lsCopy;
}
}
}

if (!levelSet) {
VIENNACORE_LOG_WARNING("Material " + MaterialMap::toString(material) +
" not found in domain.");
}

return levelSet;
}

void print(std::ostream &out = std::cout, bool hrle = false) const {
constexpr std::string_view separator =
"*****************************************\n";
Expand Down Expand Up @@ -655,8 +693,8 @@ VIENNAPS_TEMPLATE_ND(NumericType, D) class Domain {
private:
void materialMapCheck() const {
if (materialMap_->size() != levelSets_.size()) {
VIENNACORE_LOG_WARNING(
"Size mismatch in material map and number of Level-Sets in domain.");
VIENNACORE_LOG_WARNING("Size mismatch in material map and number of "
"Level-Sets in domain.");
}
}

Expand Down
13 changes: 12 additions & 1 deletion python/pyWrapDimension.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@ template <int D> void bindApi(py::module &module) {
.def("getLevelSets", &Domain<T, D>::getLevelSets)
.def("getMaterialsInDomain", &Domain<T, D>::getMaterialsInDomain,
"Get the material IDs present in the domain.")
.def("getMaterialLevelSet", &Domain<T, D>::getMaterialLevelSet,
py::arg("material"),
"Returns a Level-Set representing the specified material in the "
"domain.")
.def("getSurface", &Domain<T, D>::getSurface,
"Get the surface level set.")
.def("getCellSet", &Domain<T, D>::getCellSet, "Get the cell set.")
Expand All @@ -564,6 +568,7 @@ template <int D> void bindApi(py::module &module) {
"Get the surface mesh of the domain")
.def("getHullMesh", &Domain<T, D>::getHullMesh,
py::arg("bottomExtension") = 0.0, py::arg("sharpCorners") = false)
.def("getDiskMesh", &Domain<T, D>::getDiskMesh)
// Save to file
.def("saveLevelSetMesh", &Domain<T, D>::saveLevelSetMesh,
py::arg("filename"), py::arg("width") = 1,
Expand All @@ -576,6 +581,7 @@ template <int D> void bindApi(py::module &module) {
.def("saveHullMesh", &Domain<T, D>::saveHullMesh, py::arg("filename"),
py::arg("bottomExtension") = 0.0, py::arg("sharpCorners") = false,
"Save the hull of the domain.")
.def("saveDiskMesh", &Domain<T, D>::saveDiskMesh, py::arg("filename"))
.def("saveVolumeMesh", &Domain<T, D>::saveVolumeMesh, py::arg("filename"),
py::arg("wrappingLayerEpsilon") = 1e-2,
"Save the volume representation of the domain.")
Expand Down Expand Up @@ -1055,6 +1061,9 @@ template <int D> void bindApi(py::module &module) {
}),
py::arg("radius"))
.def("addMaskMaterial", &SphereDistribution<T, D>::addMaskMaterial,
py::arg("material"))
.def("applyToSingleMaterial",
&SphereDistribution<T, D>::applyToSingleMaterial,
py::arg("material"));

// Box Distribution
Expand All @@ -1070,7 +1079,9 @@ template <int D> void bindApi(py::module &module) {
}),
py::arg("halfAxes"))
.def("addMaskMaterial", &BoxDistribution<T, D>::addMaskMaterial,
py::arg("material"));
py::arg("material"))
.def("applyToSingleMaterial",
&BoxDistribution<T, D>::applyToSingleMaterial, py::arg("material"));

// Custom Sphere Distribution
py::class_<CustomSphereDistribution<T, D>,
Expand Down
12 changes: 12 additions & 0 deletions python/viennaps/d2/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class BoxDistribution(ProcessModel):
...
def addMaskMaterial(self, material: viennaps._core.Material) -> None:
...
def applyToSingleMaterial(self, material: viennaps._core.Material) -> None:
...
class CF4O2Etching(ProcessModel):
@typing.overload
def __init__(self) -> None:
Expand Down Expand Up @@ -302,6 +304,8 @@ class Domain:
"""
Get the cell set.
"""
def getDiskMesh(self) -> viennals._core.Mesh:
...
def getGrid(self) -> viennals.d2.hrleGrid:
"""
Get the grid
Expand All @@ -318,6 +322,10 @@ class Domain:
"""
def getLevelSets(self) -> list[viennals.d2.Domain]:
...
def getMaterialLevelSet(self, material: viennaps._core.Material) -> viennals.d2.Domain:
"""
Returns a Level-Set representing the specified material in the domain.
"""
def getMaterialMap(self) -> viennaps._core.MaterialMap:
...
def getMaterialsInDomain(self) -> set[viennaps._core.Material]:
Expand Down Expand Up @@ -378,6 +386,8 @@ class Domain:
...
def removeTopLevelSet(self) -> None:
...
def saveDiskMesh(self, filename: str) -> None:
...
def saveHullMesh(self, filename: str, bottomExtension: typing.SupportsFloat | typing.SupportsIndex = 0.0, sharpCorners: bool = False) -> None:
"""
Save the hull of the domain.
Expand Down Expand Up @@ -934,6 +944,8 @@ class SphereDistribution(ProcessModel):
...
def addMaskMaterial(self, material: viennaps._core.Material) -> None:
...
def applyToSingleMaterial(self, material: viennaps._core.Material) -> None:
...
class StencilLocalLaxFriedrichsScalar:
@staticmethod
def setMaxDissipation(maxDissipation: typing.SupportsFloat | typing.SupportsIndex) -> None:
Expand Down
12 changes: 12 additions & 0 deletions python/viennaps/d3/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class BoxDistribution(ProcessModel):
...
def addMaskMaterial(self, material: viennaps._core.Material) -> None:
...
def applyToSingleMaterial(self, material: viennaps._core.Material) -> None:
...
class CF4O2Etching(ProcessModel):
@typing.overload
def __init__(self) -> None:
Expand Down Expand Up @@ -302,6 +304,8 @@ class Domain:
"""
Get the cell set.
"""
def getDiskMesh(self) -> viennals._core.Mesh:
...
def getGrid(self) -> viennals.d3.hrleGrid:
"""
Get the grid
Expand All @@ -318,6 +322,10 @@ class Domain:
"""
def getLevelSets(self) -> list[viennals.d3.Domain]:
...
def getMaterialLevelSet(self, material: viennaps._core.Material) -> viennals.d3.Domain:
"""
Returns a Level-Set representing the specified material in the domain.
"""
def getMaterialMap(self) -> viennaps._core.MaterialMap:
...
def getMaterialsInDomain(self) -> set[viennaps._core.Material]:
Expand Down Expand Up @@ -378,6 +386,8 @@ class Domain:
...
def removeTopLevelSet(self) -> None:
...
def saveDiskMesh(self, filename: str) -> None:
...
def saveHullMesh(self, filename: str, bottomExtension: typing.SupportsFloat | typing.SupportsIndex = 0.0, sharpCorners: bool = False) -> None:
"""
Save the hull of the domain.
Expand Down Expand Up @@ -934,6 +944,8 @@ class SphereDistribution(ProcessModel):
...
def addMaskMaterial(self, material: viennaps._core.Material) -> None:
...
def applyToSingleMaterial(self, material: viennaps._core.Material) -> None:
...
class StencilLocalLaxFriedrichsScalar:
@staticmethod
def setMaxDissipation(maxDissipation: typing.SupportsFloat | typing.SupportsIndex) -> None:
Expand Down
Loading