Skip to content

Commit 409c239

Browse files
authored
Merge pull request #323 from VibekeSkytt/lrref_affected
Modified search for affected B-splines in lr refinement
2 parents 8aba865 + b70db3f commit 409c239

File tree

5 files changed

+389
-175
lines changed

5 files changed

+389
-175
lines changed

lrsplines2D/include/GoTools/lrsplines2D/LRSplineUtils.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,16 @@ namespace Go
135135
LRSplineSurface::BSplineMap& bmap,
136136
double domain[],
137137
std::vector<std::unique_ptr<BSplineUniLR> >& bspline_vec1,
138-
std::vector<std::unique_ptr<BSplineUniLR> >& bspline_vec2);
138+
std::vector<std::unique_ptr<BSplineUniLR> >& bspline_vec2,
139+
bool support);
139140

140141
std::tuple<int, int, int, int>
141142
refine_mesh(Direction2D d, double fixed_val, double start, double end,
142143
int mult, bool absolute,
143144
int spline_degree, double knot_tol,
144145
Mesh2D& mesh,
145-
std::vector<std::unique_ptr<BSplineUniLR> >& bsplines);
146+
std::vector<std::unique_ptr<BSplineUniLR> >& bsplines,
147+
bool& refined);
146148

147149
bool support_equal(const LRBSpline2D* b1, const LRBSpline2D* b2);
148150

@@ -184,6 +186,12 @@ namespace Go
184186
bool u_at_end, bool v_at_end,
185187
std::vector<Point>& result);
186188

189+
void
190+
get_affected_bsplines(const std::vector<LRSplineSurface::Refinement2D>& refs,
191+
const LRSplineSurface::ElementMap& emap,
192+
double knot_tol, const Mesh2D& mesh,
193+
std::vector<LRBSpline2D*>& affected);
194+
187195
//==============================================================================
188196
struct support_compare
189197
//==============================================================================

lrsplines2D/include/GoTools/lrsplines2D/Mesh2D.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ namespace Go
5757
struct GPos {
5858
// due to Visual Studio 2010 not supporting initializer lists, we have
5959
// to make an explicit constructor here.
60-
GPos(int i, int m) : ix(i), mult(m) {}
61-
GPos() : ix(-1), mult(-1) {}
60+
GPos(int i, int m) : ix(i), mult(m) {}
61+
GPos() : ix(-1), mult(-1) {}
6262

6363
int ix;
6464
int mult;
@@ -87,12 +87,11 @@ class Mesh2D : public MeshLR
8787
// values.
8888
template<typename Array>
8989
Mesh2D(const Array& xknots, const Array& yknots);
90-
9190

9291
Mesh2D(const std::vector<double>& xknots, const std::vector<double>& yknots,
9392
const std::vector<std::vector<int> >& mrvecx,
9493
const std::vector<std::vector<int> >& mrvecy);
95-
94+
9695
// Read the mesh from a stream
9796
virtual void read(std::istream& is);
9897

@@ -240,7 +239,7 @@ class Mesh2D : public MeshLR
240239
// ix - the index of the row/column of the meshrectangles
241240
// start - the index to the start of the first consecutive meshrectangle along the line
242241
// end - the index to the one-past-end of the last consecutive meshrectangle along the line
243-
void setMult(Direction2D d, int ix, int start, int end, int mult);
242+
bool setMult(Direction2D d, int ix, int start, int end, int mult);
244243

245244
// increment multiplicity of a consecutive set of meshrectangles by 'mult'
246245
// The consecutive set is specified by:
@@ -398,6 +397,7 @@ std::vector<int> Mesh2D::compactify_ixvec_(Iterator kvec_start, Iterator kvec_en
398397
mult.clear();
399398
for (auto i = result.begin(); i != result.end(); ++i)
400399
mult.push_back(std::count(kvec_start, kvec_end, *i));
400+
401401
return result;
402402
}
403403

@@ -517,9 +517,11 @@ inline Direction2D flip(Direction2D d)
517517
}
518518

