Merge branch 'fix_splinesurface' into 'master'

fixes for SplineSurface lifetime, pytest

Sind ein paar fixes für die lifetimes von splinesurfaces. Die CSGeometry speichert jetzt die hinzugefügten SplineSurfaces (damit die shared_ptr nicht sterben)
Ich verwende std::vector für dynamische Arrays von shared_ptrs, da die Netgen Arrays nur mit trivialen Datentypen arbeiten können. (Könnte man evtl die NGSolve Arrays auch in Netgen verfügbar machen)
Der Rest der Änderungen sollte nur meine SplineSurfaces betreffen. 

Habe auch einen pytest hinzugefügt. Habe dafür mit Matthias die tests auch für Netgen aktiviert. 
Da ich das öfters testen musste habe ich die commits jetzt gesquashed

Ich hoffe das passt so.

LG
Christopher

See merge request !35
This commit is contained in:
Joachim Schöberl 2017-02-28 09:16:05 +01:00
commit 8b6e057712
15 changed files with 151 additions and 55 deletions

View File

@ -138,7 +138,12 @@ test_win64:
.template_test_linux: &test_linux .template_test_linux: &test_linux
stage: test stage: test
script: script:
- docker run netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION} bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V"' - >-
docker run
-e NETGENDIR=/opt/netgen/bin
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION}
bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V"'
test_ubuntu_1510: test_ubuntu_1510:
<<: *ubuntu_1510 <<: *ubuntu_1510

View File

@ -257,6 +257,11 @@ execute_process(COMMAND hdiutil create -volname Netgen -srcfolder ${INSTALL_DIR}
") ")
add_custom_target(bundle COMMAND ${CMAKE_COMMAND} "-P" "${CMAKE_CURRENT_BINARY_DIR}/fixup.cmake") add_custom_target(bundle COMMAND ${CMAKE_COMMAND} "-P" "${CMAKE_CURRENT_BINARY_DIR}/fixup.cmake")
####################################################################### #######################################################################
# CTest
enable_testing()
include(CTest)
#######################################################################
add_subdirectory(libsrc) add_subdirectory(libsrc)
add_subdirectory(ng) add_subdirectory(ng)
@ -268,13 +273,9 @@ add_subdirectory(py_tutorials)
add_subdirectory(doc) add_subdirectory(doc)
add_subdirectory(windows) add_subdirectory(windows)
add_subdirectory(nglib) add_subdirectory(nglib)
add_subdirectory(tests)
#######################################################################
# CTest
enable_testing()
include(CTest)
####################################################################### #######################################################################
# Debian packager # Debian packager

View File

@ -10,7 +10,6 @@
#include <myadt.hpp> #include <myadt.hpp>
#include <gprim.hpp> #include <gprim.hpp>
#include <meshing.hpp> #include <meshing.hpp>
// #include <geometry2d.hpp> // #include <geometry2d.hpp>
#include "../gprim/spline.hpp" #include "../gprim/spline.hpp"
#include "../gprim/splinegeometry.hpp" #include "../gprim/splinegeometry.hpp"
@ -21,12 +20,12 @@
#include "solid.hpp" #include "solid.hpp"
#include "identify.hpp" #include "identify.hpp"
#include "singularref.hpp" #include "singularref.hpp"
#include "splinesurface.hpp"
#include "csgeom.hpp" #include "csgeom.hpp"
#include "csgparser.hpp" #include "csgparser.hpp"
#include "triapprox.hpp" #include "triapprox.hpp"
#include "algprim.hpp" #include "algprim.hpp"
#include "splinesurface.hpp"
#include "brick.hpp" #include "brick.hpp"
#include "spline3d.hpp" #include "spline3d.hpp"
#include "manifold.hpp" #include "manifold.hpp"

View File

