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
stage: test
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:
<<: *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")
#######################################################################
# CTest
enable_testing()
include(CTest)
#######################################################################
add_subdirectory(libsrc)
add_subdirectory(ng)
@ -268,13 +273,9 @@ add_subdirectory(py_tutorials)
add_subdirectory(doc)
add_subdirectory(windows)
add_subdirectory(nglib)
add_subdirectory(tests)
#######################################################################
# CTest
enable_testing()
include(CTest)
#######################################################################
# Debian packager

View File

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

View File

@ -345,7 +345,25 @@ namespace netgen
const ExtrusionFace * ef = dynamic_cast< const ExtrusionFace * > (GetSurface(i));
const RevolutionFace * rf = dynamic_cast< const RevolutionFace * > (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)
{
@ -819,6 +837,7 @@ namespace netgen
int inv;
int nsurf = GetNSurf();
isidenticto.SetSize(nsurf);
for (int i = 0; i < nsurf; i++)
isidenticto[i] = i;

View File

@ -143,6 +143,9 @@ namespace netgen
/// filename of inputfile
string filename;
/// store splinesurfaces, such that added ones do not get deleted before geometry does
Array<shared_ptr<SplineSurface>> spline_surfaces;
public:
CSGeometry ();
CSGeometry (const string & afilename);
@ -315,7 +318,9 @@ namespace netgen
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)
{
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
{
@ -499,7 +499,7 @@ namespace netgen
if(splinesurface2)
{
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",
"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)
{
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++)
{
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!");
auto sp = dynamic_cast<OneSurfacePrimitive*>(sps()->GetSolid()->GetPrimitive());
if(sp)
acuts->Append(sp);
acuts->Append(shared_ptr<OneSurfacePrimitive>(sp));
else
throw NgException("Cut must be SurfacePrimitive in constructor of SplineSurface!");
}
if(!primitive)
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())
.def("AddPoint", FunctionPointer
([] (SplineSurface & self, double x, double y, double z, bool hpref)
@ -237,8 +238,8 @@ DLL_HEADER void ExportCSG(py::module &m)
.def("AddSegment", FunctionPointer
([] (SplineSurface & self, int i1, int i2, string bcname, double maxh)
{
auto str = new string(bcname);
self.AppendSegment(new LineSeg<3>(self.GetPoint(i1),self.GetPoint(i2)),str,maxh);
auto seg = make_shared<LineSeg<3>>(self.GetPoint(i1),self.GetPoint(i2));
self.AppendSegment(seg,bcname,maxh);
}),
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)
{
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)){
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);
int tlonr = self.SetTopLevelObject(spsol->GetSolid(), &*surf);
int tlonr = self.SetTopLevelObject(spsol->GetSolid(), surf.get());
for(auto p : surf->GetPoints())
self.AddUserPoint(p);
self.AddSplineSurface(surf);
}),
py::arg("SplineSurface"))

View File

@ -10,14 +10,14 @@ void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const
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);
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;
@ -32,36 +32,44 @@ void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const
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)
cuttings->Append(cut);
for(int i = 0; i<splines.Size(); i++)
{
auto spline = splines[i];
auto lineseg = dynamic_cast<LineSeg<3>*>(spline);
auto p1 = Point<3>(spline->GetPoint(0));
Project(p1);
auto p2 = Point<3>(spline->GetPoint(1));
Project(p2);
auto vec = Vec<3>(p2)-Vec<3>(p1);
auto plane = new Plane(p1,-Cross(vec,baseprimitive->GetNormalVector(p1)));
if(maxh[i]>0)
{
plane->SetMaxH(maxh[i]);
}
cuttings->Append(plane);
auto lineseg = dynamic_cast<LineSeg<3>*>(spline.get());
if(lineseg)
{
auto p1 = Point<3>(spline->GetPoint(0));
Project(p1);
auto p2 = Point<3>(spline->GetPoint(1));
Project(p2);
auto vec = Vec<3>(p2)-Vec<3>(p1);
auto plane = make_shared<Plane>(p1,-Cross(vec,baseprimitive->GetNormalVector(p1)));
if(maxh[i]>0)
{
plane->SetMaxH(maxh[i]);
}
cuttings->Append(plane);
}
else
throw NgException("Spline type not implemented for SplineSurface!");
}
all_cuts = cuttings;
return cuttings;
}
void SplineSurface :: Print(ostream & str) const
{
str << "SplineSurface " << endl;
str << "SplineSurface with base " << *baseprimitive << endl;
}
}

View File

@ -8,19 +8,20 @@ namespace netgen
{
protected:
Array<GeomPoint<3>> geompoints;
Array<SplineSeg<3>*> splines;
Array<string*> bcnames;
Array<shared_ptr<SplineSeg<3>>> splines;
Array<string> bcnames;
Array<double> maxh;
OneSurfacePrimitive* baseprimitive;
Array<OneSurfacePrimitive*>* cuts;
shared_ptr<OneSurfacePrimitive> baseprimitive;
shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> cuts;
shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> all_cuts;
public:
SplineSurface(OneSurfacePrimitive* abaseprimitive, Array<OneSurfacePrimitive*>* acuts) :
SplineSurface(shared_ptr<OneSurfacePrimitive> abaseprimitive, shared_ptr<Array<shared_ptr<OneSurfacePrimitive>>> acuts) :
OneSurfacePrimitive(), baseprimitive(abaseprimitive), cuts(acuts)
{ ; }
virtual ~SplineSurface() { ; }
const Array<SplineSeg<3>*> & GetSplines() const { return splines; }
const auto & GetSplines() const { return splines; }
int GetNSplines() const { return splines.Size(); }
const Array<GeomPoint<3>>& GetPoints() const { return geompoints; }
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]; }
int GetNP() const { return geompoints.Size(); }
const GeomPoint<3> & GetPoint(int i) const { return geompoints[i]; }
string* GetBCName(int i) const { return bcnames[i]; }
string* GetBCNameOf(Point<3> p1, Point<3> p2) const;
string GetBCName(int i) const { return bcnames[i]; }
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);
void AppendSegment(SplineSeg<3>* spline, string* bcname, double amaxh = -1);
OneSurfacePrimitive* GetBase() const { return baseprimitive; }
Array<OneSurfacePrimitive*>* CreateCuttingSurfaces() const;
void AppendSegment(shared_ptr<SplineSeg<3>> spline, string & bcname, double amaxh = -1);
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 double CalcFunctionValue (const Point<3> & point) const

View File

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

View File

@ -1,4 +1,4 @@
FROM ubuntu:16.04
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

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