519519
// defining streaming operators
520-
inline std::ostream& operator<<(std::ostream& os, const GPos& g) { return os << g.ix << " " << g.mult << " ";}
521-
inline std::istream& operator>>(std::istream& is, GPos& g) { return is >> g.ix >> g.mult;}
522-
inline std::ostream& operator<<(std::ostream& os, const Mesh2D& m){ m.write(os); return os;}
520+
inline std::ostream& operator<<(std::ostream& os, const GPos& g)
521+
{ return os << g.ix << " " << g.mult << " ";}
522+
inline std::istream& operator>>(std::istream& is, GPos& g)
523+
{ return is >> g.ix >> g.mult;}
524+
inline std::ostream& operator<<(std::ostream& os, const Mesh2D& m) { m.write(os); return os;}
523525
inline std::istream& operator>>(std::istream& is, Mesh2D& m) { m.read(is); return is;}
524526

525527
}; // end namespace Go

lrsplines2D/src/LRSplineSurface.C

Lines changed: 139 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <iostream> // @@ debug
4545
#include <fstream>
4646
#include <iterator> // @@ debug - remove
47+
#include <string.h>
4748
//#include <chrono> // @@ debug
4849
#include <set>
4950
#include <tuple>
@@ -716,10 +717,12 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
716717
// Make a copy of the initial mesh
717718
Mesh2D mesh2 = mesh_;
718719

720+
bool refined;
719721
const auto indices = // tuple<int, int, int, int>
720-
LRSplineUtils::refine_mesh(d, fixed_val, start, end, mult, absolute,
721-
degree(d), knot_tol_, mesh_,
722-
(d == XFIXED) ? bsplinesuni1_ : bsplinesuni2_);
722+
LRSplineUtils::refine_mesh(d, fixed_val, start, end, mult,
723+
absolute, degree(d), knot_tol_, mesh_,
724+
(d == XFIXED) ? bsplinesuni1_ : bsplinesuni2_,
725+
refined);
723726

724727
#ifdef DEBUG
725728
std::ofstream of2("mesh1.eps");
@@ -788,6 +791,22 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
788791
#ifdef DEBUG
789792
elems_affected.push_back(curr_el);
790793
#endif
794+
// if (d == XFIXED)
795+
// {
796+
// double u1 = curr_el->umin();
797+
// double u2 = curr_el->umax();
798+
// if ((u2 - fixed_val > 0.55*(u2-u1) || fixed_val - u1 > 0.55*(u2-u1)) &&
799+
// u2-fixed_val > 0.0001 && fixed_val-u1 > 0.0001)
800+
// std::cout << "Unbalanced element, 1. par: " << fixed_val << " in [" << u1 << "," << u2 << "]" << std::endl;
801+
// }
802+
// else
803+
// {
804+
// double v1 = curr_el->vmin();
805+
// double v2 = curr_el->vmax();
806+
// if ((v2 - fixed_val > 0.55*(v2-v1) || fixed_val - v1 > 0.55*(v2-v1)) &&
807+
// v2-fixed_val > 0.0001 && fixed_val-v1 > 0.0001)
808+
// std::cout << "Unbalanced element, 2. par: " << fixed_val << " in [" << v1 << "," << v2 << "]" << std::endl;
809+
// }
791810
}
792811
}
793812
vector<LRBSpline2D*> bsplines_affected(all_bsplines.begin(), all_bsplines.end());
@@ -891,7 +910,7 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
891910
// combination of objects and pointers will not work.
892911
LRSplineUtils::iteratively_split2(bsplines_affected, mesh_,
893912
bsplines_, domain,
894-
bsplinesuni1_, bsplinesuni2_);
913+
bsplinesuni1_, bsplinesuni2_, true);
895914
// bsplinesuni1_, iu1, iu2,
896915
// bsplinesuni2_, iv1, iv2);
897916