@ -345,7 +345,25 @@ namespace netgen
const ExtrusionFace * ef = dynamic_cast< const ExtrusionFace * > (GetSurface(i)); const ExtrusionFace * ef = dynamic_cast< const ExtrusionFace * > (GetSurface(i));
const RevolutionFace * rf = dynamic_cast< const RevolutionFace * > (GetSurface(i)); const RevolutionFace * rf = dynamic_cast< const RevolutionFace * > (GetSurface(i));
const DummySurface * dummyf = dynamic_cast< const DummySurface * > (GetSurface(i)); const DummySurface * dummyf = dynamic_cast< const DummySurface * > (GetSurface(i));
const SplineSurface * splines = dynamic_cast<const SplineSurface *> (GetSurface(i));
if (splines)
{
splines->GetBase()->GetPrimitiveData(classname,coeffs);
out << classname << " " << coeffs.Size() << "\n";
for (int j=0; j<coeffs.Size(); j++)
out << coeffs[j] << " ";
out << "\n";
for (auto cut : *(splines->GetCuts()))
{
cut->GetPrimitiveData(classname,coeffs);
out << classname << " " << coeffs.Size() << "\n";
for (int j=0; j<coeffs.Size(); j++)
out << coeffs[j] << " ";
out << "\n";
}
return;
}
if(sp) if(sp)
{ {
@ -819,6 +837,7 @@ namespace netgen
int inv; int inv;
int nsurf = GetNSurf(); int nsurf = GetNSurf();
isidenticto.SetSize(nsurf); isidenticto.SetSize(nsurf);
for (int i = 0; i < nsurf; i++) for (int i = 0; i < nsurf; i++)
isidenticto[i] = i; isidenticto[i] = i;

View File

@ -143,6 +143,9 @@ namespace netgen
/// filename of inputfile /// filename of inputfile
string filename; string filename;
/// store splinesurfaces, such that added ones do not get deleted before geometry does
Array<shared_ptr<SplineSurface>> spline_surfaces;
public: public:
CSGeometry (); CSGeometry ();
CSGeometry (const string & afilename); CSGeometry (const string & afilename);
@ -315,7 +318,9 @@ namespace netgen
virtual int GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam); virtual int GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam);
virtual const Refinement & GetRefinement () const; virtual const Refinement & GetRefinement () const;
void AddSplineSurface (shared_ptr<SplineSurface> ss) { spline_surfaces.Append(ss); }
}; };

View File

@ -491,7 +491,7 @@ namespace netgen
if(splinesurface) if(splinesurface)
{ {
auto name = splinesurface->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p); auto name = splinesurface->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p);
mesh.SetCD2Name(refedges[i].edgenr,*name); mesh.SetCD2Name(refedges[i].edgenr,name);
} }
else else
{ {
@ -499,7 +499,7 @@ namespace netgen
if(splinesurface2) if(splinesurface2)
{ {
auto name = splinesurface2->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p); auto name = splinesurface2->GetBCNameOf(specpoints[startpoints.Get(refedges[i].edgenr)].p,specpoints[endpoints.Get(refedges[i].edgenr)].p);
mesh.SetCD2Name(refedges[i].edgenr,*name); mesh.SetCD2Name(refedges[i].edgenr,name);
} }
} }

View File

