netgen/libsrc/geom2d/geometry2d.cpp
Monty Montgomery de7ffc5906 Eliminate a "C++ initialization order fiasco" for geometryregister
Current initialization of the global geometryregister suffers from a
classic 'initialization order fiasco'.  Depending on the order the
compilation units are loaded/linked, the initialization of the global
geometryregisterarray is not guaranteed to happen (and indeed often
does not happen) before it is used.  This leads to entries being
appended before it's initialized (usually 'suceeding, but potentially
causing memory corruption if the segment at that point isn't zeroed),
initialization then happening halfway through (wiping the initial
entries) and then the last entries being the only ones that show up.

The net effect is either a crash at startup, or several geometry types
seeming to be missing.  Eg, step files will oad, but STL files are
just ignored.  The bug is actively observed on, eg, Linux.

This patch implements a simple 'initialize at first access' convention
for the array, eliminating the ordering problem.

I've not reviewed the rest of the source for other potential examples
of the fiasco pattern; this fixes only the geometryregister, since
that was actively biting.
2022-05-22 11:29:10 -04:00

1112 lines
25 KiB
C++

/*
2d Spline curve for Mesh generator
*/
#include <meshing.hpp>
#include <geometry2d.hpp>
#include <core/register_archive.hpp>
namespace netgen
{
SplineGeometry2d :: ~SplineGeometry2d()
{
for ( int i = 0; i < bcnames.Size(); i++ )
delete bcnames[i];
for (int i=0; i<materials.Size(); i++)
delete [] materials[i];
}
void SplineGeometry2d :: PointBetweenEdge(const Point<3> & p1, const Point<3> & p2, double secpoint,
int surfi1, int surfi2,
const EdgePointGeomInfo & ap1,
const EdgePointGeomInfo & ap2,
Point<3> & newp, EdgePointGeomInfo & newgi) const
{
Point<2> p2d;
double newdist;
auto spline = GetSplines().Get(ap1.edgenr);
if( (ap1.dist == 0.0) && (ap2.dist == 0.0) )
{
// used for manually generated meshes
const SplineSeg3<2> * ss3;
const LineSeg<2> * ls;
auto ext = dynamic_cast<const SplineSegExt *>(spline);
if(ext)
{
ss3 = dynamic_cast<const SplineSeg3<2> *>(ext->seg);
ls = dynamic_cast<const LineSeg<2> *>(ext->seg);
}
else
{
ss3 = dynamic_cast<const SplineSeg3<2> *>(spline);
ls = dynamic_cast<const LineSeg<2> *>(spline);
}
Point<2> p12d(p1(0),p1(1)), p22d(p2(0),p2(1));
Point<2> p1_proj(0.0,0.0), p2_proj(0.0,0.0);
double t1_proj = 0.0;
double t2_proj = 0.0;
if(ss3)
{
ss3->Project(p12d,p1_proj,t1_proj);
ss3->Project(p22d,p2_proj,t2_proj);
}
else if(ls)
{
ls->Project(p12d,p1_proj,t1_proj);
ls->Project(p22d,p2_proj,t2_proj);
}
p2d = spline->GetPoint (((1-secpoint)*t1_proj+secpoint*t2_proj));
newdist = (1-secpoint)*t1_proj+secpoint*t2_proj;
}
else
{
p2d = spline->GetPoint (((1-secpoint)*ap1.dist+secpoint*ap2.dist));
newdist = (1-secpoint)*ap1.dist+secpoint*ap2.dist;
}
// (*testout) << "refine 2d line, ap1.dist, ap2.dist = " << ap1.dist << ", " << ap2.dist << endl;
// (*testout) << "p1, p2 = " << p1 << p2 << ", newp = " << p2d << endl;
newp = Point3d (p2d(0), p2d(1), 0);
newgi.edgenr = ap1.edgenr;
newgi.dist = newdist;
};
Vec<3> SplineGeometry2d :: GetTangent(const Point<3> & p, int surfi1, int surfi2,
const EdgePointGeomInfo & ap1) const
{
Vec<2> t2d = GetSplines().Get(ap1.edgenr) -> GetTangent(ap1.dist);
return Vec<3> (t2d(0), t2d(1), 0);
}
Vec<3> SplineGeometry2d :: GetNormal(int surfi1, const Point<3> & p,
const PointGeomInfo* gi) const
{
return Vec<3> (0,0,1);
}
void SplineGeometry2d :: Load (const filesystem::path & filename)
{
ifstream infile;
Point<2> x;
char buf[50];
infile.open (filename);
if ( ! infile.good() )
throw NgException(string ("Input file '") +
filename.string() +
string ("' not available!"));
TestComment ( infile );
infile >> buf; // file recognition
tensormeshing.SetSize(0);
quadmeshing.SetSize(0);
TestComment ( infile );
if ( strcmp (buf, "splinecurves2dnew") == 0 )
{
LoadDataNew ( infile );
}
else if ( strcmp (buf, "splinecurves2dv2") == 0 )
{
LoadDataV2 ( infile );
}
else
{
LoadData(infile );
}
infile.close();
}
// herbert: fixed TestComment
void SplineGeometry2d :: TestComment ( ifstream & infile )
{
bool comment = true;
char ch;
while ( comment == true && !infile.eof() ) {
infile.get(ch);
if ( ch == '#' ) { // skip comments
while ( ch != '\n' && !infile.eof() ) {
infile.get(ch);
}
}
else if ( ch == '\n' ) { // skip empty lines
;
}
else if ( isspace(ch) ) { // skip whitespaces
;
}
else { // end of comment
infile.putback(ch);
comment = false;
}
}
return;
}
void SplineGeometry2d :: LoadData ( ifstream & infile )
{
enum { D = 2 };
int nump, numseg, leftdom, rightdom;
Point<D> x;
int hi1, hi2, hi3;
double hd;
char buf[50], ch;
materials.SetSize(0);
maxh.SetSize(0);
infile >> elto0;
TestComment ( infile );
infile >> nump;
for (int i = 0; i < nump; i++)
{
TestComment ( infile );
for(int j=0; j<D; j++)
infile >> x(j);
infile >> hd;
Flags flags;
ch = 'a';
// infile >> ch;
do {
infile.get (ch);
} while (isspace(ch) && ch != '\n');
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
do {
infile.get (ch);
} while (isspace(ch) && ch != '\n');
}
if (infile.good())
infile.putback (ch);
geompoints.Append (GeomPoint<D>(x, hd));
geompoints.Last().hpref = flags.GetDefineFlag ("hpref");
geompoints.Last().hmax = flags.GetNumFlag("hmax", 1e99);
}
PrintMessage (3, nump, " points loaded");
TestComment ( infile );
infile >> numseg;
bcnames.SetSize(numseg);
for ( int i = 0; i < numseg; i++ )
bcnames[i] = 0; // "default";
SplineSeg<D> * spline = 0;
PrintMessage (3, numseg, " segments loaded");
for (int i = 0; i < numseg; i++)
{
TestComment ( infile );
infile >> leftdom >> rightdom;
// cout << "add spline " << i << ", left = " << leftdom << ", right = " << rightdom << endl;
infile >> buf;
// type of spline segment
if (strcmp (buf, "2") == 0)
{ // a line
infile >> hi1 >> hi2;
spline = new LineSeg<D>(geompoints[hi1-1],
geompoints[hi2-1]);
}
else if (strcmp (buf, "3") == 0)
{ // a rational spline
infile >> hi1 >> hi2 >> hi3;
spline = new SplineSeg3<D> (geompoints[hi1-1],
geompoints[hi2-1],
geompoints[hi3-1]);
}
else if (strcmp (buf, "4") == 0)
{ // an arc
infile >> hi1 >> hi2 >> hi3;
spline = new CircleSeg<D> (geompoints[hi1-1],
geompoints[hi2-1],
geompoints[hi3-1]);
// break;
}
else if (strcmp (buf, "discretepoints") == 0)
{
int npts;
infile >> npts;
NgArray< Point<D> > pts(npts);
for (int j = 0; j < npts; j++)
for(int k=0; k<D; k++)
infile >> pts[j](k);
spline = new DiscretePointsSeg<D> (pts);
}
SplineSegExt * spex = new SplineSegExt (*spline);
infile >> spex->reffak;
spex -> leftdom = leftdom;
spex -> rightdom = rightdom;
splines.Append (spex);
Flags flags;
ch = 'a';
infile >> ch;
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
infile >> ch;
}
if (infile.good())
infile.putback (ch);
spex->bc = int (flags.GetNumFlag ("bc", i+1));
spex->hpref_left = int (flags.GetDefineFlag ("hpref")) ||
int (flags.GetDefineFlag ("hprefleft"));
spex->hpref_right = int (flags.GetDefineFlag ("hpref")) ||
int (flags.GetDefineFlag ("hprefright"));
spex->copyfrom = int (flags.GetNumFlag ("copy", -1));
if ( flags.StringFlagDefined("bcname") )
{
int mybc = spex->bc-1;
delete bcnames[mybc];
bcnames[mybc] = new string (flags.GetStringFlag("bcname","") );
}
spex -> hmax = flags.GetNumFlag("hmax", 1e99);
}
}
void SplineGeometry2d :: LoadDataNew ( ifstream & infile )
{
enum { D = 2 };
int nump, numseg, leftdom, rightdom;
Point<D> x;
int hi1, hi2, hi3;
double hd;
char buf[50], ch;
int pointnr;
TestComment ( infile );
infile >> elto0;
TestComment ( infile );
infile >> nump;
geompoints.SetSize(nump);
for (int i = 0; i < nump; i++)
{
TestComment ( infile );
infile >> pointnr;
if ( pointnr > nump )
{
throw NgException(string ("Point number greater than total number of points") );
}
for(int j=0; j<D; j++)
infile >> x(j);
// hd is now optional, default 1
// infile >> hd;
hd = 1;
Flags flags;
// get flags,
ch = 'a';
// infile >> ch;
do
{
infile.get (ch);
// if another int-value, set refinement flag to this value
// (corresponding to old files)
if ( int (ch) >= 48 && int(ch) <= 57 )
{
infile.putback(ch);
infile >> hd;
infile.get(ch);
}
}
while (isspace(ch) && ch != '\n');
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
do {
infile.get (ch);
} while (isspace(ch) && ch != '\n');
}
if (infile.good())
infile.putback (ch);
if ( hd == 1 )
hd = flags.GetNumFlag ( "ref", 1.0);
// geompoints.Append (GeomPoint<D>(x, hd));
geompoints[pointnr-1] = GeomPoint<D>(x, hd);
geompoints[pointnr-1].hpref = flags.GetDefineFlag ("hpref");
}
TestComment ( infile );
infile >> numseg;
bcnames.SetSize(numseg);
for ( int i = 0; i < numseg; i++ )
bcnames[i] = 0;//new"default";
SplineSeg<D> * spline = 0;
for (int i = 0; i < numseg; i++)
{
TestComment ( infile );
infile >> leftdom >> rightdom;
// cout << "add spline " << i << ", left = " << leftdom << endl;
infile >> buf;
// type of spline segment
if (strcmp (buf, "2") == 0)
{ // a line
infile >> hi1 >> hi2;
spline = new LineSeg<D> (geompoints[hi1-1],
geompoints[hi2-1]);
}
else if (strcmp (buf, "3") == 0)
{ // a rational spline
infile >> hi1 >> hi2 >> hi3;
spline = new SplineSeg3<D> (geompoints[hi1-1],
geompoints[hi2-1],
geompoints[hi3-1]);
}
else if (strcmp (buf, "4") == 0)
{ // an arc
infile >> hi1 >> hi2 >> hi3;
spline = new CircleSeg<D> (geompoints[hi1-1],
geompoints[hi2-1],
geompoints[hi3-1]);
// break;
}
else if (strcmp (buf, "discretepoints") == 0)
{
int npts;
infile >> npts;
NgArray< Point<D> > pts(npts);
for (int j = 0; j < npts; j++)
for(int k=0; k<D; k++)
infile >> pts[j](k);
spline = new DiscretePointsSeg<D> (pts);
}
// infile >> spline->reffak;
SplineSegExt * spex = new SplineSegExt (*spline);
spex -> leftdom = leftdom;
spex -> rightdom = rightdom;
splines.Append (spex);
// hd is now optional, default 1
// infile >> hd;
hd = 1;
infile >> ch;
// get refinement parameter, if it is there
// infile.get (ch);
// if another int-value, set refinement flag to this value
// (corresponding to old files)
if ( int (ch) >= 48 && int(ch) <= 57 )
{
infile.putback(ch);
infile >> hd;
infile >> ch ;
}
Flags flags;
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
infile >> ch;
}
if (infile.good())
infile.putback (ch);
spex->bc = int (flags.GetNumFlag ("bc", i+1));
spex->hpref_left = int (flags.GetDefineFlag ("hpref")) ||
int (flags.GetDefineFlag ("hprefleft"));
spex->hpref_right = int (flags.GetDefineFlag ("hpref")) ||
int (flags.GetDefineFlag ("hprefright"));
spex->copyfrom = int (flags.GetNumFlag ("copy", -1));
spex->reffak = flags.GetNumFlag ("ref", 1 );
spex->hmax = flags.GetNumFlag ("maxh", 1e99 );
if ( flags.StringFlagDefined("bcname") )
{
int mybc = spex->bc-1;
if ( bcnames[mybc] ) delete bcnames[mybc];
bcnames[mybc] = new string (flags.GetStringFlag("bcname","") );
}
if ( hd != 1 )
spex->reffak = hd;
}
if ( !infile.good() )
return;
TestComment ( infile );
int numdomains;
int domainnr;
char material[100];
if ( !infile.good() )
return;
infile >> numdomains;
materials.SetSize(numdomains) ;
maxh.SetSize ( numdomains ) ;
maxh = 1e99;
TestComment ( infile );
for ( int i=0; i<numdomains; i++)
materials [ i ] = new char (100);
for ( int i=0; i<numdomains && infile.good(); i++)
{
TestComment ( infile );
infile >> domainnr;
infile >> material;
strcpy(materials[domainnr-1], material);
Flags flags;
ch = 'a';
infile >> ch;
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
infile >> ch;
}
if (infile.good())
infile.putback (ch);
maxh[domainnr-1] = flags.GetNumFlag ( "maxh", 1e99);
}
return;
}
void SplineGeometry2d :: LoadDataV2 ( ifstream & infile )
{
enum { D = 2 };
// new parser by Astrid Sinwel
PrintMessage (1, "Load 2D Geometry V2");
int nump, leftdom, rightdom;
Point<D> x;
int hi1, hi2, hi3;
double hd;
char buf[50], ch;
int pointnr;
string keyword;
NgArray < GeomPoint<D> > infilepoints (0);
NgArray <int> pointnrs (0);
nump = 0;
int numdomains = 0;
TestComment ( infile );
// refinement factor
infile >> elto0;
TestComment ( infile );
// test if next ch is a letter, i.e. new keyword starts
bool ischar = false;
while ( infile.good() )
{
infile >> keyword;
ischar = false;
if ( keyword == "points" )
{
PrintMessage (3, "load points");
infile.get(ch);
infile.putback(ch);
// test if ch is a letter
if ( int(ch) >= 65 && int(ch) <=90 )
ischar = true;
if ( int(ch) >= 97 && int(ch) <= 122 )
ischar = true;
while ( ! ischar )
{
TestComment ( infile );
infile >> pointnr;
// pointnrs 1-based
if ( pointnr > nump ) nump = pointnr;
pointnrs.Append(pointnr);
for(int j=0; j<D; j++)
infile >> x(j);
// hd is now optional, default 1
// infile >> hd;
hd = 1;
Flags flags;
// get flags,
ch = 'a';
// infile >> ch;
do
{
infile.get (ch);
// if another int-value, set refinement flag to this value
// (corresponding to old files)
if ( int (ch) >= 48 && int(ch) <= 57 )
{
infile.putback(ch);
infile >> hd;
infile.get(ch);
}
}
while (isspace(ch) && ch != '\n');
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
do {
infile.get (ch);
} while (isspace(ch) && ch != '\n');
}
if (infile.good())
infile.putback (ch);
if ( hd == 1 )
hd = flags.GetNumFlag ( "ref", 1.0);
// geompoints.Append (GeomPoint<D>(x, hd));
infilepoints.Append ( GeomPoint<D>(x, hd) );
infilepoints.Last().hpref = flags.GetDefineFlag ("hpref");
infilepoints.Last().hmax = flags.GetNumFlag ("maxh", 1e99);
TestComment(infile);
infile.get(ch);
infile.putback(ch);
// test if letter
if ( int(ch) >= 65 && int(ch) <=90 )
ischar = true;
if ( int(ch) >= 97 && int(ch) <= 122 )
ischar = true;
}
// infile.putback (ch);
geompoints.SetSize(nump);
for ( int i = 0; i < nump; i++ )
{
geompoints[pointnrs[i] - 1] = infilepoints[i];
geompoints[pointnrs[i] - 1].hpref = infilepoints[i].hpref;
}
TestComment(infile);
}
else if ( keyword == "segments" )
{
PrintMessage (3, "load segments");
bcnames.SetSize(0);
infile.get(ch);
infile.putback(ch);
int i = 0;
// test if ch is a letter
if ( int(ch) >= 65 && int(ch) <=90 )
ischar = true;
if ( int(ch) >= 97 && int(ch) <= 122 )
ischar = true;
while ( !ischar ) //ch != 'p' && ch != 'm' )
{
i++;
TestComment ( infile );
SplineSeg<D> * spline = 0;
TestComment ( infile );
infile >> leftdom >> rightdom;
if ( leftdom > numdomains ) numdomains = leftdom;
if ( rightdom > numdomains ) numdomains = rightdom;
infile >> buf;
// type of spline segment
if (strcmp (buf, "2") == 0)
{ // a line
infile >> hi1 >> hi2;
spline = new LineSeg<D>(geompoints[hi1-1],
geompoints[hi2-1]);
}
else if (strcmp (buf, "3") == 0)
{ // a rational spline
infile >> hi1 >> hi2 >> hi3;
spline = new SplineSeg3<D> (geompoints[hi1-1],
geompoints[hi2-1],
geompoints[hi3-1]);
}
else if (strcmp (buf, "4") == 0)
{ // an arc
infile >> hi1 >> hi2 >> hi3;
spline = new CircleSeg<D> (geompoints[hi1-1],
geompoints[hi2-1],
geompoints[hi3-1]);
}
else if (strcmp (buf, "discretepoints") == 0)
{
int npts;
infile >> npts;
NgArray< Point<D> > pts(npts);
for (int j = 0; j < npts; j++)
for(int k=0; k<D; k++)
infile >> pts[j](k);
spline = new DiscretePointsSeg<D> (pts);
}
else if (strcmp (buf, "bsplinepoints") == 0)
{
int npts,order;
infile >> npts;
infile >> order;
NgArray< Point<D> > pts(npts);
for (int j = 0; j < npts; j++)
for(int k=0; k<D; k++)
infile >> pts[j](k);
if(order<2)
cerr<<"Minimum order of 2 is required!!"<<endl;
else if(order==2)
spline = new BSplineSeg<D,2> (pts);
else if(order==3)
spline = new BSplineSeg<D,3> (pts);
else if(order==4)
spline = new BSplineSeg<D,4> (pts);
else if(order>4)
cerr<<"Maximum allowed order is 4!!"<<endl;
}
// infile >> spline->reffak;
SplineSegExt * spex = new SplineSegExt (*spline);
spex -> leftdom = leftdom;
spex -> rightdom = rightdom;
splines.Append (spex);
// hd is now optional, default 1
// infile >> hd;
hd = 1;
infile >> ch;
// get refinement parameter, if it is there
//infile.get (ch);
// if another int-value, set refinement flag to this value
// (corresponding to old files)
/*
if ( int (ch) >= 48 && int(ch) <= 57 )
{
infile.putback(ch);
infile >> hd;
infile >> ch ;
}
*/
// get flags,
Flags flags;
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
infile >> ch;
}
if (infile.good())
infile.putback (ch);
spex->bc = int (flags.GetNumFlag ("bc", i+1));
spex->hpref_left = int (flags.GetDefineFlag ("hpref")) ||
int (flags.GetDefineFlag ("hprefleft"));
spex->hpref_right = int (flags.GetDefineFlag ("hpref")) ||
int (flags.GetDefineFlag ("hprefright"));
spex->copyfrom = int (flags.GetNumFlag ("copy", -1));
spex->reffak = flags.GetNumFlag ("ref", 1 );
spex->hmax = flags.GetNumFlag ("maxh", 1e99 );
if ( hd != 1 ) spex->reffak = hd;
if ( flags.StringFlagDefined("bcname") )
{
int mybc = spex->bc-1;
for ( int ii = bcnames.Size(); ii <= mybc; ii++ )
bcnames.Append ( new string ("default"));
if ( bcnames[mybc] ) delete bcnames[mybc];
bcnames[mybc] = new string (flags.GetStringFlag("bcname","") );
}
TestComment(infile);
infile.get(ch);
infile.putback(ch);
// test if ch is a letter
if ( int(ch) >= 65 && int(ch) <=90 )
ischar = true;
if ( int(ch) >= 97 && int(ch) <= 122 )
ischar = true;
}
infile.get(ch);
infile.putback(ch);
}
else if ( keyword == "materials" )
{
TestComment ( infile );
int domainnr;
char material[100];
if ( !infile.good() )
return;
materials.SetSize(numdomains) ;
maxh.SetSize ( numdomains ) ;
for ( int i = 0; i < numdomains; i++)
maxh[i] = 1000;
quadmeshing.SetSize ( numdomains );
quadmeshing = false;
tensormeshing.SetSize ( numdomains );
tensormeshing = false;
layer.SetSize ( numdomains );
layer = 1;
TestComment ( infile );
for ( int i=0; i<numdomains; i++)
materials [ i ] = new char[100];
for ( int i=0; i<numdomains && infile.good(); i++)
{
TestComment ( infile );
infile >> domainnr;
infile >> material;
strcpy (materials[domainnr-1], material);
Flags flags;
ch = 'a';
infile >> ch;
while (ch == '-')
{
char flag[100];
flag[0]='-';
infile >> (flag+1);
flags.SetCommandLineFlag (flag);
ch = 'a';
infile >> ch;
}
if (infile.good())
infile.putback (ch);
maxh[domainnr-1] = flags.GetNumFlag ( "maxh", 1000);
if (flags.GetDefineFlag("quad")) quadmeshing[domainnr-1] = true;
if (flags.GetDefineFlag("tensor")) tensormeshing[domainnr-1] = true;
layer[domainnr-1] = int(flags.GetNumFlag ("layer", 1));
}
}
}
return;
}
/*
void CalcPartition (const SplineSegExt & spline,
double l, double h, double h1, double h2,
double hcurve, double elto0, NgArray<double> & points)
{
double fperel, oldf, f;
int n = 1000;
points.SetSize (0);
double dt = l / n;
double sum = 0;
for (int i = 1; i <= n; i++)
{
double t = (i-0.5)*dt;
double fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2);
double curv = spline.CalcCurvature (t/l);
cout << "curv = " << curv << endl;
if (curv < 1e-10) curv = 1e-10;
fun = min2 (fun, 0.1/curv);
sum += dt / fun;
}
int nel = int (sum+1);
fperel = sum / nel;
points.Append (0);
int i = 1;
oldf = 0;
// t = 0.5 * dt;
for (int j = 1; j <= n && i < nel; j++)
{
double t = (j-0.5)*dt;
double fun = min3 (hcurve, t/elto0 + h1, (l-t)/elto0 + h2);
double curv = spline.CalcCurvature (t/l);
if (curv < 1e-10) curv = 1e-10;
fun = min2 (fun, 0.1/curv);
f = oldf + dt / fun;
while (i * fperel < f && i < nel)
{
points.Append ( dt * (j-1) + (i * fperel - oldf) * fun);
i++;
}
oldf = f;
t += dt;
}
points.Append (l);
}
*/
void SplineGeometry2d :: SetBCName (int bcnr, string name)
{
if (bcnr < 1)
throw NgException ("Illegal nr in SetBCName");
int new_to_add = bcnr - bcnames.Size();
for (int i = 0; i < new_to_add; i++)
bcnames.Append (new string("default"));
delete bcnames[bcnr-1];
bcnames[bcnr-1] = new string(name);
}
string SplineGeometry2d :: GetBCName( int bcnr ) const
{
if (bcnames.Size() >= bcnr)
if (bcnames[bcnr-1] )
return *bcnames[bcnr-1];
return "default";
}
string * SplineGeometry2d :: BCNamePtr( int bcnr )
{
if ( bcnr > bcnames.Size() )
return nullptr;
else
return bcnames[bcnr-1];
}
int SplineGeometry2d :: GetBCNumber (string name) const
{
for (int i = 0; i < bcnames.Size(); i++)
if (*bcnames[i] == name)
return i+1;
return 0;
}
int SplineGeometry2d :: AddBCName (string name)
{
bcnames.Append (new string(name));
return bcnames.Size();
}
void SplineGeometry2d :: GetMaterial (int domnr, char* & material )
{
if ( materials.Size() >= domnr)
material = materials[domnr-1];
else
material = 0;
}
void SplineGeometry2d :: SetMaterial (int domnr, const string & material)
{
int oldsize = materials.Size();
if (domnr > materials.Size()) materials.SetSize (domnr);
for (int i = oldsize; i < domnr; i++)
materials[i] = nullptr;
if (domnr >= 1) // && domnr <= materials.Size())
{
delete materials[domnr-1];
materials[domnr-1] = new char[material.size()+1];
strcpy(materials[domnr-1], material.c_str());
}
else
throw NgException ("material index out of range");
}
double SplineGeometry2d :: GetDomainMaxh (const int domnr )
{
if ( maxh.Size() >= domnr && domnr > 0)
return maxh[domnr-1];
else
return -1;
}
void SplineGeometry2d :: SetDomainMaxh (int domnr, double h)
{
int oldsize = maxh.Size();
if (domnr > maxh.Size()) maxh.SetSize (domnr);
for (int i = oldsize; i < domnr; i++)
maxh[i] = 1e99;
if (domnr >= 1)
maxh[domnr-1] = h;
else
throw NgException ("material index out of range");
}
extern void MeshFromSpline2D (SplineGeometry2d & geometry,
shared_ptr<Mesh> & mesh,
MeshingParameters & mp);
int SplineGeometry2d :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)
{
if(restricted_h.Size())
{
// copy so that we don't change mparam outside
MeshingParameters mp = mparam;
for(const auto& [pnt, maxh] : restricted_h)
mp.meshsize_points.Append({pnt, maxh});
MeshFromSpline2D (*this, mesh, mp);
}
else
MeshFromSpline2D (*this, mesh, mparam);
return 0;
}
class SplineGeometryRegister : public GeometryRegister
{
public:
virtual NetgenGeometry * Load (const filesystem::path & filename) const;
};
NetgenGeometry * SplineGeometryRegister :: Load (const filesystem::path & filename) const
{
string ext = ToLower(filename.extension());
if (ext == ".in2d")
{
PrintMessage (1, "Load 2D-Spline geometry file ", filename);
ifstream infile(filename);
SplineGeometry2d * hgeom = new SplineGeometry2d();
hgeom -> Load (filename);
return hgeom;
}
return NULL;
}
class SplineGeoInit
{
public:
SplineGeoInit()
{
GeometryRegisterArray& gra = FetchGeometryRegisterArray();
gra.Append (new SplineGeometryRegister);
}
};
SplineGeoInit sginit;
static RegisterClassForArchive<SplineGeometry2d, SplineGeometry<2>, NetgenGeometry> regspg2;
static RegisterClassForArchive<SplineSegExt, SplineSeg<2>> regssext;
}