@@ -999,8 +1018,7 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
9991018

10001019
#ifdef DEBUG
10011020
if (it2 == emap_.end())
1002-
int stop_break = 1;
1003-
//std::cout << "LRSplineSurface::refine : Element not found" << std::endl;
1021+
std::cout << "LRSplineSurface::refine : Element not found" << std::endl;
10041022
#endif
10051023
}
10061024

@@ -1031,14 +1049,9 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
10311049
it2->second->getOutsidePoints(data_points, d, sort_in_u);
10321050
it2->second->getOutsideSignificantPoints(significant_points,
10331051
d, sort_in_u_significant);
1034-
it2->second->getOutsideGhostPoints(ghost_points, d,
1052+
it2->second->getOutsideGhostPoints(ghost_points, d,
10351053
sort_in_u_ghost);
10361054
pt_del = it2->second->getNmbValPrPoint();
1037-
// it2->second->getAccuracyInfo(averr, maxerr, nmbout);
1038-
// accerr = it2->second->getAccumulatedError();
1039-
1040-
// Update accuracy statistices in element
1041-
it2->second->updateAccuracyInfo();
10421055

10431056
// Update supported LRBsplines
10441057
for (size_t kb=0; kb<bsplines_affected.size(); ++kb)
@@ -1079,17 +1092,14 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
10791092
if (data_points.size() > 0)
10801093
elem->addDataPoints(data_points.begin(), data_points.end(),
10811094
sort_in_u, pt_del);
1082-
if (significant_points.size() > 0)
1083-
elem->addSignificantPoints(significant_points.begin(),
1084-
significant_points.end(),
1085-
sort_in_u_significant, pt_del);
1095+
if (significant_points.size() > 0)
1096+
elem->addSignificantPoints(significant_points.begin(),
1097+
significant_points.end(),
1098+
sort_in_u_significant, pt_del);
1099+
10861100
if (ghost_points.size() > 0)
10871101
elem->addGhostPoints(ghost_points.begin(), ghost_points.end(),
10881102
sort_in_u_ghost, pt_del);
1089-
//elem->setAccuracyInfo(accerr, averr, maxerr, nmbout); // Not exact info as the
1090-
// element has been split
1091-
elem->updateAccuracyInfo(); // Accuracy statistic in element
1092-
10931103
emap_.insert(std::make_pair(key, std::move(elem)));
10941104
//auto it3 = emap_.find(key);
10951105

@@ -1107,6 +1117,22 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
11071117
#endif
11081118
}
11091119