@ -207,11 +207,11 @@ DLL_HEADER void ExportCSG(py::module &m)
; ;
py::class_<SplineSurface, shared_ptr<SplineSurface>> (m, "SplineSurface", py::class_<SplineSurface, shared_ptr<SplineSurface>> (m, "SplineSurface",
"A surface for co dim 2 integrals on the splines") "A surface for co dim 2 integrals on the splines")
.def("__init__", FunctionPointer ([](SplineSurface* instance, shared_ptr<SPSolid> base, py::list cuts) .def("__init__", FunctionPointer ([](SplineSurface* instance, shared_ptr<SPSolid> base, py::list cuts)
{ {
auto primitive = dynamic_cast<OneSurfacePrimitive*> (base->GetSolid()->GetPrimitive()); auto primitive = dynamic_cast<OneSurfacePrimitive*> (base->GetSolid()->GetPrimitive());
auto acuts = new Array<OneSurfacePrimitive*>(); auto acuts = make_shared<Array<shared_ptr<OneSurfacePrimitive>>>();
for(int i = 0; i<py::len(cuts);i++) for(int i = 0; i<py::len(cuts);i++)
{ {
py::extract<shared_ptr<SPSolid>> sps(cuts[i]); py::extract<shared_ptr<SPSolid>> sps(cuts[i]);
@ -219,13 +219,14 @@ DLL_HEADER void ExportCSG(py::module &m)
throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!"); throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!");
auto sp = dynamic_cast<OneSurfacePrimitive*>(sps()->GetSolid()->GetPrimitive()); auto sp = dynamic_cast<OneSurfacePrimitive*>(sps()->GetSolid()->GetPrimitive());
if(sp) if(sp)
acuts->Append(sp); acuts->Append(shared_ptr<OneSurfacePrimitive>(sp));
else else
throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!"); throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!");
} }
if(!primitive) if(!primitive)
throw NgException("Base is not a SurfacePrimitive in constructor of SplineSurface!"); throw NgException("Base is not a SurfacePrimitive in constructor of SplineSurface!");
new (instance) SplineSurface(primitive,acuts); new (instance) SplineSurface(shared_ptr<OneSurfacePrimitive>(primitive),acuts);
py::object obj = py::cast(instance);
}),py::arg("base"), py::arg("cuts")=py::list()) }),py::arg("base"), py::arg("cuts")=py::list())
.def("AddPoint", FunctionPointer .def("AddPoint", FunctionPointer
([] (SplineSurface & self, double x, double y, double z, bool hpref) ([] (SplineSurface & self, double x, double y, double z, bool hpref)
@ -237,8 +238,8 @@ DLL_HEADER void ExportCSG(py::module &m)
.def("AddSegment", FunctionPointer .def("AddSegment", FunctionPointer
([] (SplineSurface & self, int i1, int i2, string bcname, double maxh) ([] (SplineSurface & self, int i1, int i2, string bcname, double maxh)
{ {
auto str = new string(bcname); auto seg = make_shared<LineSeg<3>>(self.GetPoint(i1),self.GetPoint(i2));
self.AppendSegment(new LineSeg<3>(self.GetPoint(i1),self.GetPoint(i2)),str,maxh); self.AppendSegment(seg,bcname,maxh);
}), }),
py::arg("pnt1"),py::arg("pnt2"),py::arg("bcname")="default", py::arg("maxh")=-1.) py::arg("pnt1"),py::arg("pnt2"),py::arg("bcname")="default", py::arg("maxh")=-1.)
; ;
@ -433,14 +434,15 @@ DLL_HEADER void ExportCSG(py::module &m)
([] (CSGeometry & self, shared_ptr<SplineSurface> surf) ([] (CSGeometry & self, shared_ptr<SplineSurface> surf)
{ {
auto cuttings = surf->CreateCuttingSurfaces(); auto cuttings = surf->CreateCuttingSurfaces();
auto spsol = make_shared<SPSolid>(new Solid(&*surf)); auto spsol = make_shared<SPSolid>(new Solid(surf.get()));
for(auto cut : (*cuttings)){ for(auto cut : (*cuttings)){
spsol = make_shared<SPSolid>(SPSolid::SECTION,spsol,make_shared<SPSolid>(new Solid(cut))); spsol = make_shared<SPSolid>(SPSolid::SECTION,spsol,make_shared<SPSolid>(new Solid(cut.get())));
} }
spsol->AddSurfaces(self); spsol->AddSurfaces(self);
int tlonr = self.SetTopLevelObject(spsol->GetSolid(), &*surf); int tlonr = self.SetTopLevelObject(spsol->GetSolid(), surf.get());
for(auto p : surf->GetPoints()) for(auto p : surf->GetPoints())
self.AddUserPoint(p); self.AddUserPoint(p);
self.AddSplineSurface(surf);
}), }),
py::arg("SplineSurface")) py::arg("SplineSurface"))

View File

@ -10,14 +10,14 @@ void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const
geompoints.Last().hpref = hpref; geompoints.Last().hpref = hpref;
} }
void SplineSurface :: AppendSegment(SplineSeg<3>* spline, string* bcname, double amaxh) void SplineSurface :: AppendSegment(shared_ptr<SplineSeg<3>> sp, string & bcname, double amaxh)
{ {
splines.Append(spline); splines.Append(sp);
bcnames.Append(bcname); bcnames.Append(bcname);
maxh.Append(amaxh); maxh.Append(amaxh);
} }
string* SplineSurface :: GetBCNameOf (Point<3> p1, Point<3> p2) const string SplineSurface :: GetBCNameOf (Point<3> p1, Point<3> p2) const
{ {
double eps = 1e-5; double eps = 1e-5;
@ -32,36 +32,44 @@ void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const
return bcnames[i]; return bcnames[i];
} }
} }
return new string("default"); return "default";
} }
Array<OneSurfacePrimitive*>* SplineSurface :: CreateCuttingSurfaces() const const shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> SplineSurface :: CreateCuttingSurfaces()
{ {
auto cuttings = new Array<OneSurfacePrimitive*>(); if(all_cuts)
return all_cuts;
auto cuttings = make_shared<Array<shared_ptr<OneSurfacePrimitive>>>();
for (auto cut : *cuts) for (auto cut : *cuts)
cuttings->Append(cut); cuttings->Append(cut);
for(int i = 0; i<splines.Size(); i++) for(int i = 0; i<splines.Size(); i++)
{ {
auto spline = splines[i]; auto spline = splines[i];
auto lineseg = dynamic_cast<LineSeg<3>*>(spline); auto lineseg = dynamic_cast<LineSeg<3>*>(spline.get());
auto p1 = Point<3>(spline->GetPoint(0)); if(lineseg)
Project(p1); {
auto p2 = Point<3>(spline->GetPoint(1)); auto p1 = Point<3>(spline->GetPoint(0));
Project(p2); Project(p1);
auto vec = Vec<3>(p2)-Vec<3>(p1); auto p2 = Point<3>(spline->GetPoint(1));
auto plane = new Plane(p1,-Cross(vec,baseprimitive->GetNormalVector(p1))); Project(p2);
if(maxh[i]>0) auto vec = Vec<3>(p2)-Vec<3>(p1);
{ auto plane = make_shared<Plane>(p1,-Cross(vec,baseprimitive->GetNormalVector(p1)));
plane->SetMaxH(maxh[i]); if(maxh[i]>0)
} {
cuttings->Append(plane); plane->SetMaxH(maxh[i]);
}
cuttings->Append(plane);
}
else
throw NgException("Spline type not implemented for SplineSurface!");
} }
all_cuts = cuttings;
return cuttings; return cuttings;
} }
void SplineSurface :: Print(ostream & str) const void SplineSurface :: Print(ostream & str) const
{ {
str << "SplineSurface " << endl; str << "SplineSurface with base " << *baseprimitive << endl;
} }
} }

