diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ccdf78b4..32f3bacc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -81,11 +81,20 @@ test_win: script: - pip install pytest-check - cd tests\pytest - - REM python test_tutorials.py new_results.json - cd %NETGEN_BUILD_DIR%\netgen - ctest -C Release -V --output-on-failure - cd .. needs: ["build_win"] + +generate_results: + <<: *win + stage: test + script: + - pip install pytest-check + - cd tests\pytest + - python test_tutorials.py new_results.json + needs: ["build_win"] + when: manual artifacts: paths: - tests/pytest/new_results.json @@ -272,7 +281,7 @@ cleanup_mac: needs: ["test_mac"] pip_linux: - image: quay.io/pypa/manylinux2014_x86_64 + image: quay.io/pypa/manylinux_2_28_x86_64 stage: build tags: - pip @@ -288,6 +297,7 @@ pip_windows: - pip - windows script: + - .\tests\build_pip.ps1 C:\Python313 - .\tests\build_pip.ps1 C:\Python312 - .\tests\build_pip.ps1 C:\Python311 - .\tests\build_pip.ps1 C:\Python310 @@ -302,6 +312,7 @@ pip_macos: - macosx - m1 script: + - ./tests/build_pip_mac.sh 3.13 - ./tests/build_pip_mac.sh 3.12 - ./tests/build_pip_mac.sh 3.11 - ./tests/build_pip_mac.sh 3.10 diff --git a/cmake/external_projects/tcltk.cmake b/cmake/external_projects/tcltk.cmake index 7a9937de..edbe9a79 100644 --- a/cmake/external_projects/tcltk.cmake +++ b/cmake/external_projects/tcltk.cmake @@ -51,12 +51,17 @@ if(APPLE OR WIN32) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH - HINTS ${PYTHON_PREFIX}/lib ${PYTHON_PREFIX}/tcl + HINTS + ${PYTHON_PREFIX}/lib + ${PYTHON_PREFIX}/tcl + ${PYTHON_PREFIX}/Frameworks + ${PYTHON_PREFIX}/Frameworks/Tcl.framework + ${PYTHON_PREFIX}/Frameworks/Tk.framework ) find_library(TCL_STUB_LIBRARY NAMES tclstub85 tclstub8.5 tclstub86 tclstub8.6 ${tcl_find_args}) find_library(TK_STUB_LIBRARY NAMES tkstub85 tkstub8.5 tkstub86 tkstub8.6 ${tcl_find_args}) - find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t ${tcl_find_args}) - find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t ${tcl_find_args}) + find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t Tcl ${tcl_find_args}) + find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t Tk ${tcl_find_args}) else() # use system tcl/tk on linux find_package(TclStub REQUIRED) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 839fbdc6..8a3d7a32 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -1,6 +1,7 @@ #ifndef NETGEN_CORE_ARCHIVE_HPP #define NETGEN_CORE_ARCHIVE_HPP +#include #include #include // for array #include // for complex @@ -1136,15 +1137,32 @@ namespace ngcore { char c; *stream >> c; b = (c=='t'); return *this; } Archive & operator & (std::string & str) override { + // Ignore \r (carriage return) characters when reading strings + // this is necessary for instance when a file was written on Windows and is read on Unix + int len; *stream >> len; char ch; - stream->get(ch); // '\n' + stream->get(ch); // read newline character if(ch == '\r') // windows line endings -> read \n as well stream->get(ch); str.resize(len); if(len) stream->get(&str[0], len+1, '\0'); + + // remove all \r characters from the string, check if size changed + // if so, read the remaining characters + str.erase(std::remove(str.begin(), str.end(), '\r'), str.cend()); + size_t chars_to_read = len-str.size(); + while (chars_to_read>0) + { + auto old_size = str.size(); + str.resize(len); + + stream->get(&str[old_size], chars_to_read+1, '\0'); + str.erase(std::remove(str.begin()+old_size, str.end(), '\r'), str.cend()); + chars_to_read = len - str.size(); + } return *this; } Archive & operator & (char *& str) override diff --git a/libsrc/core/python_ngcore_export.cpp b/libsrc/core/python_ngcore_export.cpp index 73bba40e..eea84619 100644 --- a/libsrc/core/python_ngcore_export.cpp +++ b/libsrc/core/python_ngcore_export.cpp @@ -141,10 +141,16 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT .def(py::self | py::self) .def(py::self & py::self) - // .def(py::self |= py::self) // false clang warnings, - // .def(py::self &= py::self) // see https://github.com/pybind/pybind11/issues/1893 - .def("__ior__", [](BitArray& lhs, const BitArray& rhs) { return lhs |= rhs; }, py::is_operator()) - .def("__iand__", [](BitArray& lhs, const BitArray& rhs) { return lhs &= rhs; }, py::is_operator()) + #ifdef __clang__ + // see https://github.com/pybind/pybind11/issues/1893 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wself-assign-overloaded" + #endif + .def(py::self |= py::self) + .def(py::self &= py::self) + #ifdef __clang__ + #pragma GCC diagnostic pop + #endif .def(~py::self) ; diff --git a/libsrc/meshing/basegeom.hpp b/libsrc/meshing/basegeom.hpp index 8d5a0ee5..2eb7a203 100644 --- a/libsrc/meshing/basegeom.hpp +++ b/libsrc/meshing/basegeom.hpp @@ -212,11 +212,18 @@ namespace netgen size_t GetNVertices() const { return vertices.Size(); } size_t GetNEdges() const { return edges.Size(); } size_t GetNFaces() const { return faces.Size(); } + size_t GetNSolids() const { return solids.Size(); } + const GeometrySolid & GetSolid(int i) const { return *solids[i]; } const GeometryFace & GetFace(int i) const { return *faces[i]; } const GeometryEdge & GetEdge(int i) const { return *edges[i]; } const GeometryVertex & GetVertex(int i) const { return *vertices[i]; } + auto Solids() const { return FlatArray{solids}; } + auto Faces() const { return FlatArray{faces}; } + auto Edges() const { return FlatArray{edges}; } + auto Vertices() const { return FlatArray{vertices}; } + virtual Array GetFaceVertices(const GeometryFace& face) const { return Array{}; } void Clear(); diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index 90a2ff65..ce27961a 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -7286,17 +7286,27 @@ namespace netgen regex regex_faces(faces); regex regex_domains(domains); - for(auto dom : Range(ndomains)) - { - if(regex_match(mesh.GetMaterial(dom+1), regex_domains)) - keep_domain.SetBit(dom); - } + if(dimension == 3) { + for(auto dom : Range(ndomains)) + if(regex_match(mesh.GetMaterial(dom+1), regex_domains)) + keep_domain.SetBit(dom); - for(auto fi : Range(nfaces)) - { - auto & fd = mesh.FaceDescriptors()[fi]; - if (keep_domain[fd.DomainIn()] || keep_domain[fd.DomainOut()] || regex_match(fd.GetBCName(), regex_faces)) - keep_face.SetBit(fd.BCProperty()); + for(auto fi : Range(nfaces)) + { + auto & fd = mesh.FaceDescriptors()[fi]; + if (regex_match(fd.GetBCName(), regex_faces) + || keep_domain[fd.DomainIn()] || keep_domain[fd.DomainOut()]) + keep_face.SetBit(fd.BCProperty()); + } + } + else { + for(auto fi : Range(nfaces)) + { + auto & fd = mesh.FaceDescriptors()[fi]; + auto mat = GetMaterial(fd.BCProperty()); + if (regex_match(mat, regex_faces)) + keep_face.SetBit(fd.BCProperty()); + } } auto filter_elements = [&keep_point](auto & elements, auto & keep_region) diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 1e9314cb..3404fb16 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -522,10 +522,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) for (int i = 0; i < 2; i++) (*newel)[i] = py::extract(vertices[i])(); newel -> si = index; - newel -> edgenr = edgenr; newel -> epgeominfo[0].edgenr = edgenr; newel -> epgeominfo[1].edgenr = edgenr; - // needed for codim2 in 3d newel -> edgenr = index; for(auto i : Range(len(trignums))) newel->geominfo[i].trignum = py::cast(trignums[i]); @@ -1030,10 +1028,22 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) return self.AddSurfaceElement (el); }) - .def ("Add", [](Mesh & self, const Segment & el) + .def ("Add", [](Mesh & self, const Segment & el, bool project_geominfo) { + if (project_geominfo) + { + auto &p1 = self[el[0]]; + auto &p2 = self[el[1]]; + auto geo = self.GetGeometry(); + geo->ProjectPointEdge + (0,0,p1, + const_cast(&el.epgeominfo[0])); + geo->ProjectPointEdge + (0,0,p2, + const_cast(&el.epgeominfo[1])); + } return self.AddSegment (el); - }) + }, py::arg("el"), py::arg("project_geominfo")=false) .def ("Add", [](Mesh & self, const Element0d & el) { @@ -1085,7 +1095,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) ptr += 3; } }) - .def ("AddElements", [](Mesh & self, int dim, int index, py::buffer b1, int base) + .def ("AddElements", [](Mesh & self, int dim, int index, py::buffer b1, int base, + bool project_geometry) { static Timer timer("Mesh::AddElements"); static Timer timercast("Mesh::AddElements casting"); @@ -1137,6 +1148,21 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) for (int j = 0; j < np; j++) el[j] = ptr[j]+PointIndex::BASE-base; el.SetIndex(index); + if(project_geometry) + { + // find some point in the mid of trig/quad for + // quick + stable uv-projection of all points + auto startp = Center(self[el[0]], self[el[1]], self[el[2]]); + PointGeomInfo gi = self.GetGeometry()->ProjectPoint(index, + startp); + for(auto i : Range(np)) + { + el.GeomInfo()[i] = gi; + self.GetGeometry()->ProjectPointGI(index, + self[el[i]], + el.GeomInfo()[i]); + } + } self.AddSurfaceElement (el); ptr += info.strides[0]/sizeof(int); } @@ -1168,7 +1194,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) } } - }, py::arg("dim"), py::arg("index"), py::arg("data"), py::arg("base")=0) + }, py::arg("dim"), py::arg("index"), py::arg("data"), py::arg("base")=0, + py::arg("project_geometry")=false) .def ("DeleteSurfaceElement", [](Mesh & self, SurfaceElementIndex i) diff --git a/libsrc/occ/occ_utils.cpp b/libsrc/occ/occ_utils.cpp index 243349fc..96a8a41e 100644 --- a/libsrc/occ/occ_utils.cpp +++ b/libsrc/occ/occ_utils.cpp @@ -5,6 +5,7 @@ #include #include "occ_utils.hpp" +#include "occgeom.hpp" namespace netgen { diff --git a/libsrc/occ/occ_utils.hpp b/libsrc/occ/occ_utils.hpp index 8696cb55..04973789 100644 --- a/libsrc/occ/occ_utils.hpp +++ b/libsrc/occ/occ_utils.hpp @@ -170,6 +170,17 @@ namespace netgen common.push_back(shape); return common; } + + ListOfShapes GetHighestDimShapes() const + { + for (auto type : {TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX}) + { + auto ret = SubShapes(type); + if (ret.size() > 0) + return ret; + } + return ListOfShapes(); + } }; inline ListOfShapes GetSolids(const TopoDS_Shape & shape) @@ -212,6 +223,16 @@ namespace netgen return sub; } + inline ListOfShapes GetHighestDimShapes(const TopoDS_Shape & shape) + { + auto ret = GetSolids(shape); if(ret.size() > 0) return ret; + ret = GetFaces(shape); if(ret.size() > 0) return ret; + ret = GetEdges(shape); if(ret.size() > 0) return ret; + ret = GetVertices(shape); if(ret.size() > 0) return ret; + return ListOfShapes(); + } + + class DirectionalInterval { public: diff --git a/libsrc/occ/occgenmesh.cpp b/libsrc/occ/occgenmesh.cpp index 9a6c269e..1ce34c55 100644 --- a/libsrc/occ/occgenmesh.cpp +++ b/libsrc/occ/occgenmesh.cpp @@ -414,7 +414,7 @@ namespace netgen // Philippose - 15/01/2009 - auto& props = OCCGeometry::GetProperties(geom.fmap(k)); + auto& props = occface.properties; double maxh = min2(geom.face_maxh[k-1], props.maxh); //double maxh = mparam.maxh; // int noldpoints = mesh->GetNP(); @@ -485,21 +485,18 @@ namespace netgen int maxlayer = 1; int dom = 0; - for(const auto& s : GetSolids(geom.GetShape())) + for(auto dom : Range(geom.GetNSolids())) { - if(!OCCGeometry::HaveProperties(s)) - continue; - auto& props = OCCGeometry::GetProperties(s); + auto & props = geom.GetSolid(dom).properties; maxhdom[dom] = min2(maxhdom[dom], props.maxh); maxlayer = max2(maxlayer, props.layer); - dom++; } - for(const auto& f : GetFaces(geom.GetShape())) - if(OCCGeometry::HaveProperties(f)) - maxlayer = max2(maxlayer, OCCGeometry::GetProperties(f).layer); - for(const auto& e : GetEdges(geom.GetShape())) - if(OCCGeometry::HaveProperties(e)) - maxlayer = max2(maxlayer, OCCGeometry::GetProperties(e).layer); + + for(auto & f : geom.Faces()) + maxlayer = max2(maxlayer, f->properties.layer); + + for(auto & e : geom.Edges()) + maxlayer = max2(maxlayer, e->properties.layer); mesh.SetMaxHDomain (maxhdom); @@ -514,14 +511,11 @@ namespace netgen for(auto layer : Range(1, maxlayer+1)) mesh.SetLocalH (bb.PMin(), bb.PMax(), mparam.grading, layer); - for(const auto& v : GetVertices(geom.GetShape())) + for(auto& v : geom.Vertices()) { - if(OCCGeometry::HaveProperties(v)) - { - auto& props = OCCGeometry::GetProperties(v); - if(props.maxh < 1e99) - mesh.GetLocalH(props.layer)->SetH(occ2ng(BRep_Tool::Pnt(TopoDS::Vertex(v))), props.maxh); - } + auto& props = v->properties; + if(props.maxh < 1e99) + mesh.GetLocalH(props.layer)->SetH(v->GetPoint(), props.maxh); } int nedges = geom.emap.Extent(); @@ -538,19 +532,10 @@ namespace netgen multithread.task = "Setting local mesh size (elements per edge)"; - // Philippose - 23/01/2009 - // Find all the parent faces of a given edge - // and limit the mesh size of the edge based on the - // mesh size limit of the face - TopTools_IndexedDataMapOfShapeListOfShape edge_face_map; - edge_face_map.Clear(); - TopExp::MapShapesAndAncestors(geom.shape, TopAbs_EDGE, TopAbs_FACE, edge_face_map); - // setting elements per edge for (int i = 1; i <= nedges && !multithread.terminate; i++) { TopoDS_Edge e = TopoDS::Edge (geom.emap(i)); - int layer = OCCGeometry::GetProperties(e).layer; multithread.percent = 100 * (i-1)/double(nedges); if (BRep_Tool::Degenerated(e)) continue; @@ -583,23 +568,10 @@ namespace netgen double localh = len/mparam.segmentsperedge; double s0, s1; - const TopTools_ListOfShape& parent_faces = edge_face_map.FindFromKey(e); - - TopTools_ListIteratorOfListOfShape parent_face_list; - - for(parent_face_list.Initialize(parent_faces); parent_face_list.More(); parent_face_list.Next()) - { - TopoDS_Face parent_face = TopoDS::Face(parent_face_list.Value()); - - int face_index = geom.fmap.FindIndex(parent_face); - - if(face_index >= 1) localh = min(localh,geom.face_maxh[face_index - 1]); - localh = min2(localh, OCCGeometry::GetProperties(parent_face).maxh); - } - Handle(Geom_Curve) c = BRep_Tool::Curve(e, s0, s1); - localh = min2(localh, OCCGeometry::GetProperties(e).maxh); + const auto & props = gedge.properties; + localh = min2(localh, props.maxh); maxedgelen = max (maxedgelen, len); minedgelen = min (minedgelen, len); int maxj = max((int) ceil(len/localh)*2, 2); @@ -607,7 +579,7 @@ namespace netgen for (int j = 0; j <= maxj; j++) { gp_Pnt pnt = c->Value (s0+double(j)/maxj*(s1-s0)); - mesh.RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), localh, layer); + mesh.RestrictLocalH (Point3d(pnt.X(), pnt.Y(), pnt.Z()), localh, props.layer); } } @@ -622,12 +594,12 @@ namespace netgen double maxcur = 0; multithread.percent = 100 * (i-1)/double(nedges); TopoDS_Edge edge = TopoDS::Edge (geom.emap(i)); - int layer = OCCGeometry::GetProperties(edge).layer; if (BRep_Tool::Degenerated(edge)) continue; double s0, s1; Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1); BRepAdaptor_Curve brepc(edge); BRepLProp_CLProps prop(brepc, 2, 1e-5); + auto layer = geom.GetEdge(edge).properties.layer; for (int j = 1; j <= nsections; j++) { @@ -658,7 +630,6 @@ namespace netgen { multithread.percent = 100 * (i-1)/double(nfaces); TopoDS_Face face = TopoDS::Face(geom.fmap(i)); - int layer = OCCGeometry::GetProperties(face).layer; TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface (face); Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); @@ -675,6 +646,7 @@ namespace netgen // one prop for evaluating and one for derivatives BRepLProp_SLProps prop(sf, 0, 1e-5); BRepLProp_SLProps prop2(sf, 2, 1e-5); + auto layer = geom.GetFace(face).properties.layer; int ntriangles = triangulation -> NbTriangles(); for (int j = 1; j <= ntriangles; j++) @@ -725,7 +697,7 @@ namespace netgen for (int i = 1; i <= nedges && !multithread.terminate; i++) { TopoDS_Edge edge = TopoDS::Edge (geom.emap(i)); - int layer = OCCGeometry::GetProperties(edge).layer; + int layer = geom.GetEdge(edge).properties.layer; if (BRep_Tool::Degenerated(edge)) continue; double s0, s1; diff --git a/libsrc/occ/occgeom.cpp b/libsrc/occ/occgeom.cpp index c942a50d..13156783 100644 --- a/libsrc/occ/occgeom.cpp +++ b/libsrc/occ/occgeom.cpp @@ -200,6 +200,11 @@ namespace netgen return *faces[fmap.FindIndex(shape)-1]; } + const GeometrySolid & OCCGeometry :: GetSolid(const TopoDS_Shape & shape) const + { + return *solids[somap.FindIndex(shape)-1]; + } + string STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * aReader) { @@ -416,16 +421,7 @@ namespace netgen } #endif -#ifdef OCC_HAVE_HISTORY - Handle(BRepTools_History) history = aBuilder.History (); - - for (TopExp_Explorer e(shape, TopAbs_SOLID); e.More(); e.Next()) - { - if (auto name = OCCGeometry::GetProperties(e.Current()).name) - for (auto mods : history->Modified(e.Current())) - OCCGeometry::GetProperties(mods).name = *name; - } -#endif // OCC_HAVE_HISTORY + PropagateProperties(aBuilder, shape); // result of the operation shape = aBuilder.Shape(); @@ -1248,11 +1244,11 @@ namespace netgen auto occ_solid = make_unique(s); if(HaveProperties(s)) occ_solid->properties = GetProperties(s); - solids.Append(std::move(occ_solid)); - for(auto f : GetFaces(s)) { auto & face = static_cast(GetFace(f)); + face.properties.maxh = min2(face.properties.maxh, occ_solid->properties.maxh); + if(face.domin==-1) face.domin = k; else @@ -1260,21 +1256,10 @@ namespace netgen if(face.Shape().Orientation() == TopAbs_INTERNAL) face.domout = k; } + solids.Append(std::move(occ_solid)); } // Propagate maxh to children - for(auto& solid : solids) - { - auto& shape = static_cast(*solid).GetShape(); - if(!OCCGeometry::HaveProperties(shape)) - continue; - for(auto& f : GetFaces(shape)) - { - auto& face = GetFace(f); - face.properties.maxh = min2(face.properties.maxh, - GetProperties(shape).maxh); - } - } for(auto& face : faces) for(auto& edge : face->edges) edge->properties.maxh = min2(edge->properties.maxh, diff --git a/libsrc/occ/occgeom.hpp b/libsrc/occ/occgeom.hpp index fa00163a..6d2abbc8 100644 --- a/libsrc/occ/occgeom.hpp +++ b/libsrc/occ/occgeom.hpp @@ -232,6 +232,7 @@ namespace netgen using NetgenGeometry::GetVertex; using NetgenGeometry::GetEdge; using NetgenGeometry::GetFace; + using NetgenGeometry::GetSolid; GeometryShape & GetShape(const TopoDS_Shape & shape) { @@ -252,10 +253,16 @@ namespace netgen return const_cast(as_const(*this).GetFace(shape)); } + GeometrySolid & GetSolid(const TopoDS_Shape & shape) + { + return const_cast(as_const(*this).GetSolid(shape)); + } + const GeometryShape & GetShape(const TopoDS_Shape & shape) const; const GeometryVertex & GetVertex(const TopoDS_Shape & shape) const; const GeometryEdge & GetEdge(const TopoDS_Shape & shape) const; const GeometryFace & GetFace(const TopoDS_Shape & shape) const; + const GeometrySolid & GetSolid(const TopoDS_Shape & shape) const; void Analyse(Mesh& mesh, const MeshingParameters& mparam) const override; diff --git a/libsrc/occ/python_occ_shapes.cpp b/libsrc/occ/python_occ_shapes.cpp index e2c819d1..62c8f387 100644 --- a/libsrc/occ/python_occ_shapes.cpp +++ b/libsrc/occ/python_occ_shapes.cpp @@ -827,6 +827,8 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) return nullopt; }, [](const TopoDS_Shape & self, optional name) { OCCGeometry::GetProperties(self).name = name; + for (auto & s : GetHighestDimShapes(self)) + OCCGeometry::GetProperties(s).name = name; }, "'name' of shape") .def_property("maxh", @@ -837,6 +839,8 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) [](TopoDS_Shape& self, double val) { OCCGeometry::GetProperties(self).maxh = val; + for(auto & s : GetHighestDimShapes(self)) + OCCGeometry::GetProperties(s).maxh = val; }, "maximal mesh-size for shape") .def_property("hpref", @@ -846,8 +850,9 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) }, [](TopoDS_Shape& self, double val) { - auto & hpref = OCCGeometry::GetProperties(self).hpref; - hpref = max2(val, hpref); + OCCGeometry::GetProperties(self).hpref = val; + for(auto & s : GetHighestDimShapes(self)) + OCCGeometry::GetProperties(s).hpref = val; }, "number of refinement levels for geometric refinement") .def_property("col", [](const TopoDS_Shape & self) -> py::object { @@ -860,6 +865,8 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) if(c.size() == 4) col[3] = c[3]; OCCGeometry::GetProperties(self).col = col; + for(auto & s : GetHighestDimShapes(self)) + OCCGeometry::GetProperties(s).col = col; }, "color of shape as RGB - tuple") .def_property("layer", [](const TopoDS_Shape& self) { if (!OCCGeometry::HaveProperties(self)) @@ -867,6 +874,8 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) return OCCGeometry::GetProperties(self).layer; }, [](const TopoDS_Shape& self, int layer) { OCCGeometry::GetProperties(self).layer = layer; + for(auto & s : GetHighestDimShapes(self)) + OCCGeometry::GetProperties(s).layer = layer; }, "layer of shape") .def("UnifySameDomain", [](const TopoDS_Shape& shape, bool edges, bool faces, @@ -1813,17 +1822,8 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) }, [](ListOfShapes& shapes, double maxh) { - for(auto& shape : shapes) - { - for(auto& s : GetSolids(shape)) - OCCGeometry::GetProperties(s).maxh = maxh; - for(auto& s : GetFaces(shape)) - OCCGeometry::GetProperties(s).maxh = maxh; - for(auto& s : GetEdges(shape)) - OCCGeometry::GetProperties(s).maxh = maxh; - for(auto& s : GetVertices(shape)) - OCCGeometry::GetProperties(s).maxh = maxh; - } + for(auto & s : shapes) + OCCGeometry::GetProperties(s).maxh = maxh; }, "set maxh for all elements of list") .def_property("hpref", [](ListOfShapes& shapes) { @@ -1832,10 +1832,7 @@ DLL_HEADER void ExportNgOCCShapes(py::module &m) [](ListOfShapes& shapes, double hpref) { for(auto& shape : shapes) - { - auto& val = OCCGeometry::GetProperties(shape).hpref; - val = max2(hpref, val); - } + OCCGeometry::GetProperties(shape).hpref = hpref; }, "set hpref for all elements of list") .def_property("quad_dominated", [](ListOfShapes& shapes) { diff --git a/tests/build_pip.ps1 b/tests/build_pip.ps1 index 2692af82..c665edcb 100644 --- a/tests/build_pip.ps1 +++ b/tests/build_pip.ps1 @@ -10,7 +10,7 @@ $env:NETGEN_ARCH = 'avx2' $pydir=$args[0] & $pydir\python.exe --version -& $pydir\python.exe -m pip install packaging +& $pydir\python.exe -m pip install packaging requests & $pydir\python.exe tests\utils.py --check-pip if ($LASTEXITCODE -ne 0) { exit 0 diff --git a/tests/build_pip.sh b/tests/build_pip.sh index 533d1173..87c23034 100755 --- a/tests/build_pip.sh +++ b/tests/build_pip.sh @@ -1,25 +1,19 @@ set -e ulimit -n 1024000 # lower open file limit, seems to affect performance yum -y update -yum -y install ninja-build fontconfig-devel tk-devel tcl-devel libXmu-devel mesa-libGLU-devel ccache dpkg +yum -y install ninja-build fontconfig-devel tk-devel tcl-devel libXmu-devel mesa-libGLU-devel openmpi-devel mpich-devel +mkdir -p /opt/openmpi/include /opt/mpich/include +cp -a /usr/include/openmpi-x86_64/* /opt/openmpi/include/ +cp -a /usr/include/mpich-x86_64/* /opt/mpich/include/ -curl http://ftp.de.debian.org/debian/pool/main/o/openmpi/libopenmpi-dev_4.1.6-13.3_amd64.deb -o openmpi-dev.deb -dpkg-deb -R openmpi-dev.deb /opt/openmpi -mv /opt/openmpi/usr/lib/x86_64-linux-gnu/openmpi/include /opt/openmpi/include - - -curl http://ftp.de.debian.org/debian/pool/main/m/mpich/libmpich-dev_4.2.1-2_amd64.deb -o mpich.deb -dpkg-deb -R mpich.deb /opt/mpich -mv /opt/mpich/usr/lib/x86_64-linux-gnu/mpich/include /opt/mpich/include - +curl https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/c/ccache-3.7.7-1.el8.x86_64.rpm -o ccache.rpm +dnf -y install ccache.rpm rm -rf wheelhouse export NETGEN_CCACHE=1 -/opt/python/cp39-cp39/bin/python tests/fix_auditwheel_policy.py - -for pyversion in 312 311 310 39 38 +for pyversion in 313 312 311 310 39 38 do export PYDIR="/opt/python/cp${pyversion}-cp${pyversion}/bin" echo $PYDIR @@ -31,7 +25,6 @@ do rm -rf _skbuild NETGEN_ARCH=avx2 $PYDIR/pip wheel . mkdir -p wheelhouse - #auditwheel repair netgen_mesher*-cp${pyversion}-*.whl rename linux_x86_64 manylinux_2_17_x86_64.manylinux2014_x86_64 netgen_mesher*-cp${pyversion}-*.whl mv netgen_mesher*-cp${pyversion}-*.whl wheelhouse/ diff --git a/tests/build_pip_mac.sh b/tests/build_pip_mac.sh index d6f6cb7a..1824ea9a 100755 --- a/tests/build_pip_mac.sh +++ b/tests/build_pip_mac.sh @@ -7,7 +7,7 @@ export PATH=$PYDIR:/Applications/CMake.app/Contents/bin:$PATH export NETGEN_CCACHE=1 $PYDIR/python3 --version -$PYDIR/python3 -m pip install packaging +$PYDIR/python3 -m pip install packaging requests $PYDIR/python3 tests/utils.py --check-pip || exit 0 $PYDIR/python3 -m pip install --user numpy twine scikit-build wheel pybind11-stubgen $PYDIR/python3 -m pip install --user -U netgen-occt==7.8.1 netgen-occt-devel==7.8.1 diff --git a/tests/fix_auditwheel_policy.py b/tests/fix_auditwheel_policy.py deleted file mode 100644 index 1b0329f9..00000000 --- a/tests/fix_auditwheel_policy.py +++ /dev/null @@ -1,26 +0,0 @@ -import json - -policy_file = "/opt/_internal/pipx/venvs/auditwheel/lib/python3.10/site-packages/auditwheel/policy/manylinux-policy.json" -data = json.load(open(policy_file)) -additional_libs = [ - "libbz2.so.1.0.6", - "libfontconfig.so.1.11.1", - "libfreetype.so.6.14.0", - "libGLU.so.1.3.1", - "libpng15.so.15.13.0", - "libtcl8.so", - "libtk8.so", - "libuuid.so.1.3.0", - "libz.so.1.2.7", - "libXmu.so.6", - "libOpenGL.so.0", - "libGLdispatch.so.0", - "libGLX.so.0", - "libGLU.so.1", - ] - -for entry in data: - if 'manylinux' in entry['name']: - entry['lib_whitelist'] += additional_libs - -json.dump(data, open(policy_file, 'w')) diff --git a/tests/pytest/results.json b/tests/pytest/results.json index 8f58035e..c455838d 100644 --- a/tests/pytest/results.json +++ b/tests/pytest/results.json @@ -827,98 +827,6 @@ "total_badness": 100414.60403 } ], - "cylinder.geo": [ - { - "angles_tet": [ - 19.071, - 144.66 - ], - "angles_trig": [ - 22.881, - 111.85 - ], - "ne1d": 52, - "ne2d": 286, - "ne3d": 394, - "quality_histogram": "[0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 18, 38, 45, 53, 70, 51, 48, 40, 12, 9]", - "total_badness": 562.09628542 - }, - { - "angles_tet": [ - 22.85, - 151.98 - ], - "angles_trig": [ - 25.237, - 118.13 - ], - "ne1d": 24, - "ne2d": 66, - "ne3d": 69, - "quality_histogram": "[0, 0, 0, 0, 0, 0, 1, 1, 3, 3, 3, 5, 0, 4, 2, 2, 9, 26, 3, 7]", - "total_badness": 95.643757297 - }, - { - "angles_tet": [ - 14.788, - 156.92 - ], - "angles_trig": [ - 11.549, - 134.56 - ], - "ne1d": 36, - "ne2d": 152, - "ne3d": 548, - "quality_histogram": "[0, 0, 0, 0, 1, 7, 24, 35, 41, 59, 44, 55, 57, 51, 39, 38, 48, 26, 19, 4]", - "total_badness": 980.19781779 - }, - { - "angles_tet": [ - 19.062, - 144.68 - ], - "angles_trig": [ - 22.836, - 111.85 - ], - "ne1d": 52, - "ne2d": 286, - "ne3d": 394, - "quality_histogram": "[0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 18, 38, 45, 52, 71, 52, 46, 41, 12, 9]", - "total_badness": 562.08196742 - }, - { - "angles_tet": [ - 23.602, - 139.69 - ], - "angles_trig": [ - 23.844, - 118.54 - ], - "ne1d": 76, - "ne2d": 636, - "ne3d": 1056, - "quality_histogram": "[0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 35, 78, 108, 109, 163, 185, 154, 105, 81, 20]", - "total_badness": 1453.0463737 - }, - { - "angles_tet": [ - 24.173, - 139.41 - ], - "angles_trig": [ - 26.472, - 120.11 - ], - "ne1d": 124, - "ne2d": 1666, - "ne3d": 6448, - "quality_histogram": "[0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 17, 44, 136, 282, 586, 944, 1320, 1470, 1240, 401]", - "total_badness": 7815.6380623 - } - ], "cylsphere.geo": [ { "angles_tet": [ @@ -3422,4 +3330,4 @@ "total_badness": 12938.174838 } ] -} +} \ No newline at end of file diff --git a/tests/utils.py b/tests/utils.py index b4e1784a..9a79e670 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,6 +2,7 @@ import argparse import os import requests import sys +import time from subprocess import check_output from packaging import tags from packaging.utils import parse_wheel_filename @@ -63,6 +64,18 @@ def get_git_version(cwd): return check_output(["git", "describe", "--tags"], cwd=cwd).decode("utf-8").strip() +def get_dev_extension(cwd): + if not is_dev_build(): + return "" + + # if the current commit does not belong to master, build a .dev1 package to avoid name conflicts for subsequent nightly builds from master + try: + check_output(["git", "merge-base", "--is-ancestor", "HEAD", "master"], cwd=cwd) + return ".dev0" + except: + return ".dev1" + + def get_version(cwd): git_version = get_git_version(cwd) @@ -71,8 +84,7 @@ def get_version(cwd): version = version[:2] if len(version) > 1: version = ".post".join(version) - if is_dev_build(): - version += ".dev0" + version += get_dev_extension(cwd) else: version = version[0] @@ -86,6 +98,11 @@ def main(): action="store_true", help="Check if package is on pypi already, fails with exit code 1 if available", ) + parser.add_argument( + "--wait-pip", + action="store_true", + help="Wait until package is on pypi, fails with exit code 1 if still not available after 300s", + ) parser.add_argument( "--get-git-version", action="store_true", @@ -115,6 +132,19 @@ def main(): if is_package_available(args.package, version): print(f"{args.package}=={version} is already on pypi") sys.exit(1) + elif args.wait_pip: + version = get_version(args.dir) + t0 = time.time() + while time.time() - t0 < 300 and not is_package_available( + args.package, version + ): + time.sleep(20) + + if not is_package_available(args.package, version): + print( + f"Timeout waiting for package {args.package}=={version} to be available on pypi" + ) + sys.exit(1) else: print("no action")