1120+
struct refval
1121+
{
1122+
refval(int val, int m)
1123+
{
1124+
kval = val;
1125+
mult = m;
1126+
}
1127+
int kval, mult;
1128+
};
1129+
1130+
int compare_refs_sf(refval r1, refval r2)
1131+
{
1132+
return (r1.kval < r2.kval);
1133+
}
1134+
1135+
11101136
//==============================================================================
11111137
void LRSplineSurface::refine(const vector<Refinement2D>& refs,
11121138
bool absolute)
@@ -1123,7 +1149,14 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
11231149
int stop_break = 1;
11241150
}
11251151
#endif
1152+
// Collect B-splines affected by the refinements
1153+
vector<LRBSpline2D*> affected;
1154+
LRSplineUtils::get_affected_bsplines(refs, emap_, knot_tol_, mesh_,
1155+
affected);
1156+
1157+
vector<refval> u_refs, v_refs;
11261158
for (size_t i = 0; i != refs.size(); ++i) {
1159+
bool refined;
11271160
const Refinement2D& r = refs[i];
11281161
const auto indices = // tuple<int, int, int, int>
11291162
LRSplineUtils::refine_mesh(r.d,
@@ -1135,51 +1168,109 @@ void LRSplineSurface::refine(Direction2D d, double fixed_val, double start,
11351168
degree(r.d),
11361169
knot_tol_,
11371170
mesh_,
1138-
(r.d == XFIXED) ? bsplinesuni1_ : bsplinesuni2_);
1171+
(r.d == XFIXED) ? bsplinesuni1_ : bsplinesuni2_,
1172+
refined);
11391173

1140-
// Not efficient
1141-
int fixed_ix = get<1>(indices); // Index of fixed_val in global knot vector.
1142-
int last_ix =
1143-
BSplineUniUtils::last_overlapping_bsplineuni(fixed_ix,
1144-
(r.d == XFIXED) ? bsplinesuni1_ : bsplinesuni2_);
1145-
1174+
if (!refined)
1175+
continue;
1176+
refval curr(r.kval, r.multiplicity);
1177+
size_t kr;
11461178
if (r.d == XFIXED)
1179+
{
1180+
for (kr=0; kr<u_refs.size(); ++kr)
1181+
if (u_refs[kr].kval == curr.kval &&
1182+
u_refs[kr].mult == curr.mult)
1183+
break;
1184+
if (kr == u_refs.size())
1185+
u_refs.push_back(curr);
1186+
}
1187+
else if (r.d == YFIXED)
1188+
{
1189+
for (kr=0; kr<v_refs.size(); ++kr)
1190+
if (v_refs[kr].kval == curr.kval &&
1191+
v_refs[kr].mult == curr.mult)
1192+
break;
1193+
if (kr == v_refs.size())
1194+
v_refs.push_back(curr);
1195+
}
1196+
}
1197+
1198+
if (u_refs.size() + v_refs.size() == 0)
1199+
return; // Mesh rectangles already existing
1200+
1201+
//std::cout << "Post refine mesh" << std::endl;
1202+
std::sort(u_refs.begin(), u_refs.end(), compare_refs_sf);
1203+
std::sort(v_refs.begin(), v_refs.end(), compare_refs_sf);
1204+
1205+
for (int ki=(int)u_refs.size()-1; ki>=0; --ki)
1206+
{
1207+
int kval = u_refs[ki].kval;
1208+
int fixed_ix = Mesh2DUtils::last_nonlarger_knotvalue_ix(mesh_, XFIXED, kval);
1209+
1210+
int last_ix =
1211+
BSplineUniUtils::last_overlapping_bsplineuni(fixed_ix, bsplinesuni1_);
1212+
11471213
LRSplineUtils::split_univariate(bsplinesuni1_, last_ix, fixed_ix,
1148-
(absolute) ? r.multiplicity : 1);
1149-
else
1214+
absolute? u_refs[ki].mult : 1);
1215+
}
1216+
1217+
for (int ki=(int)v_refs.size()-1; ki>=0; --ki)
1218+
{
1219+
int kval = v_refs[ki].kval;
1220+
int fixed_ix = Mesh2DUtils::last_nonlarger_knotvalue_ix(mesh_, YFIXED, kval);
1221+
1222+
int last_ix =
1223+
BSplineUniUtils::last_overlapping_bsplineuni(fixed_ix, bsplinesuni2_);
1224+
11501225
LRSplineUtils::split_univariate(bsplinesuni2_, last_ix, fixed_ix,
1151-
(absolute) ? r.multiplicity : 1);
1152-
}
1226+
absolute? v_refs[ki].mult : 1);
1227+
}
1228+
1229+
// // Not efficient
1230+
// int fixed_ix = get<1>(indices); // Index of fixed_val in global knot vector.
1231+
// int last_ix =
1232+
// BSplineUniUtils::last_overlapping_bsplineuni(fixed_ix,
1233+
// (r.d == XFIXED) ? bsplinesuni1_ : bsplinesuni2_);
1234+
1235+
// if (r.d == XFIXED)
1236+
// LRSplineUtils::split_univariate(bsplinesuni1_, last_ix, fixed_ix,
1237+
// (absolute) ? r.multiplicity : 1);
1238+
// else
1239+
// LRSplineUtils::split_univariate(bsplinesuni2_, last_ix, fixed_ix,
1240+
// (absolute) ? r.multiplicity : 1);
1241+
// }
11531242