View File

@ -8,19 +8,20 @@ namespace netgen
{ {
protected: protected:
Array<GeomPoint<3>> geompoints; Array<GeomPoint<3>> geompoints;
Array<SplineSeg<3>*> splines; Array<shared_ptr<SplineSeg<3>>> splines;
Array<string*> bcnames; Array<string> bcnames;
Array<double> maxh; Array<double> maxh;
OneSurfacePrimitive* baseprimitive; shared_ptr<OneSurfacePrimitive> baseprimitive;
Array<OneSurfacePrimitive*>* cuts; shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> cuts;
shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> all_cuts;
public: public:
SplineSurface(OneSurfacePrimitive* abaseprimitive, Array<OneSurfacePrimitive*>* acuts) : SplineSurface(shared_ptr<OneSurfacePrimitive> abaseprimitive, shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> acuts) :
OneSurfacePrimitive(), baseprimitive(abaseprimitive), cuts(acuts) OneSurfacePrimitive(), baseprimitive(abaseprimitive), cuts(acuts)
{ ; } { ; }
virtual ~SplineSurface() { ; } virtual ~SplineSurface() { ; }
const Array<SplineSeg<3>*> & GetSplines() const { return splines; } const auto & GetSplines() const { return splines; }
int GetNSplines() const { return splines.Size(); } int GetNSplines() const { return splines.Size(); }
const Array<GeomPoint<3>>& GetPoints() const { return geompoints; } const Array<GeomPoint<3>>& GetPoints() const { return geompoints; }
string GetSplineType(const int i) const { return splines[i]->GetType(); } string GetSplineType(const int i) const { return splines[i]->GetType(); }
@ -28,16 +29,15 @@ namespace netgen
const SplineSeg<3> & GetSpline(const int i) const { return *splines[i]; } const SplineSeg<3> & GetSpline(const int i) const { return *splines[i]; }
int GetNP() const { return geompoints.Size(); } int GetNP() const { return geompoints.Size(); }
const GeomPoint<3> & GetPoint(int i) const { return geompoints[i]; } const GeomPoint<3> & GetPoint(int i) const { return geompoints[i]; }
string* GetBCName(int i) const { return bcnames[i]; } string GetBCName(int i) const { return bcnames[i]; }
string* GetBCNameOf(Point<3> p1, Point<3> p2) const; string GetBCNameOf(Point<3> p1, Point<3> p2) const;
DLL_HEADER void AppendPoint(const Point<3> & p, const double reffac = 1., const bool hpref=false); DLL_HEADER void AppendPoint(const Point<3> & p, const double reffac = 1., const bool hpref=false);
void AppendSegment(SplineSeg<3>* spline, string* bcname, double amaxh = -1); void AppendSegment(shared_ptr<SplineSeg<3>> spline, string & bcname, double amaxh = -1);
OneSurfacePrimitive* GetBase() const { return baseprimitive; }
Array<OneSurfacePrimitive*>* CreateCuttingSurfaces() const;
const shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> CreateCuttingSurfaces();
const shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> GetCuts() const { return all_cuts; }
const shared_ptr<OneSurfacePrimitive> GetBase() const { return baseprimitive; }
virtual void Project (Point<3> & p3d) const { baseprimitive->Project(p3d); } virtual void Project (Point<3> & p3d) const { baseprimitive->Project(p3d); }
virtual double CalcFunctionValue (const Point<3> & point) const virtual double CalcFunctionValue (const Point<3> & point) const

View File

@ -75,7 +75,7 @@ namespace netgen
(*testout) << "Meshing subdomain " << k << endl; (*testout) << "Meshing subdomain " << k << endl;
mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k)); mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k));
mesh3d.CalcSurfacesOfNode(); mesh3d.CalcSurfacesOfNode();
mesh3d.FindOpenElements(k); mesh3d.FindOpenElements(k);