11541243

11551244
//std::wcout << "Preparing for iterative splitting." << std::endl;
1156-
vector<unique_ptr<LRBSpline2D> > affected;
1157-
affected.reserve(bsplines_.size());
1158-
// for_each(bsplines_.begin(), bsplines_.end(), [&](const BSplineMap::value_type& b) {
1159-
for (auto it = bsplines_.begin(); it!= bsplines_.end(); ++it)
1160-
{
1161-
// @@@ VSK. This is maybe the place to remove element information from the bsplines?
1162-
unique_ptr<LRBSpline2D> ptr = std::move(it->second);
1163-
affected.emplace_back(std::move(ptr));//b.second);
1164-
};
1245+
//vector<unique_ptr<LRBSpline2D> > affected;
1246+
// vector<LRBSpline2D*> affected;
1247+
// affected.reserve(bsplines_.size());
1248+
// // for_each(bsplines_.begin(), bsplines_.end(), [&](const BSplineMap::value_type& b) {
1249+
// for (auto it = bsplines_.begin(); it!= bsplines_.end(); ++it)
1250+
// {
1251+
// affected.push_back((*it).second.get());
1252+
// // @@@ VSK. This is maybe the place to remove element information from the bsplines?
1253+
// // unique_ptr<LRBSpline2D> ptr = std::move(it->second);
1254+
// // affected.emplace_back(std::move(ptr));//b.second);
1255+
// };
11651256

11661257
// @@@ VSK. In this case, we should not bother about splitting elements. They will
11671258
// be regenerated later. Thus, the bsplines should NOT be updated with elements during
11681259
// splitting
11691260
// The bsplines should not have any pointers to elements. They will be set later
11701261
//std::wcout << "Iteratively splitting." << std::endl;
11711262

1172-
LRSplineUtils::iteratively_split(affected, mesh_,
1173-
bsplinesuni1_, bsplinesuni2_);
1174-
bsplines_.clear();
1263+
LRSplineUtils::iteratively_split2(affected, mesh_, bsplines_, NULL,
1264+
bsplinesuni1_, bsplinesuni2_, false);
1265+
//bsplines_.clear();
11751266

11761267
//std::wcout << "Splitting finished, now inserting resulting functions" << std::endl;
11771268
// The bsplines are checked for duplicates and inserted in the global bspline map
11781269
// for_each(affected.begin(), affected.end(), [&](unique_ptr<LRBSpline2D> b) {
1179-
for (auto it = affected.begin(); it != affected.end(); ++it)
1180-
{
1181-
LRSplineUtils::insert_basis_function(*it, mesh_, bsplines_);
1182-
};
1270+
// for (auto it = affected.begin(); it != affected.end(); ++it)
1271+
// {
1272+
// LRSplineUtils::insert_basis_function(*it, mesh_, bsplines_);
1273+
// };
11831274

11841275
#if 0//ndef NDEBUG
11851276
{
@@ -1218,7 +1309,6 @@ for (auto it = affected.begin(); it != affected.end(); ++it)
12181309

12191310
}
12201311

1221-
12221312
//==============================================================================
12231313
void LRSplineSurface::addSurface(const LRSplineSurface& other_sf, double fac)
12241314
//==============================================================================
@@ -3573,6 +3663,7 @@ LRSplineSurface::collect_basis(int from_u, int to_u,
35733663
return b_splines;
35743664
}
35753665

3666+
35763667
//===========================================================================
35773668
void
35783669
LRSplineSurface::checkSupport(LRBSpline2D* basis) const

0 commit comments

Comments
 (0)