1
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory(pytest)

View File

@ -1,4 +1,4 @@
FROM ubuntu:15.10 FROM ubuntu:15.10
MAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at> MAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>
RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev libboost-python-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy
ADD . /root/src/netgen ADD . /root/src/netgen

View File

@ -1,4 +1,4 @@
FROM ubuntu:16.04 FROM ubuntu:16.04
MAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at> MAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>
RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev libboost-python-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy
ADD . /root/src/netgen ADD . /root/src/netgen

View File

@ -0,0 +1,4 @@
if(USE_PYTHON)
add_test(NAME pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(pytest ${PYTHON_EXECUTABLE} -m pytest WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif(USE_PYTHON)

View File

@ -0,0 +1,52 @@
from netgen.csg import *
from netgen import meshing
import filecmp
import difflib
from math import sqrt, cos, sin
def CreateQuad():
base = Plane(Pnt(0,0,0),Vec(0,0,1))
surface = SplineSurface(base)
pts = [(-0.2,-0.2,0),(-0.2,0.2,0),(0.2,0.2,0),(0.2,-0.2,0)]
geopts = [surface.AddPoint(*p) for p in pts]
for p1,p2,bc in [(0,1,"wire"), (1, 2,"contact"),(2,3,"wire"),(3,0,"wire")]:
surface.AddSegment(geopts[p1],geopts[p2],bc)
return surface
Cross = lambda a,b: [a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-b[0]*a[1]]
def CreateGeo():
geo = CSGeometry()
air = OrthoBrick(Pnt(-1,-1,-1),Pnt(1,1,1))
geo.Add(air.mat("air"))
surface = CreateQuad()
geo.AddSplineSurface(surface)
return geo
def test_BBNDsave():
mesh = CreateGeo().GenerateMesh(maxh=0.4,perfstepsend = meshing.MeshingStep.MESHSURFACE)
for i in range(2):
mesh.GenerateVolumeMesh(mp = MeshingParameters(only3D_domain=i+1,maxh=0.4))
mesh.SetGeometry(None)
mesh.Save("test.vol")
mesh2 = meshing.Mesh()
mesh2.Load("test.vol")
mesh2.Save("test2.vol")
with open("test.vol","r") as f:
first = f.readlines()
with open("test2.vol","r") as f:
second = f.readlines()
# exclude the face colours section (because they aren't in the same order)
for i,line in enumerate(first):
if line[0:12] == "face_colours":
first = first[0:i]
second = second[0:i]
break
diff = difflib.context_diff(first,second)
print("File diff:")
l = list(diff)
print(*l)
assert len(l)==0