13 #include "../fem/fem.hpp"
14 #include "../general/text.hpp"
17 #if defined(_MSC_VER) && (_MSC_VER < 1800)
19 #define copysign _copysign
31 input >> Order >> NumOfControlPoints;
32 knot.Load(input, NumOfControlPoints + Order + 1);
39 NumOfControlPoints = NCP;
40 knot.SetSize(NumOfControlPoints + Order + 1);
62 " Parent KnotVector order higher than child");
65 const int nOrder = Order + t;
68 for (
int i = 0; i <= nOrder; i++)
70 (*newkv)[i] = knot(0);
72 for (
int i = nOrder + 1; i < newkv->
GetNCP(); i++)
74 (*newkv)[i] = knot(i - t);
76 for (
int i = 0; i <= nOrder; i++)
78 (*newkv)[newkv->
GetNCP() + i] = knot(knot.Size()-1);
88 newknots.
SetSize(NumOfElements);
90 for (
int i = 0; i < knot.Size()-1; i++)
92 if (knot(i) != knot(i+1))
94 newknots(j) = 0.5*(knot(i) + knot(i+1));
103 for (
int i = Order; i < NumOfControlPoints; i++)
105 if (knot(i) != knot(i+1))
114 double apb = knot(0) + knot(knot.Size()-1);
116 int ns = (NumOfControlPoints - Order)/2;
117 for (
int i = 1; i <= ns; i++)
119 double tmp = apb - knot(Order + i);
120 knot(Order + i) = apb - knot(NumOfControlPoints - i);
121 knot(NumOfControlPoints - i) = tmp;
127 out << Order <<
' ' << NumOfControlPoints <<
' ';
128 knot.Print(out, knot.Size());
134 MFEM_ASSERT(Order <= MaxOrder, "Order > MaxOrder!
");
137 int ip = (i >= 0) ? (i + p) : (-1 - i + p);
138 double u = getKnotLocation((i >= 0) ? xi : 1. - xi, ip), saved, tmp;
139 double left[MaxOrder+1], right[MaxOrder+1];
142 for (int j = 1; j <= p; ++j)
144 left[j] = u - knot(ip+1-j);
145 right[j] = knot(ip+j) - u;
147 for (int r = 0; r < j; ++r)
149 tmp = shape(r)/(right[r+1] + left[j-r]);
150 shape(r) = saved + right[r+1]*tmp;
151 saved = left[j-r]*tmp;
157 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller
158 void KnotVector::CalcDShape(Vector &grad, int i, double xi) const
160 int p = Order, rk, pk;
161 int ip = (i >= 0) ? (i + p) : (-1 - i + p);
162 double u = getKnotLocation((i >= 0) ? xi : 1. - xi, ip), temp, saved, d;
163 double ndu[MaxOrder+1][MaxOrder+1], left[MaxOrder+1], right[MaxOrder+1];
173 for (int j = 1; j <= p; j++)
175 left[j] = u - knot(ip-j+1);
176 right[j] = knot(ip+j) - u;
178 for (int r = 0; r < j; r++)
180 ndu[j][r] = right[r+1] + left[j-r];
181 temp = ndu[r][j-1]/ndu[j][r];
182 ndu[r][j] = saved + right[r+1]*temp;
183 saved = left[j-r]*temp;
188 for (int r = 0; r <= p; ++r)
195 d = ndu[rk][pk]/ndu[p][rk];
199 d -= ndu[r][pk]/ndu[p][r];
206 grad *= p*(knot(ip+1) - knot(ip));
210 grad *= p*(knot(ip) - knot(ip+1));
214 int KnotVector::findKnotSpan(double u) const
218 if (u == knot(NumOfControlPoints+Order))
220 mid = NumOfControlPoints;
225 high = NumOfControlPoints + 1;
226 mid = (low + high)/2;
227 while ( (u < knot(mid-1)) || (u > knot(mid)) )
237 mid = (low + high)/2;
243 void KnotVector::Difference(const KnotVector &kv, Vector &diff) const
245 if (Order != kv.GetOrder())
248 " Can not compare knot vectors with different orders!
");
251 int s = kv.Size() - Size();
254 kv.Difference(*this, diff);
262 for (int j = 0; j < kv.Size(); j++)
264 if (knot(i) == kv[j])
277 void NURBSPatch::init(int dim_)
284 ni = kv[0]->GetNCP();
285 nj = kv[1]->GetNCP();
288 data = new double[ni*nj*Dim];
291 for (int i = 0; i < ni*nj*Dim; i++)
297 else if (kv.Size() == 3)
299 ni = kv[0]->GetNCP();
300 nj = kv[1]->GetNCP();
301 nk = kv[2]->GetNCP();
303 data = new double[ni*nj*nk*Dim];
306 for (int i = 0; i < ni*nj*nk*Dim; i++)
318 NURBSPatch::NURBSPatch(const NURBSPatch &orig)
319 : ni(orig.ni), nj(orig.nj), nk(orig.nk), Dim(orig.Dim),
320 data(NULL), kv(orig.kv.Size()), sd(orig.sd), nd(orig.nd)
322 // Allocate and copy data:
323 const int data_size = Dim*ni*nj*((kv.Size() == 2) ? 1 : nk);
324 data = new double[data_size];
325 std::memcpy(data, orig.data, data_size*sizeof(double));
327 // Copy the knot vectors:
328 for (int i = 0; i < kv.Size(); i++)
330 kv[i] = new KnotVector(*orig.kv[i]);
334 NURBSPatch::NURBSPatch(std::istream &input)
336 int pdim, dim, size = 1;
339 input >> ws >> ident >> pdim; // knotvectors
341 for (int i = 0; i < pdim; i++)
343 kv[i] = new KnotVector(input);
344 size *= kv[i]->GetNCP();
347 input >> ws >> ident >> dim; // dimension
350 input >> ws >> ident; // controlpoints (homogeneous coordinates)
351 if (ident == "controlpoints
" || ident == "controlpoints_homogeneous
")
353 for (int j = 0, i = 0; i < size; i++)
354 for (int d = 0; d <= dim; d++, j++)
359 else // "controlpoints_cartesian
" (Cartesian coordinates with weight)
361 for (int j = 0, i = 0; i < size; i++)
363 for (int d = 0; d <= dim; d++)
367 for (int d = 0; d < dim; d++)
369 data[j+d] *= data[j+dim];
376 NURBSPatch::NURBSPatch(const KnotVector *kv0, const KnotVector *kv1, int dim_)
379 kv[0] = new KnotVector(*kv0);
380 kv[1] = new KnotVector(*kv1);
384 NURBSPatch::NURBSPatch(const KnotVector *kv0, const KnotVector *kv1,
385 const KnotVector *kv2, int dim_)
388 kv[0] = new KnotVector(*kv0);
389 kv[1] = new KnotVector(*kv1);
390 kv[2] = new KnotVector(*kv2);
394 NURBSPatch::NURBSPatch(Array<const KnotVector *> &kv_, int dim_)
396 kv.SetSize(kv_.Size());
397 for (int i = 0; i < kv.Size(); i++)
399 kv[i] = new KnotVector(*kv_[i]);
404 NURBSPatch::NURBSPatch(NURBSPatch *parent, int dir, int Order, int NCP)
406 kv.SetSize(parent->kv.Size());
407 for (int i = 0; i < kv.Size(); i++)
410 kv[i] = new KnotVector(*parent->kv[i]);
414 kv[i] = new KnotVector(Order, NCP);
419 void NURBSPatch::swap(NURBSPatch *np)
426 for (int i = 0; i < kv.Size(); i++)
428 if (kv[i]) { delete kv[i]; }
445 NURBSPatch::~NURBSPatch()
452 for (int i = 0; i < kv.Size(); i++)
454 if (kv[i]) { delete kv[i]; }
458 void NURBSPatch::Print(std::ostream &out) const
462 out << "knotvectors\n
" << kv.Size() << '\n';
463 for (int i = 0; i < kv.Size(); i++)
466 size *= kv[i]->GetNCP();
469 out << "\ndimension\n
" << Dim - 1
470 << "\n\ncontrolpoints\n
";
471 for (int j = 0, i = 0; i < size; i++)
474 for (int d = 1; d < Dim; d++)
476 out << ' ' << data[j++];
482 int NURBSPatch::SetLoopDirection(int dir)
503 " Direction error in 2D patch, dir =
" << dir << '\n';
533 " Direction error in 3D patch, dir =
" << dir << '\n';
541 void NURBSPatch::UniformRefinement()
544 for (int dir = 0; dir < kv.Size(); dir++)
546 kv[dir]->UniformRefinement(newknots);
547 KnotInsert(dir, newknots);
551 void NURBSPatch::KnotInsert(Array<KnotVector *> &newkv)
553 for (int dir = 0; dir < kv.Size(); dir++)
555 KnotInsert(dir, *newkv[dir]);
559 void NURBSPatch::KnotInsert(int dir, const KnotVector &newkv)
561 if (dir >= kv.Size() || dir < 0)
566 int t = newkv.GetOrder() - kv[dir]->GetOrder();
570 DegreeElevate(dir, t);
578 GetKV(dir)->Difference(newkv, diff);
581 KnotInsert(dir, diff);
585 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller
586 void NURBSPatch::KnotInsert(int dir, const Vector &knot)
588 if (dir >= kv.Size() || dir < 0)
593 NURBSPatch &oldp = *this;
594 KnotVector &oldkv = *kv[dir];
596 NURBSPatch *newpatch = new NURBSPatch(this, dir, oldkv.GetOrder(),
597 oldkv.GetNCP() + knot.Size());
598 NURBSPatch &newp = *newpatch;
599 KnotVector &newkv = *newp.GetKV(dir);
601 int size = oldp.SetLoopDirection(dir);
602 if (size != newp.SetLoopDirection(dir))
607 int rr = knot.Size() - 1;
608 int a = oldkv.findKnotSpan(knot(0)) - 1;
609 int b = oldkv.findKnotSpan(knot(rr)) - 1;
610 int pl = oldkv.GetOrder();
611 int ml = oldkv.GetNCP();
613 for (int j = 0; j <= a; j++)
617 for (int j = b+pl; j <= ml+pl; j++)
619 newkv[j+rr+1] = oldkv[j];
621 for (int k = 0; k <= (a-pl); k++)
623 for (int ll = 0; ll < size; ll++)
625 newp(k,ll) = oldp(k,ll);
628 for (int k = (b-1); k < ml; k++)
630 for (int ll = 0; ll < size; ll++)
632 newp(k+rr+1,ll) = oldp(k,ll);
639 for (int j = rr; j >= 0; j--)
641 while ( (knot(j) <= oldkv[i]) && (i > a) )
644 for (int ll = 0; ll < size; ll++)
646 newp(k-pl-1,ll) = oldp(i-pl-1,ll);
653 for (int ll = 0; ll < size; ll++)
655 newp(k-pl-1,ll) = newp(k-pl,ll);
658 for (int l = 1; l <= pl; l++)
661 double alfa = newkv[k+l] - knot(j);
662 if (fabs(alfa) == 0.0)
664 for (int ll = 0; ll < size; ll++)
666 newp(ind-1,ll) = newp(ind,ll);
671 alfa = alfa/(newkv[k+l] - oldkv[i-pl+l]);
672 for (int ll = 0; ll < size; ll++)
674 newp(ind-1,ll) = alfa*newp(ind-1,ll) + (1.0-alfa)*newp(ind,ll);
688 void NURBSPatch::DegreeElevate(int t)
690 for (int dir = 0; dir < kv.Size(); dir++)
692 DegreeElevate(dir, t);
696 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller
697 void NURBSPatch::DegreeElevate(int dir, int t)
699 if (dir >= kv.Size() || dir < 0)
704 int i, j, k, kj, mpi, mul, mh, kind, cind, first, last;
705 int r, a, b, oldr, save, s, tr, lbz, rbz, l;
706 double inv, ua, ub, numer, alf, den, bet, gam;
708 NURBSPatch &oldp = *this;
709 KnotVector &oldkv = *kv[dir];
711 NURBSPatch *newpatch = new NURBSPatch(this, dir, oldkv.GetOrder() + t,
712 oldkv.GetNCP() + oldkv.GetNE()*t);
713 NURBSPatch &newp = *newpatch;
714 KnotVector &newkv = *newp.GetKV(dir);
716 int size = oldp.SetLoopDirection(dir);
717 if (size != newp.SetLoopDirection(dir))
722 int p = oldkv.GetOrder();
723 int n = oldkv.GetNCP()-1;
725 DenseMatrix bezalfs (p+t+1, p+1);
726 DenseMatrix bpts (p+1, size);
727 DenseMatrix ebpts (p+t+1, size);
728 DenseMatrix nextbpts(p-1, size);
736 Array2D<int> binom(ph+1, ph+1);
737 for (i = 0; i <= ph; i++)
739 binom(i,0) = binom(i,i) = 1;
740 for (j = 1; j < i; j++)
742 binom(i,j) = binom(i-1,j) + binom(i-1,j-1);
749 for (i = 1; i <= ph2; i++)
751 inv = 1.0/binom(ph,i);
753 for (j = max(0,i-t); j <= mpi; j++)
755 bezalfs(i,j) = inv*binom(p,j)*binom(t,i-j);
760 for (i = ph2+1; i < ph; i++)
763 for (j = max(0,i-t); j <= mpi; j++)
765 bezalfs(i,j) = bezalfs(ph-i,p-j);
776 for (l = 0; l < size; l++)
778 newp(0,l) = oldp(0,l);
780 for (i = 0; i <= ph; i++)
785 for (i = 0; i <= p; i++)
787 for (l = 0; l < size; l++)
789 bpts(i,l) = oldp(i,l);
796 while (b < m && oldkv[b] == oldkv[b+1]) { b++; }
804 if (oldr > 0) { lbz = (oldr+2)/2; }
807 if (r > 0) { rbz = ph-(r+1)/2; }
813 for (k = p ; k > mul; k--)
815 alphas[k-mul-1] = numer/(oldkv[a+k]-ua);
818 for (j = 1; j <= r; j++)
822 for (k = p; k >= s; k--)
824 for (l = 0; l < size; l++)
825 bpts(k,l) = (alphas[k-s]*bpts(k,l) +
826 (1.0-alphas[k-s])*bpts(k-1,l));
828 for (l = 0; l < size; l++)
830 nextbpts(save,l) = bpts(p,l);
835 for (i = lbz; i <= ph; i++)
837 for (l = 0; l < size; l++)
842 for (j = max(0,i-t); j <= mpi; j++)
844 for (l = 0; l < size; l++)
846 ebpts(i,l) += bezalfs(i,j)*bpts(j,l);
856 bet = (ub-newkv[kind-1])/den;
858 for (tr = 1; tr < oldr; tr++)
867 alf = (ub-newkv[i])/(ua-newkv[i]);
868 for (l = 0; l < size; l++)
870 newp(i,l) = alf*newp(i,l)-(1.0-alf)*newp(i-1,l);
875 if ((j-tr) <= (kind-ph+oldr))
877 gam = (ub-newkv[j-tr])/den;
878 for (l = 0; l < size; l++)
880 ebpts(kj,l) = gam*ebpts(kj,l) + (1.0-gam)*ebpts(kj+1,l);
885 for (l = 0; l < size; l++)
887 ebpts(kj,l) = bet*ebpts(kj,l) + (1.0-bet)*ebpts(kj+1,l);
902 for (i = 0; i < (ph-oldr); i++)
908 for (j = lbz; j <= rbz; j++)
910 for (l = 0; l < size; l++)
912 newp(cind,l) = ebpts(j,l);
919 for (j = 0; j <r; j++)
920 for (l = 0; l < size; l++)
922 bpts(j,l) = nextbpts(j,l);
925 for (j = r; j <= p; j++)
926 for (l = 0; l < size; l++)
928 bpts(j,l) = oldp(b-p+j,l);
937 for (i = 0; i <= ph; i++)
948 void NURBSPatch::FlipDirection(int dir)
950 int size = SetLoopDirection(dir);
952 for (int id = 0; id < nd/2; id++)
953 for (int i = 0; i < size; i++)
955 Swap<double>((*this)(id,i), (*this)(nd-1-id,i));
960 void NURBSPatch::SwapDirections(int dir1, int dir2)
962 if (abs(dir1-dir2) == 2)
965 " directions 0 and 2 are not supported!
");
968 Array<const KnotVector *> nkv(kv);
970 Swap<const KnotVector *>(nkv[dir1], nkv[dir2]);
971 NURBSPatch *newpatch = new NURBSPatch(nkv, Dim);
973 int size = SetLoopDirection(dir1);
974 newpatch->SetLoopDirection(dir2);
976 for (int id = 0; id < nd; id++)
977 for (int i = 0; i < size; i++)
979 (*newpatch)(id,i) = (*this)(id,i);
985 void NURBSPatch::Get3DRotationMatrix(double n[], double angle, double r,
989 double l2 = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
992 if (fabs(angle) == M_PI_2)
994 s = r*copysign(1., angle);
998 else if (fabs(angle) == M_PI)
1013 T(0,0) = (n[0]*n[0] + (n[1]*n[1] + n[2]*n[2])*c)/l2;
1014 T(0,1) = -(n[0]*n[1]*c1)/l2 - (n[2]*s)/l;
1015 T(0,2) = -(n[0]*n[2]*c1)/l2 + (n[1]*s)/l;
1016 T(1,0) = -(n[0]*n[1]*c1)/l2 + (n[2]*s)/l;
1017 T(1,1) = (n[1]*n[1] + (n[0]*n[0] + n[2]*n[2])*c)/l2;
1018 T(1,2) = -(n[1]*n[2]*c1)/l2 - (n[0]*s)/l;
1019 T(2,0) = -(n[0]*n[2]*c1)/l2 - (n[1]*s)/l;
1020 T(2,1) = -(n[1]*n[2]*c1)/l2 + (n[0]*s)/l;
1021 T(2,2) = (n[2]*n[2] + (n[0]*n[0] + n[1]*n[1])*c)/l2;
1024 void NURBSPatch::Rotate3D(double n[], double angle)
1032 Vector x(3), y(NULL, 3);
1034 Get3DRotationMatrix(n, angle, 1., T);
1037 for (int i = 0; i < kv.Size(); i++)
1039 size *= kv[i]->GetNCP();
1042 for (int i = 0; i < size; i++)
1044 y.SetData(data + i*Dim);
1050 int NURBSPatch::MakeUniformDegree(int degree)
1056 for (int dir = 0; dir < kv.Size(); dir++)
1058 maxd = std::max(maxd, kv[dir]->GetOrder());
1062 for (int dir = 0; dir < kv.Size(); dir++)
1064 if (maxd > kv[dir]->GetOrder())
1066 DegreeElevate(dir, maxd - kv[dir]->GetOrder());
1073 NURBSPatch *Interpolate(NURBSPatch &p1, NURBSPatch &p2)
1075 if (p1.kv.Size() != p2.kv.Size() || p1.Dim != p2.Dim)
1080 int size = 1, dim = p1.Dim;
1081 Array<const KnotVector *> kv(p1.kv.Size() + 1);
1083 for (int i = 0; i < p1.kv.Size(); i++)
1085 if (p1.kv[i]->GetOrder() < p2.kv[i]->GetOrder())
1087 p1.KnotInsert(i, *p2.kv[i]);
1088 p2.KnotInsert(i, *p1.kv[i]);
1092 p2.KnotInsert(i, *p1.kv[i]);
1093 p1.KnotInsert(i, *p2.kv[i]);
1096 size *= kv[i]->GetNCP();
1099 KnotVector &nkv = *(new KnotVector(1, 2));
1100 nkv[0] = nkv[1] = 0.0;
1101 nkv[2] = nkv[3] = 1.0;
1105 NURBSPatch *patch = new NURBSPatch(kv, dim);
1108 for (int i = 0; i < size; i++)
1110 for (int d = 0; d < dim; d++)
1112 patch->data[i*dim+d] = p1.data[i*dim+d];
1113 patch->data[(i+size)*dim+d] = p2.data[i*dim+d];
1120 NURBSPatch *Revolve3D(NURBSPatch &patch, double n[], double ang, int times)
1128 Array<const KnotVector *> nkv(patch.kv.Size() + 1);
1130 for (int i = 0; i < patch.kv.Size(); i++)
1132 nkv[i] = patch.kv[i];
1133 size *= nkv[i]->GetNCP();
1136 KnotVector &lkv = *(new KnotVector(2, ns));
1138 lkv[0] = lkv[1] = lkv[2] = 0.0;
1139 for (int i = 1; i < times; i++)
1141 lkv[2*i+1] = lkv[2*i+2] = i;
1143 lkv[ns] = lkv[ns+1] = lkv[ns+2] = times;
1145 NURBSPatch *newpatch = new NURBSPatch(nkv, 4);
1148 DenseMatrix T(3), T2(3);
1149 Vector u(NULL, 3), v(NULL, 3);
1151 NURBSPatch::Get3DRotationMatrix(n, ang, 1., T);
1152 double c = cos(ang/2);
1153 NURBSPatch::Get3DRotationMatrix(n, ang/2, 1./c, T2);
1156 double *op = patch.data, *np;
1157 for (int i = 0; i < size; i++)
1159 np = newpatch->data + 4*i;
1160 for (int j = 0; j < 4; j++)
1164 for (int j = 0; j < times; j++)
1167 v.SetData(np += 4*size);
1170 v.SetData(np += 4*size);
1181 NURBSExtension::NURBSExtension(const NURBSExtension &orig)
1182 : mOrder(orig.mOrder), mOrders(orig.mOrders),
1183 NumOfKnotVectors(orig.NumOfKnotVectors),
1184 NumOfVertices(orig.NumOfVertices),
1185 NumOfElements(orig.NumOfElements),
1186 NumOfBdrElements(orig.NumOfBdrElements),
1187 NumOfDofs(orig.NumOfDofs),
1188 NumOfActiveVertices(orig.NumOfActiveVertices),
1189 NumOfActiveElems(orig.NumOfActiveElems),
1190 NumOfActiveBdrElems(orig.NumOfActiveBdrElems),
1191 NumOfActiveDofs(orig.NumOfActiveDofs),
1192 activeVert(orig.activeVert),
1193 activeElem(orig.activeElem),
1194 activeBdrElem(orig.activeBdrElem),
1195 activeDof(orig.activeDof),
1196 patchTopo(new Mesh(*orig.patchTopo)),
1198 edge_to_knot(orig.edge_to_knot),
1199 knotVectors(orig.knotVectors.Size()), // knotVectors are copied in the body
1200 weights(orig.weights),
1201 v_meshOffsets(orig.v_meshOffsets),
1202 e_meshOffsets(orig.e_meshOffsets),
1203 f_meshOffsets(orig.f_meshOffsets),
1204 p_meshOffsets(orig.p_meshOffsets),
1205 v_spaceOffsets(orig.v_spaceOffsets),
1206 e_spaceOffsets(orig.e_spaceOffsets),
1207 f_spaceOffsets(orig.f_spaceOffsets),
1208 p_spaceOffsets(orig.p_spaceOffsets),
1209 el_dof(orig.el_dof ? new Table(*orig.el_dof) : NULL),
1210 bel_dof(orig.bel_dof ? new Table(*orig.bel_dof) : NULL),
1211 el_to_patch(orig.el_to_patch),
1212 bel_to_patch(orig.bel_to_patch),
1213 el_to_IJK(orig.el_to_IJK),
1214 bel_to_IJK(orig.bel_to_IJK),
1215 patches(orig.patches.Size()) // patches are copied in the body
1217 // Copy the knot vectors:
1218 for (int i = 0; i < knotVectors.Size(); i++)
1220 knotVectors[i] = new KnotVector(*orig.knotVectors[i]);
1223 // Copy the patches:
1224 for (int p = 0; p < patches.Size(); p++)
1226 patches[p] = new NURBSPatch(*orig.patches[p]);
1230 NURBSExtension::NURBSExtension(std::istream &input)
1233 patchTopo = new Mesh;
1234 patchTopo->LoadPatchTopo(input, edge_to_knot);
1238 // CheckBdrPatches();
1240 skip_comment_lines(input, '#');
1242 // Read knotvectors or patches
1244 input >> ws >> ident; // 'knotvectors' or 'patches'
1245 if (ident == "knotvectors
")
1247 input >> NumOfKnotVectors;
1248 knotVectors.SetSize(NumOfKnotVectors);
1249 for (int i = 0; i < NumOfKnotVectors; i++)
1251 knotVectors[i] = new KnotVector(input);
1254 else if (ident == "patches
")
1256 patches.SetSize(GetNP());
1257 for (int p = 0; p < patches.Size(); p++)
1259 skip_comment_lines(input, '#');
1260 patches[p] = new NURBSPatch(input);
1263 NumOfKnotVectors = 0;
1264 for (int i = 0; i < patchTopo->GetNEdges(); i++)
1265 if (NumOfKnotVectors < KnotInd(i))
1267 NumOfKnotVectors = KnotInd(i);
1270 knotVectors.SetSize(NumOfKnotVectors);
1273 Array<int> edges, oedge;
1274 for (int p = 0; p < patches.Size(); p++)
1276 patchTopo->GetElementEdges(p, edges, oedge);
1277 if (Dimension() == 2)
1279 if (knotVectors[KnotInd(edges[0])] == NULL)
1281 knotVectors[KnotInd(edges[0])] =
1282 new KnotVector(*patches[p]->GetKV(0));
1284 if (knotVectors[KnotInd(edges[1])] == NULL)
1286 knotVectors[KnotInd(edges[1])] =
1287 new KnotVector(*patches[p]->GetKV(1));
1292 if (knotVectors[KnotInd(edges[0])] == NULL)
1294 knotVectors[KnotInd(edges[0])] =
1295 new KnotVector(*patches[p]->GetKV(0));
1297 if (knotVectors[KnotInd(edges[3])] == NULL)
1299 knotVectors[KnotInd(edges[3])] =
1300 new KnotVector(*patches[p]->GetKV(1));
1302 if (knotVectors[KnotInd(edges[8])] == NULL)
1304 knotVectors[KnotInd(edges[8])] =
1305 new KnotVector(*patches[p]->GetKV(2));
1312 MFEM_ABORT("invalid section:
" << ident);
1315 SetOrdersFromKnotVectors();
1320 // NumOfVertices, NumOfElements, NumOfBdrElements, NumOfDofs
1322 skip_comment_lines(input, '#');
1324 // Check for a list of mesh elements
1325 if (patches.Size() == 0)
1327 input >> ws >> ident;
1329 if (patches.Size() == 0 && ident == "mesh_elements
")
1331 input >> NumOfActiveElems;
1332 activeElem.SetSize(GetGNE());
1335 for (int i = 0; i < NumOfActiveElems; i++)
1338 activeElem[glob_elem] = true;
1341 skip_comment_lines(input, '#');
1342 input >> ws >> ident;
1346 NumOfActiveElems = NumOfElements;
1347 activeElem.SetSize(NumOfElements);
1351 GenerateActiveVertices();
1352 GenerateElementDofTable();
1353 GenerateActiveBdrElems();
1354 GenerateBdrElementDofTable();
1356 if (patches.Size() == 0)
1359 if (ident == "weights
")
1361 weights.Load(input, GetNDof());
1363 else // e.g. ident = "unitweights
" or "autoweights
"
1365 weights.SetSize(GetNDof());
1371 NURBSExtension::NURBSExtension(NURBSExtension *parent, int newOrder)
1373 patchTopo = parent->patchTopo;
1376 parent->edge_to_knot.Copy(edge_to_knot);
1378 NumOfKnotVectors = parent->GetNKV();
1379 knotVectors.SetSize(NumOfKnotVectors);
1380 const Array<int> &pOrders = parent->GetOrders();
1381 for (int i = 0; i < NumOfKnotVectors; i++)
1383 if (newOrder > pOrders[i])
1386 parent->GetKnotVector(i)->DegreeElevate(newOrder - pOrders[i]);
1390 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
1394 // copy some data from parent
1395 NumOfElements = parent->NumOfElements;
1396 NumOfBdrElements = parent->NumOfBdrElements;
1398 SetOrdersFromKnotVectors();
1400 GenerateOffsets(); // dof offsets will be different from parent
1402 NumOfActiveVertices = parent->NumOfActiveVertices;
1403 NumOfActiveElems = parent->NumOfActiveElems;
1404 NumOfActiveBdrElems = parent->NumOfActiveBdrElems;
1405 parent->activeVert.Copy(activeVert);
1406 parent->activeElem.Copy(activeElem);
1407 parent->activeBdrElem.Copy(activeBdrElem);
1409 GenerateElementDofTable();
1410 GenerateBdrElementDofTable();
1412 weights.SetSize(GetNDof());
1416 NURBSExtension::NURBSExtension(NURBSExtension *parent,
1417 const Array<int> &newOrders)
1419 newOrders.Copy(mOrders);
1420 SetOrderFromOrders();
1422 patchTopo = parent->patchTopo;
1425 parent->edge_to_knot.Copy(edge_to_knot);
1427 NumOfKnotVectors = parent->GetNKV();
1428 MFEM_VERIFY(mOrders.Size() == NumOfKnotVectors, "invalid newOrders array
");
1429 knotVectors.SetSize(NumOfKnotVectors);
1430 const Array<int> &pOrders = parent->GetOrders();
1432 for (int i = 0; i < NumOfKnotVectors; i++)
1434 if (mOrders[i] > pOrders[i])
1437 parent->GetKnotVector(i)->DegreeElevate(mOrders[i] - pOrders[i]);
1441 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
1445 // copy some data from parent
1446 NumOfElements = parent->NumOfElements;
1447 NumOfBdrElements = parent->NumOfBdrElements;
1449 GenerateOffsets(); // dof offsets will be different from parent
1451 NumOfActiveVertices = parent->NumOfActiveVertices;
1452 NumOfActiveElems = parent->NumOfActiveElems;
1453 NumOfActiveBdrElems = parent->NumOfActiveBdrElems;
1454 parent->activeVert.Copy(activeVert);
1455 parent->activeElem.Copy(activeElem);
1456 parent->activeBdrElem.Copy(activeBdrElem);
1458 GenerateElementDofTable();
1459 GenerateBdrElementDofTable();
1461 weights.SetSize(GetNDof());
1465 NURBSExtension::NURBSExtension(Mesh *mesh_array[], int num_pieces)
1467 NURBSExtension *parent = mesh_array[0]->NURBSext;
1469 if (!parent->own_topo)
1472 " parent does not own the patch topology!
");
1474 patchTopo = parent->patchTopo;
1476 parent->own_topo = 0;
1478 parent->edge_to_knot.Copy(edge_to_knot);
1480 parent->GetOrders().Copy(mOrders);
1481 mOrder = parent->GetOrder();
1483 NumOfKnotVectors = parent->GetNKV();
1484 knotVectors.SetSize(NumOfKnotVectors);
1485 for (int i = 0; i < NumOfKnotVectors; i++)
1487 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
1494 // assuming the meshes define a partitioning of all the elements
1495 NumOfActiveElems = NumOfElements;
1496 activeElem.SetSize(NumOfElements);
1499 GenerateActiveVertices();
1500 GenerateElementDofTable();
1501 GenerateActiveBdrElems();
1502 GenerateBdrElementDofTable();
1504 weights.SetSize(GetNDof());
1505 MergeWeights(mesh_array, num_pieces);
1508 NURBSExtension::~NURBSExtension()
1510 if (patches.Size() == 0)
1516 for (int i = 0; i < knotVectors.Size(); i++)
1518 delete knotVectors[i];
1521 for (int i = 0; i < patches.Size(); i++)
1532 void NURBSExtension::Print(std::ostream &out) const
1534 patchTopo->PrintTopo(out, edge_to_knot);
1535 if (patches.Size() == 0)
1537 out << "\nknotvectors\n
" << NumOfKnotVectors << '\n';
1538 for (int i = 0; i < NumOfKnotVectors; i++)
1540 knotVectors[i]->Print(out);
1543 if (NumOfActiveElems < NumOfElements)
1545 out << "\nmesh_elements\n
" << NumOfActiveElems << '\n';
1546 for (int i = 0; i < NumOfElements; i++)
1553 out << "\nweights\n
";
1554 weights.Print(out, 1);
1558 out << "\npatches\n
";
1559 for (int p = 0; p < patches.Size(); p++)
1561 out << "\n# patch
" << p << "\n\n
";
1562 patches[p]->Print(out);
1567 void NURBSExtension::PrintCharacteristics(std::ostream &out) const
1570 "NURBS
Mesh entity sizes:\n
"
1571 "Dimension =
" << Dimension() << "\n
"
1573 Array<int> unique_orders(mOrders);
1574 unique_orders.Sort();
1575 unique_orders.Unique();
1576 unique_orders.Print(out, unique_orders.Size());
1578 "NumOfKnotVectors =
" << GetNKV() << "\n
"
1579 "NumOfPatches =
" << GetNP() << "\n
"
1580 "NumOfBdrPatches =
" << GetNBP() << "\n
"
1581 "NumOfVertices =
" << GetGNV() << "\n
"
1582 "NumOfElements =
" << GetGNE() << "\n
"
1583 "NumOfBdrElements =
" << GetGNBE() << "\n
"
1584 "NumOfDofs =
" << GetNTotalDof() << "\n
"
1585 "NumOfActiveVertices =
" << GetNV() << "\n
"
1586 "NumOfActiveElems =
" << GetNE() << "\n
"
1587 "NumOfActiveBdrElems =
" << GetNBE() << "\n
"
1588 "NumOfActiveDofs =
" << GetNDof() << '\n';
1589 for (int i = 0; i < NumOfKnotVectors; i++)
1591 out << ' ' << i + 1 << ")
";
1592 knotVectors[i]->Print(out);
1597 void NURBSExtension::GenerateActiveVertices()
1599 int vert[8], nv, g_el, nx, ny, nz, dim = Dimension();
1601 NURBSPatchMap p2g(this);
1602 const KnotVector *kv[3];
1605 activeVert.SetSize(GetGNV());
1607 for (int p = 0; p < GetNP(); p++)
1609 p2g.SetPatchVertexMap(p, kv);
1613 nz = (dim == 3) ? p2g.nz() : 1;
1615 for (int k = 0; k < nz; k++)
1617 for (int j = 0; j < ny; j++)
1619 for (int i = 0; i < nx; i++)
1621 if (activeElem[g_el])
1625 vert[0] = p2g(i, j );
1626 vert[1] = p2g(i+1,j );
1627 vert[2] = p2g(i+1,j+1);
1628 vert[3] = p2g(i, j+1);
1633 vert[0] = p2g(i, j, k);
1634 vert[1] = p2g(i+1,j, k);
1635 vert[2] = p2g(i+1,j+1,k);
1636 vert[3] = p2g(i, j+1,k);
1638 vert[4] = p2g(i, j, k+1);
1639 vert[5] = p2g(i+1,j, k+1);
1640 vert[6] = p2g(i+1,j+1,k+1);
1641 vert[7] = p2g(i, j+1,k+1);
1645 for (int v = 0; v < nv; v++)
1647 activeVert[vert[v]] = 1;
1656 NumOfActiveVertices = 0;
1657 for (int i = 0; i < GetGNV(); i++)
1658 if (activeVert[i] == 1)
1660 activeVert[i] = NumOfActiveVertices++;
1664 void NURBSExtension::GenerateActiveBdrElems()
1666 int dim = Dimension();
1667 Array<KnotVector *> kv(dim);
1669 activeBdrElem.SetSize(GetGNBE());
1670 if (GetGNE() == GetNE())
1672 activeBdrElem = true;
1673 NumOfActiveBdrElems = GetGNBE();
1676 activeBdrElem = false;
1677 NumOfActiveBdrElems = 0;
1678 // the mesh will generate the actual boundary including boundary
1679 // elements that are not on boundary patches. we use this for
1680 // visualization of processor boundaries
1682 // TODO: generate actual boundary?
1686 void NURBSExtension::MergeWeights(Mesh *mesh_array[], int num_pieces)
1688 Array<int> lelem_elem;
1690 for (int i = 0; i < num_pieces; i++)
1692 NURBSExtension *lext = mesh_array[i]->NURBSext;
1694 lext->GetElementLocalToGlobal(lelem_elem);
1696 for (int lel = 0; lel < lext->GetNE(); lel++)
1698 int gel = lelem_elem[lel];
1700 int nd = el_dof->RowSize(gel);
1701 int *gdofs = el_dof->GetRow(gel);
1702 int *ldofs = lext->el_dof->GetRow(lel);
1703 for (int j = 0; j < nd; j++)
1705 weights(gdofs[j]) = lext->weights(ldofs[j]);
1711 void NURBSExtension::MergeGridFunctions(
1712 GridFunction *gf_array[], int num_pieces, GridFunction &merged)
1714 FiniteElementSpace *gfes = merged.FESpace();
1715 Array<int> lelem_elem, dofs;
1718 for (int i = 0; i < num_pieces; i++)
1720 FiniteElementSpace *lfes = gf_array[i]->FESpace();
1721 NURBSExtension *lext = lfes->GetMesh()->NURBSext;
1723 lext->GetElementLocalToGlobal(lelem_elem);
1725 for (int lel = 0; lel < lext->GetNE(); lel++)
1727 lfes->GetElementVDofs(lel, dofs);
1728 gf_array[i]->GetSubVector(dofs, lvec);
1730 gfes->GetElementVDofs(lelem_elem[lel], dofs);
1731 merged.SetSubVector(dofs, lvec);
1736 void NURBSExtension::CheckPatches()
1741 for (int p = 0; p < GetNP(); p++)
1743 patchTopo->GetElementEdges(p, edges, oedge);
1745 for (int i = 0; i < edges.Size(); i++)
1747 edges[i] = edge_to_knot[edges[i]];
1750 edges[i] = -1 - edges[i];
1754 if ((Dimension() == 2 &&
1755 (edges[0] != -1 - edges[2] || edges[1] != -1 - edges[3])) ||
1757 (Dimension() == 3 &&
1758 (edges[0] != edges[2] || edges[0] != edges[4] ||
1759 edges[0] != edges[6] || edges[1] != edges[3] ||
1760 edges[1] != edges[5] || edges[1] != edges[7] ||
1761 edges[8] != edges[9] || edges[8] != edges[10] ||
1762 edges[8] != edges[11])))
1764 mfem::err << "NURBSExtension::CheckPatch (patch =
" << p
1765 << ")\n Inconsistent edge-to-knot mapping!\n
";
1769 if ((Dimension() == 2 &&
1770 (edges[0] < 0 || edges[1] < 0)) ||
1772 (Dimension() == 3 &&
1773 (edges[0] < 0 || edges[3] < 0 || edges[8] < 0)))
1775 mfem::err << "NURBSExtension::CheckPatch (patch =
" << p
1776 << ") : Bad orientation!\n
";
1782 void NURBSExtension::CheckBdrPatches()
1787 for (int p = 0; p < GetNBP(); p++)
1789 patchTopo->GetBdrElementEdges(p, edges, oedge);
1791 for (int i = 0; i < edges.Size(); i++)
1793 edges[i] = edge_to_knot[edges[i]];
1796 edges[i] = -1 - edges[i];
1800 if ((Dimension() == 2 && (edges[0] < 0)) ||
1801 (Dimension() == 3 && (edges[0] < 0 || edges[1] < 0)))
1804 << p << ") : Bad orientation!\n
";
1810 void NURBSExtension::GetPatchKnotVectors(int p, Array<KnotVector *> &kv)
1812 Array<int> edges, orient;
1814 kv.SetSize(Dimension());
1815 patchTopo->GetElementEdges(p, edges, orient);
1817 if (Dimension() == 2)
1819 kv[0] = KnotVec(edges[0]);
1820 kv[1] = KnotVec(edges[1]);
1824 kv[0] = KnotVec(edges[0]);
1825 kv[1] = KnotVec(edges[3]);
1826 kv[2] = KnotVec(edges[8]);
1830 void NURBSExtension::GetPatchKnotVectors(int p, Array<const KnotVector *> &kv)
1833 Array<int> edges, orient;
1835 kv.SetSize(Dimension());
1836 patchTopo->GetElementEdges(p, edges, orient);
1838 if (Dimension() == 2)
1840 kv[0] = KnotVec(edges[0]);
1841 kv[1] = KnotVec(edges[1]);
1845 kv[0] = KnotVec(edges[0]);
1846 kv[1] = KnotVec(edges[3]);
1847 kv[2] = KnotVec(edges[8]);
1851 void NURBSExtension::GetBdrPatchKnotVectors(int p, Array<KnotVector *> &kv)
1856 kv.SetSize(Dimension() - 1);
1857 patchTopo->GetBdrElementEdges(p, edges, orient);
1859 if (Dimension() == 2)
1861 kv[0] = KnotVec(edges[0]);
1865 kv[0] = KnotVec(edges[0]);
1866 kv[1] = KnotVec(edges[1]);
1870 void NURBSExtension::GetBdrPatchKnotVectors(
1871 int p, Array<const KnotVector *> &kv) const
1876 kv.SetSize(Dimension() - 1);
1877 patchTopo->GetBdrElementEdges(p, edges, orient);
1879 if (Dimension() == 2)
1881 kv[0] = KnotVec(edges[0]);
1885 kv[0] = KnotVec(edges[0]);
1886 kv[1] = KnotVec(edges[1]);
1890 void NURBSExtension::SetOrderFromOrders()
1892 MFEM_VERIFY(mOrders.Size() > 0, "");
1893 mOrder = mOrders[0];
1894 for (int i = 1; i < mOrders.Size(); i++)
1896 if (mOrders[i] != mOrder)
1898 mOrder = NURBSFECollection::VariableOrder;
1904 void NURBSExtension::SetOrdersFromKnotVectors()
1906 mOrders.SetSize(NumOfKnotVectors);
1907 for (int i = 0; i < NumOfKnotVectors; i++)
1909 mOrders[i] = knotVectors[i]->GetOrder();
1911 SetOrderFromOrders();
1914 void NURBSExtension::GenerateOffsets()
1916 int nv = patchTopo->GetNV();
1917 int ne = patchTopo->GetNEdges();
1918 int nf = patchTopo->GetNFaces();
1919 int np = patchTopo->GetNE();
1920 int meshCounter, spaceCounter, dim = Dimension();
1925 v_meshOffsets.SetSize(nv);
1926 e_meshOffsets.SetSize(ne);
1927 f_meshOffsets.SetSize(nf);
1928 p_meshOffsets.SetSize(np);
1930 v_spaceOffsets.SetSize(nv);
1931 e_spaceOffsets.SetSize(ne);
1932 f_spaceOffsets.SetSize(nf);
1933 p_spaceOffsets.SetSize(np);
1935 // Get vertex offsets
1936 for (meshCounter = 0; meshCounter < nv; meshCounter++)
1938 v_meshOffsets[meshCounter] = meshCounter;
1939 v_spaceOffsets[meshCounter] = meshCounter;
1941 spaceCounter = meshCounter;
1944 for (int e = 0; e < ne; e++)
1946 e_meshOffsets[e] = meshCounter;
1947 e_spaceOffsets[e] = spaceCounter;
1948 meshCounter += KnotVec(e)->GetNE() - 1;
1949 spaceCounter += KnotVec(e)->GetNCP() - 2;
1953 for (int f = 0; f < nf; f++)
1955 f_meshOffsets[f] = meshCounter;
1956 f_spaceOffsets[f] = spaceCounter;
1958 patchTopo->GetFaceEdges(f, edges, orient);
1961 (KnotVec(edges[0])->GetNE() - 1) *
1962 (KnotVec(edges[1])->GetNE() - 1);
1964 (KnotVec(edges[0])->GetNCP() - 2) *
1965 (KnotVec(edges[1])->GetNCP() - 2);
1968 // Get patch offsets
1969 for (int p = 0; p < np; p++)
1971 p_meshOffsets[p] = meshCounter;
1972 p_spaceOffsets[p] = spaceCounter;
1974 patchTopo->GetElementEdges(p, edges, orient);
1979 (KnotVec(edges[0])->GetNE() - 1) *
1980 (KnotVec(edges[1])->GetNE() - 1);
1982 (KnotVec(edges[0])->GetNCP() - 2) *
1983 (KnotVec(edges[1])->GetNCP() - 2);
1988 (KnotVec(edges[0])->GetNE() - 1) *
1989 (KnotVec(edges[3])->GetNE() - 1) *
1990 (KnotVec(edges[8])->GetNE() - 1);
1992 (KnotVec(edges[0])->GetNCP() - 2) *
1993 (KnotVec(edges[3])->GetNCP() - 2) *
1994 (KnotVec(edges[8])->GetNCP() - 2);
1997 NumOfVertices = meshCounter;
1998 NumOfDofs = spaceCounter;
2001 void NURBSExtension::CountElements()
2003 int dim = Dimension();
2004 Array<const KnotVector *> kv(dim);
2007 for (int p = 0; p < GetNP(); p++)
2009 GetPatchKnotVectors(p, kv);
2011 int ne = kv[0]->GetNE();
2012 for (int d = 1; d < dim; d++)
2014 ne *= kv[d]->GetNE();
2017 NumOfElements += ne;
2021 void NURBSExtension::CountBdrElements()
2023 int dim = Dimension() - 1;
2024 Array<KnotVector *> kv(dim);
2026 NumOfBdrElements = 0;
2027 for (int p = 0; p < GetNBP(); p++)
2029 GetBdrPatchKnotVectors(p, kv);
2031 int ne = kv[0]->GetNE();
2032 for (int d = 1; d < dim; d++)
2034 ne *= kv[d]->GetNE();
2037 NumOfBdrElements += ne;
2041 void NURBSExtension::GetElementTopo(Array<Element *> &elements) const
2043 elements.SetSize(GetNE());
2045 if (Dimension() == 2)
2047 Get2DElementTopo(elements);
2051 Get3DElementTopo(elements);
2055 void NURBSExtension::Get2DElementTopo(Array<Element *> &elements) const
2060 NURBSPatchMap p2g(this);
2061 const KnotVector *kv[2];
2063 for (int p = 0; p < GetNP(); p++)
2065 p2g.SetPatchVertexMap(p, kv);
2069 int patch_attr = patchTopo->GetAttribute(p);
2071 for (int j = 0; j < ny; j++)
2073 for (int i = 0; i < nx; i++)
2077 ind[0] = activeVert[p2g(i, j )];
2078 ind[1] = activeVert[p2g(i+1,j )];
2079 ind[2] = activeVert[p2g(i+1,j+1)];
2080 ind[3] = activeVert[p2g(i, j+1)];
2082 elements[el] = new Quadrilateral(ind, patch_attr);
2091 void NURBSExtension::Get3DElementTopo(Array<Element *> &elements) const
2096 NURBSPatchMap p2g(this);
2097 const KnotVector *kv[3];
2099 for (int p = 0; p < GetNP(); p++)
2101 p2g.SetPatchVertexMap(p, kv);
2106 int patch_attr = patchTopo->GetAttribute(p);
2108 for (int k = 0; k < nz; k++)
2110 for (int j = 0; j < ny; j++)
2112 for (int i = 0; i < nx; i++)
2116 ind[0] = activeVert[p2g(i, j, k)];
2117 ind[1] = activeVert[p2g(i+1,j, k)];
2118 ind[2] = activeVert[p2g(i+1,j+1,k)];
2119 ind[3] = activeVert[p2g(i, j+1,k)];
2121 ind[4] = activeVert[p2g(i, j, k+1)];
2122 ind[5] = activeVert[p2g(i+1,j, k+1)];
2123 ind[6] = activeVert[p2g(i+1,j+1,k+1)];
2124 ind[7] = activeVert[p2g(i, j+1,k+1)];
2126 elements[el] = new Hexahedron(ind, patch_attr);
2136 void NURBSExtension::GetBdrElementTopo(Array<Element *> &boundary) const
2138 boundary.SetSize(GetNBE());
2140 if (Dimension() == 2)
2142 Get2DBdrElementTopo(boundary);
2146 Get3DBdrElementTopo(boundary);
2150 void NURBSExtension::Get2DBdrElementTopo(Array<Element *> &boundary) const
2154 NURBSPatchMap p2g(this);
2155 const KnotVector *kv[1];
2158 for (int b = 0; b < GetNBP(); b++)
2160 p2g.SetBdrPatchVertexMap(b, kv, okv);
2163 int bdr_patch_attr = patchTopo->GetBdrAttribute(b);
2165 for (int i = 0; i < nx; i++)
2167 if (activeBdrElem[g_be])
2169 int _i = (okv[0] >= 0) ? i : (nx - 1 - i);
2170 ind[0] = activeVert[p2g[_i ]];
2171 ind[1] = activeVert[p2g[_i+1]];
2173 boundary[l_be] = new Segment(ind, bdr_patch_attr);
2181 void NURBSExtension::Get3DBdrElementTopo(Array<Element *> &boundary) const
2185 NURBSPatchMap p2g(this);
2186 const KnotVector *kv[2];
2189 for (int b = 0; b < GetNBP(); b++)
2191 p2g.SetBdrPatchVertexMap(b, kv, okv);
2195 int bdr_patch_attr = patchTopo->GetBdrAttribute(b);
2197 for (int j = 0; j < ny; j++)
2199 int _j = (okv[1] >= 0) ? j : (ny - 1 - j);
2200 for (int i = 0; i < nx; i++)
2202 if (activeBdrElem[g_be])
2204 int _i = (okv[0] >= 0) ? i : (nx - 1 - i);
2205 ind[0] = activeVert[p2g(_i, _j )];
2206 ind[1] = activeVert[p2g(_i+1,_j )];
2207 ind[2] = activeVert[p2g(_i+1,_j+1)];
2208 ind[3] = activeVert[p2g(_i, _j+1)];
2210 boundary[l_be] = new Quadrilateral(ind, bdr_patch_attr);
2219 void NURBSExtension::GenerateElementDofTable()
2221 activeDof.SetSize(GetNTotalDof());
2224 if (Dimension() == 2)
2226 Generate2DElementDofTable();
2230 Generate3DElementDofTable();
2233 NumOfActiveDofs = 0;
2234 for (int d = 0; d < GetNTotalDof(); d++)
2238 activeDof[d] = NumOfActiveDofs;
2241 int *dof = el_dof->GetJ();
2242 int ndof = el_dof->Size_of_connections();
2243 for (int i = 0; i < ndof; i++)
2245 dof[i] = activeDof[dof[i]] - 1;
2249 void NURBSExtension::Generate2DElementDofTable()
2253 const KnotVector *kv[2];
2254 NURBSPatchMap p2g(this);
2256 Array<Connection> el_dof_list;
2257 el_to_patch.SetSize(NumOfActiveElems);
2258 el_to_IJK.SetSize(NumOfActiveElems, 2);
2260 for (int p = 0; p < GetNP(); p++)
2262 p2g.SetPatchDofMap(p, kv);
2265 const int ord0 = kv[0]->GetOrder();
2266 const int ord1 = kv[1]->GetOrder();
2267 for (int j = 0; j < kv[1]->GetNKS(); j++)
2269 if (kv[1]->isElement(j))
2271 for (int i = 0; i < kv[0]->GetNKS(); i++)
2273 if (kv[0]->isElement(i))
2277 Connection conn(el,0);
2278 for (int jj = 0; jj <= ord1; jj++)
2280 for (int ii = 0; ii <= ord0; ii++)
2282 conn.to = p2g(i+ii,j+jj);
2283 activeDof[conn.to] = 1;
2284 el_dof_list.Append(conn);
2287 el_to_patch[el] = p;
2288 el_to_IJK(el,0) = i;
2289 el_to_IJK(el,1) = j;
2299 // We must NOT sort el_dof_list in this case.
2300 el_dof = new Table(NumOfActiveElems, el_dof_list);
2303 void NURBSExtension::Generate3DElementDofTable()
2307 const KnotVector *kv[3];
2308 NURBSPatchMap p2g(this);
2310 Array<Connection> el_dof_list;
2311 el_to_patch.SetSize(NumOfActiveElems);
2312 el_to_IJK.SetSize(NumOfActiveElems, 3);
2314 for (int p = 0; p < GetNP(); p++)
2316 p2g.SetPatchDofMap(p, kv);
2319 const int ord0 = kv[0]->GetOrder();
2320 const int ord1 = kv[1]->GetOrder();
2321 const int ord2 = kv[2]->GetOrder();
2322 for (int k = 0; k < kv[2]->GetNKS(); k++)
2324 if (kv[2]->isElement(k))
2326 for (int j = 0; j < kv[1]->GetNKS(); j++)
2328 if (kv[1]->isElement(j))
2330 for (int i = 0; i < kv[0]->GetNKS(); i++)
2332 if (kv[0]->isElement(i))
2336 Connection conn(el,0);
2337 for (int kk = 0; kk <= ord2; kk++)
2339 for (int jj = 0; jj <= ord1; jj++)
2341 for (int ii = 0; ii <= ord0; ii++)
2343 conn.to = p2g(i+ii, j+jj, k+kk);
2344 activeDof[conn.to] = 1;
2345 el_dof_list.Append(conn);
2350 el_to_patch[el] = p;
2351 el_to_IJK(el,0) = i;
2352 el_to_IJK(el,1) = j;
2353 el_to_IJK(el,2) = k;
2365 // We must NOT sort el_dof_list in this case.
2366 el_dof = new Table(NumOfActiveElems, el_dof_list);
2369 void NURBSExtension::GenerateBdrElementDofTable()
2371 if (Dimension() == 2)
2373 Generate2DBdrElementDofTable();
2377 Generate3DBdrElementDofTable();
2380 int *dof = bel_dof->GetJ();
2381 int ndof = bel_dof->Size_of_connections();
2382 for (int i = 0; i < ndof; i++)
2384 dof[i] = activeDof[dof[i]] - 1;
2388 void NURBSExtension::Generate2DBdrElementDofTable()
2391 int lbe = 0, okv[1];
2392 const KnotVector *kv[1];
2393 NURBSPatchMap p2g(this);
2395 Array<Connection> bel_dof_list;
2396 bel_to_patch.SetSize(NumOfActiveBdrElems);
2397 bel_to_IJK.SetSize(NumOfActiveBdrElems, 1);
2399 for (int b = 0; b < GetNBP(); b++)
2401 p2g.SetBdrPatchDofMap(b, kv, okv);
2402 const int nx = p2g.nx(); // NCP-1
2405 const int nks0 = kv[0]->GetNKS();
2406 const int ord0 = kv[0]->GetOrder();
2407 for (int i = 0; i < nks0; i++)
2409 if (kv[0]->isElement(i))
2411 if (activeBdrElem[gbe])
2413 Connection conn(lbe,0);
2414 for (int ii = 0; ii <= ord0; ii++)
2416 conn.to = p2g[(okv[0] >= 0) ? (i+ii) : (nx-i-ii)];
2417 bel_dof_list.Append(conn);
2419 bel_to_patch[lbe] = b;
2420 bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
2427 // We must NOT sort bel_dof_list in this case.
2428 bel_dof = new Table(NumOfActiveBdrElems, bel_dof_list);
2431 void NURBSExtension::Generate3DBdrElementDofTable()
2434 int lbe = 0, okv[2];
2435 const KnotVector *kv[2];
2436 NURBSPatchMap p2g(this);
2438 Array<Connection> bel_dof_list;
2439 bel_to_patch.SetSize(NumOfActiveBdrElems);
2440 bel_to_IJK.SetSize(NumOfActiveBdrElems, 2);
2442 for (int b = 0; b < GetNBP(); b++)
2444 p2g.SetBdrPatchDofMap(b, kv, okv);
2445 const int nx = p2g.nx(); // NCP0-1
2446 const int ny = p2g.ny(); // NCP1-1
2449 const int nks0 = kv[0]->GetNKS();
2450 const int ord0 = kv[0]->GetOrder();
2451 const int nks1 = kv[1]->GetNKS();
2452 const int ord1 = kv[1]->GetOrder();
2453 for (int j = 0; j < nks1; j++)
2455 if (kv[1]->isElement(j))
2457 for (int i = 0; i < nks0; i++)
2459 if (kv[0]->isElement(i))
2461 if (activeBdrElem[gbe])
2463 Connection conn(lbe,0);
2464 for (int jj = 0; jj <= ord1; jj++)
2466 const int _jj = (okv[1] >= 0) ? (j+jj) : (ny-j-jj);
2467 for (int ii = 0; ii <= ord0; ii++)
2469 const int _ii = (okv[0] >= 0) ? (i+ii) : (nx-i-ii);
2470 conn.to = p2g(_ii, _jj);
2471 bel_dof_list.Append(conn);
2474 bel_to_patch[lbe] = b;
2475 bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
2476 bel_to_IJK(lbe,1) = (okv[1] >= 0) ? j : (-1-j);
2485 // We must NOT sort bel_dof_list in this case.
2486 bel_dof = new Table(NumOfActiveBdrElems, bel_dof_list);
2489 void NURBSExtension::GetVertexLocalToGlobal(Array<int> &lvert_vert)
2491 lvert_vert.SetSize(GetNV());
2492 for (int gv = 0; gv < GetGNV(); gv++)
2493 if (activeVert[gv] >= 0)
2495 lvert_vert[activeVert[gv]] = gv;
2499 void NURBSExtension::GetElementLocalToGlobal(Array<int> &lelem_elem)
2501 lelem_elem.SetSize(GetNE());
2502 for (int le = 0, ge = 0; ge < GetGNE(); ge++)
2505 lelem_elem[le++] = ge;
2509 void NURBSExtension::LoadFE(int i, const FiniteElement *FE) const
2511 const NURBSFiniteElement *NURBSFE =
2512 dynamic_cast<const NURBSFiniteElement *>(FE);
2514 if (NURBSFE->GetElement() != i)
2517 NURBSFE->SetIJK(el_to_IJK.GetRow(i));
2518 if (el_to_patch[i] != NURBSFE->GetPatch())
2520 GetPatchKnotVectors(el_to_patch[i], NURBSFE->KnotVectors());
2521 NURBSFE->SetPatch(el_to_patch[i]);
2522 NURBSFE->SetOrder();
2524 el_dof->GetRow(i, dofs);
2525 weights.GetSubVector(dofs, NURBSFE->Weights());
2526 NURBSFE->SetElement(i);
2530 void NURBSExtension::LoadBE(int i, const FiniteElement *BE) const
2532 const NURBSFiniteElement *NURBSFE =
2533 dynamic_cast<const NURBSFiniteElement *>(BE);
2535 if (NURBSFE->GetElement() != i)
2538 NURBSFE->SetIJK(bel_to_IJK.GetRow(i));
2539 if (bel_to_patch[i] != NURBSFE->GetPatch())
2541 GetBdrPatchKnotVectors(bel_to_patch[i], NURBSFE->KnotVectors());
2542 NURBSFE->SetPatch(bel_to_patch[i]);
2543 NURBSFE->SetOrder();
2545 bel_dof->GetRow(i, dofs);
2546 weights.GetSubVector(dofs, NURBSFE->Weights());
2547 NURBSFE->SetElement(i);
2551 void NURBSExtension::ConvertToPatches(const Vector &Nodes)
2556 if (patches.Size() == 0)
2558 GetPatchNets(Nodes, Dimension());
2562 void NURBSExtension::SetCoordsFromPatches(Vector &Nodes)
2564 if (patches.Size() == 0) { return; }
2566 SetSolutionVector(Nodes, Dimension());
2570 void NURBSExtension::SetKnotsFromPatches()
2572 if (patches.Size() == 0)
2575 " No patches available!
");
2578 Array<KnotVector *> kv;
2580 for (int p = 0; p < patches.Size(); p++)
2582 GetPatchKnotVectors(p, kv);
2584 for (int i = 0; i < kv.Size(); i++)
2586 *kv[i] = *patches[p]->GetKV(i);
2590 SetOrdersFromKnotVectors();
2596 // all elements must be active
2597 NumOfActiveElems = NumOfElements;
2598 activeElem.SetSize(NumOfElements);
2601 GenerateActiveVertices();
2602 GenerateElementDofTable();
2603 GenerateActiveBdrElems();
2604 GenerateBdrElementDofTable();
2607 void NURBSExtension::LoadSolution(std::istream &input, GridFunction &sol) const
2609 const FiniteElementSpace *fes = sol.FESpace();
2610 MFEM_VERIFY(fes->GetNURBSext() == this, "");
2612 sol.SetSize(fes->GetVSize());
2614 Array<const KnotVector *> kv(Dimension());
2615 NURBSPatchMap p2g(this);
2616 const int vdim = fes->GetVDim();
2618 for (int p = 0; p < GetNP(); p++)
2620 skip_comment_lines(input, '#');
2622 p2g.SetPatchDofMap(p, kv);
2623 const int nx = kv[0]->GetNCP();
2624 const int ny = kv[1]->GetNCP();
2625 const int nz = (kv.Size() == 2) ? 1 : kv[2]->GetNCP();
2626 for (int k = 0; k < nz; k++)
2628 for (int j = 0; j < ny; j++)
2630 for (int i = 0; i < nx; i++)
2632 const int l = (kv.Size() == 2) ? p2g(i,j) : p2g(i,j,k);
2633 for (int vd = 0; vd < vdim; vd++)
2635 input >> sol(fes->DofToVDof(l,vd));
2643 void NURBSExtension::PrintSolution(const GridFunction &sol, std::ostream &out)
2646 const FiniteElementSpace *fes = sol.FESpace();
2647 MFEM_VERIFY(fes->GetNURBSext() == this, "");
2649 Array<const KnotVector *> kv(Dimension());
2650 NURBSPatchMap p2g(this);
2651 const int vdim = fes->GetVDim();
2653 for (int p = 0; p < GetNP(); p++)
2655 out << "\n# patch
" << p << "\n\n
";
2657 p2g.SetPatchDofMap(p, kv);
2658 const int nx = kv[0]->GetNCP();
2659 const int ny = kv[1]->GetNCP();
2660 const int nz = (kv.Size() == 2) ? 1 : kv[2]->GetNCP();
2661 for (int k = 0; k < nz; k++)
2663 for (int j = 0; j < ny; j++)
2665 for (int i = 0; i < nx; i++)
2667 const int l = (kv.Size() == 2) ? p2g(i,j) : p2g(i,j,k);
2668 out << sol(fes->DofToVDof(l,0));
2669 for (int vd = 1; vd < vdim; vd++)
2671 out << ' ' << sol(fes->DofToVDof(l,vd));
2680 void NURBSExtension::DegreeElevate(int rel_degree, int degree)
2682 for (int p = 0; p < patches.Size(); p++)
2684 for (int dir = 0; dir < patches[p]->GetNKV(); dir++)
2686 int oldd = patches[p]->GetKV(dir)->GetOrder();
2687 int newd = std::min(oldd + rel_degree, degree);
2690 patches[p]->DegreeElevate(dir, newd - oldd);
2696 void NURBSExtension::UniformRefinement()
2698 for (int p = 0; p < patches.Size(); p++)
2700 patches[p]->UniformRefinement();
2704 void NURBSExtension::KnotInsert(Array<KnotVector *> &kv)
2709 Array<KnotVector *> pkv(Dimension());
2711 for (int p = 0; p < patches.Size(); p++)
2713 patchTopo->GetElementEdges(p, edges, orient);
2717 pkv[0] = kv[KnotInd(edges[0])];
2718 pkv[1] = kv[KnotInd(edges[1])];
2722 pkv[0] = kv[KnotInd(edges[0])];
2723 pkv[1] = kv[KnotInd(edges[3])];
2724 pkv[2] = kv[KnotInd(edges[8])];
2727 patches[p]->KnotInsert(pkv);
2731 void NURBSExtension::GetPatchNets(const Vector &coords, int vdim)
2733 if (Dimension() == 2)
2735 Get2DPatchNets(coords, vdim);
2739 Get3DPatchNets(coords, vdim);
2743 void NURBSExtension::Get2DPatchNets(const Vector &coords, int vdim)
2745 Array<const KnotVector *> kv(2);
2746 NURBSPatchMap p2g(this);
2748 patches.SetSize(GetNP());
2749 for (int p = 0; p < GetNP(); p++)
2751 p2g.SetPatchDofMap(p, kv);
2752 patches[p] = new NURBSPatch(kv, vdim+1);
2753 NURBSPatch &Patch = *patches[p];
2755 for (int j = 0; j < kv[1]->GetNCP(); j++)
2757 for (int i = 0; i < kv[0]->GetNCP(); i++)
2759 const int l = p2g(i,j);
2760 for (int d = 0; d < vdim; d++)
2762 Patch(i,j,d) = coords(l*vdim + d)*weights(l);
2764 Patch(i,j,vdim) = weights(l);
2770 void NURBSExtension::Get3DPatchNets(const Vector &coords, int vdim)
2772 Array<const KnotVector *> kv(3);
2773 NURBSPatchMap p2g(this);
2775 patches.SetSize(GetNP());
2776 for (int p = 0; p < GetNP(); p++)
2778 p2g.SetPatchDofMap(p, kv);
2779 patches[p] = new NURBSPatch(kv, vdim+1);
2780 NURBSPatch &Patch = *patches[p];
2782 for (int k = 0; k < kv[2]->GetNCP(); k++)
2784 for (int j = 0; j < kv[1]->GetNCP(); j++)
2786 for (int i = 0; i < kv[0]->GetNCP(); i++)
2788 const int l = p2g(i,j,k);
2789 for (int d = 0; d < vdim; d++)
2791 Patch(i,j,k,d) = coords(l*vdim + d)*weights(l);
2793 Patch(i,j,k,vdim) = weights(l);
2800 void NURBSExtension::SetSolutionVector(Vector &coords, int vdim)
2802 if (Dimension() == 2)
2804 Set2DSolutionVector(coords, vdim);
2808 Set3DSolutionVector(coords, vdim);
2812 void NURBSExtension::Set2DSolutionVector(Vector &coords, int vdim)
2814 Array<const KnotVector *> kv(2);
2815 NURBSPatchMap p2g(this);
2817 weights.SetSize(GetNDof());
2818 for (int p = 0; p < GetNP(); p++)
2820 p2g.SetPatchDofMap(p, kv);
2821 NURBSPatch &Patch = *patches[p];
2822 MFEM_ASSERT(vdim+1 == Patch.GetNC(), "");
2824 for (int j = 0; j < kv[1]->GetNCP(); j++)
2826 for (int i = 0; i < kv[0]->GetNCP(); i++)
2828 const int l = p2g(i,j);
2829 for (int d = 0; d < vdim; d++)
2831 coords(l*vdim + d) = Patch(i,j,d)/Patch(i,j,vdim);
2833 weights(l) = Patch(i,j,vdim);
2840 void NURBSExtension::Set3DSolutionVector(Vector &coords, int vdim)
2842 Array<const KnotVector *> kv(3);
2843 NURBSPatchMap p2g(this);
2845 weights.SetSize(GetNDof());
2846 for (int p = 0; p < GetNP(); p++)
2848 p2g.SetPatchDofMap(p, kv);
2849 NURBSPatch &Patch = *patches[p];
2850 MFEM_ASSERT(vdim+1 == Patch.GetNC(), "");
2852 for (int k = 0; k < kv[2]->GetNCP(); k++)
2854 for (int j = 0; j < kv[1]->GetNCP(); j++)
2856 for (int i = 0; i < kv[0]->GetNCP(); i++)
2858 const int l = p2g(i,j,k);
2859 for (int d = 0; d < vdim; d++)
2861 coords(l*vdim + d) = Patch(i,j,k,d)/Patch(i,j,k,vdim);
2863 weights(l) = Patch(i,j,k,vdim);
2873 ParNURBSExtension::ParNURBSExtension(const ParNURBSExtension &orig)
2874 : NURBSExtension(orig),
2875 partitioning(orig.partitioning ? new int[orig.GetGNE()] : NULL),
2877 ldof_group(orig.ldof_group)
2879 // Copy the partitioning, if not NULL
2882 std::memcpy(partitioning, orig.partitioning, orig.GetGNE()*sizeof(int));
2886 ParNURBSExtension::ParNURBSExtension(MPI_Comm comm, NURBSExtension *parent,
2887 int *part, const Array<bool> &active_bel)
2890 if (parent->NumOfActiveElems < parent->NumOfElements)
2892 // SetActive (BuildGroups?) and the way the weights are copied
2893 // do not support this case
2895 " all elements in the parent must be active!
");
2898 patchTopo = parent->patchTopo;
2899 // steal ownership of patchTopo from the 'parent' NURBS extension
2900 if (!parent->own_topo)
2903 " parent does not own the patch topology!
");
2906 parent->own_topo = 0;
2908 parent->edge_to_knot.Copy(edge_to_knot);
2910 parent->GetOrders().Copy(mOrders);
2911 mOrder = parent->GetOrder();
2913 NumOfKnotVectors = parent->GetNKV();
2914 knotVectors.SetSize(NumOfKnotVectors);
2915 for (int i = 0; i < NumOfKnotVectors; i++)
2917 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
2924 // copy 'part' to 'partitioning'
2925 partitioning = new int[GetGNE()];
2926 for (int i = 0; i < GetGNE(); i++)
2928 partitioning[i] = part[i];
2930 SetActive(partitioning, active_bel);
2932 GenerateActiveVertices();
2933 GenerateElementDofTable();
2934 // GenerateActiveBdrElems(); // done by SetActive for now
2935 GenerateBdrElementDofTable();
2937 Table *serial_elem_dof = parent->GetElementDofTable();
2938 BuildGroups(partitioning, *serial_elem_dof);
2940 weights.SetSize(GetNDof());
2941 // copy weights from parent
2942 for (int gel = 0, lel = 0; gel < GetGNE(); gel++)
2944 if (activeElem[gel])
2946 int ndofs = el_dof->RowSize(lel);
2947 int *ldofs = el_dof->GetRow(lel);
2948 int *gdofs = serial_elem_dof->GetRow(gel);
2949 for (int i = 0; i < ndofs; i++)
2951 weights(ldofs[i]) = parent->weights(gdofs[i]);
2958 ParNURBSExtension::ParNURBSExtension(NURBSExtension *parent,
2959 const ParNURBSExtension *par_parent)
2960 : gtopo(par_parent->gtopo.GetComm())
2962 // steal all data from parent
2963 mOrder = parent->mOrder;
2964 Swap(mOrders, parent->mOrders);
2966 patchTopo = parent->patchTopo;
2967 own_topo = parent->own_topo;
2968 parent->own_topo = 0;
2970 Swap(edge_to_knot, parent->edge_to_knot);
2972 NumOfKnotVectors = parent->NumOfKnotVectors;
2973 Swap(knotVectors, parent->knotVectors);
2975 NumOfVertices = parent->NumOfVertices;
2976 NumOfElements = parent->NumOfElements;
2977 NumOfBdrElements = parent->NumOfBdrElements;
2978 NumOfDofs = parent->NumOfDofs;
2980 Swap(v_meshOffsets, parent->v_meshOffsets);
2981 Swap(e_meshOffsets, parent->e_meshOffsets);
2982 Swap(f_meshOffsets, parent->f_meshOffsets);
2983 Swap(p_meshOffsets, parent->p_meshOffsets);
2985 Swap(v_spaceOffsets, parent->v_spaceOffsets);
2986 Swap(e_spaceOffsets, parent->e_spaceOffsets);
2987 Swap(f_spaceOffsets, parent->f_spaceOffsets);
2988 Swap(p_spaceOffsets, parent->p_spaceOffsets);
2990 NumOfActiveVertices = parent->NumOfActiveVertices;
2991 NumOfActiveElems = parent->NumOfActiveElems;
2992 NumOfActiveBdrElems = parent->NumOfActiveBdrElems;
2993 NumOfActiveDofs = parent->NumOfActiveDofs;
2995 Swap(activeVert, parent->activeVert);
2996 Swap(activeElem, parent->activeElem);
2997 Swap(activeBdrElem, parent->activeBdrElem);
2998 Swap(activeDof, parent->activeDof);
3000 el_dof = parent->el_dof;
3001 bel_dof = parent->bel_dof;
3002 parent->el_dof = parent->bel_dof = NULL;
3004 Swap(el_to_patch, parent->el_to_patch);
3005 Swap(bel_to_patch, parent->bel_to_patch);
3006 Swap(el_to_IJK, parent->el_to_IJK);
3007 Swap(bel_to_IJK, parent->bel_to_IJK);
3009 Swap(weights, parent->weights);
3010 MFEM_VERIFY(!parent->HavePatches(), "");
3014 partitioning = NULL;
3016 MFEM_VERIFY(par_parent->partitioning,
3019 // Support for the case when 'parent' is not a local NURBSExtension, i.e.
3020 // NumOfActiveElems is not the same as in 'par_parent'. In that case, we
3021 // assume 'parent' is a global NURBSExtension, i.e. all elements are active.
3022 bool extract_weights = false;
3023 if (NumOfActiveElems != par_parent->NumOfActiveElems)
3025 MFEM_ASSERT(NumOfActiveElems == NumOfElements, "internal error
");
3027 SetActive(par_parent->partitioning, par_parent->activeBdrElem);
3028 GenerateActiveVertices();
3030 el_to_patch.DeleteAll();
3031 el_to_IJK.DeleteAll();
3032 GenerateElementDofTable();
3033 // GenerateActiveBdrElems(); // done by SetActive for now
3035 bel_to_patch.DeleteAll();
3036 bel_to_IJK.DeleteAll();
3037 GenerateBdrElementDofTable();
3038 extract_weights = true;
3041 Table *glob_elem_dof = GetGlobalElementDofTable();
3042 BuildGroups(par_parent->partitioning, *glob_elem_dof);
3043 if (extract_weights)
3045 Vector glob_weights;
3046 Swap(weights, glob_weights);
3047 weights.SetSize(GetNDof());
3048 // Copy the local 'weights' from the 'glob_weights'.
3049 // Assumption: the local element ids follow the global ordering.
3050 for (int gel = 0, lel = 0; gel < GetGNE(); gel++)
3052 if (activeElem[gel])
3054 int ndofs = el_dof->RowSize(lel);
3055 int *ldofs = el_dof->GetRow(lel);
3056 int *gdofs = glob_elem_dof->GetRow(gel);
3057 for (int i = 0; i < ndofs; i++)
3059 weights(ldofs[i]) = glob_weights(gdofs[i]);
3065 delete glob_elem_dof;
3068 Table *ParNURBSExtension::GetGlobalElementDofTable()
3070 if (Dimension() == 2)
3072 return Get2DGlobalElementDofTable();
3076 return Get3DGlobalElementDofTable();
3080 Table *ParNURBSExtension::Get2DGlobalElementDofTable()
3083 const KnotVector *kv[2];
3084 NURBSPatchMap p2g(this);
3085 Array<Connection> gel_dof_list;
3087 for (int p = 0; p < GetNP(); p++)
3089 p2g.SetPatchDofMap(p, kv);
3092 const int ord0 = kv[0]->GetOrder();
3093 const int ord1 = kv[1]->GetOrder();
3094 for (int j = 0; j < kv[1]->GetNKS(); j++)
3096 if (kv[1]->isElement(j))
3098 for (int i = 0; i < kv[0]->GetNKS(); i++)
3100 if (kv[0]->isElement(i))
3102 Connection conn(el,0);
3103 for (int jj = 0; jj <= ord1; jj++)
3105 for (int ii = 0; ii <= ord0; ii++)
3107 conn.to = p2g(i+ii,j+jj);
3108 gel_dof_list.Append(conn);
3117 // We must NOT sort gel_dof_list in this case.
3118 return (new Table(GetGNE(), gel_dof_list));
3121 Table *ParNURBSExtension::Get3DGlobalElementDofTable()
3124 const KnotVector *kv[3];
3125 NURBSPatchMap p2g(this);
3126 Array<Connection> gel_dof_list;
3128 for (int p = 0; p < GetNP(); p++)
3130 p2g.SetPatchDofMap(p, kv);
3133 const int ord0 = kv[0]->GetOrder();
3134 const int ord1 = kv[1]->GetOrder();
3135 const int ord2 = kv[2]->GetOrder();
3136 for (int k = 0; k < kv[2]->GetNKS(); k++)
3138 if (kv[2]->isElement(k))
3140 for (int j = 0; j < kv[1]->GetNKS(); j++)
3142 if (kv[1]->isElement(j))
3144 for (int i = 0; i < kv[0]->GetNKS(); i++)
3146 if (kv[0]->isElement(i))
3148 Connection conn(el,0);
3149 for (int kk = 0; kk <= ord2; kk++)
3151 for (int jj = 0; jj <= ord1; jj++)
3153 for (int ii = 0; ii <= ord0; ii++)
3155 conn.to = p2g(i+ii,j+jj,k+kk);
3156 gel_dof_list.Append(conn);
3168 // We must NOT sort gel_dof_list in this case.
3169 return (new Table(GetGNE(), gel_dof_list));
3172 void ParNURBSExtension::SetActive(const int *_partitioning,
3173 const Array<bool> &active_bel)
3175 activeElem.SetSize(GetGNE());
3177 NumOfActiveElems = 0;
3178 const int MyRank = gtopo.MyRank();
3179 for (int i = 0; i < GetGNE(); i++)
3180 if (_partitioning[i] == MyRank)
3182 activeElem[i] = true;
3186 active_bel.Copy(activeBdrElem);
3187 NumOfActiveBdrElems = 0;
3188 for (int i = 0; i < GetGNBE(); i++)
3189 if (activeBdrElem[i])
3191 NumOfActiveBdrElems++;
3195 void ParNURBSExtension::BuildGroups(const int *_partitioning,
3196 const Table &elem_dof)
3200 ListOfIntegerSets groups;
3203 Transpose(elem_dof, dof_proc); // dof_proc is dof_elem
3204 // convert elements to processors
3205 for (int i = 0; i < dof_proc.Size_of_connections(); i++)
3207 dof_proc.GetJ()[i] = _partitioning[dof_proc.GetJ()[i]];
3210 // the first group is the local one
3211 int MyRank = gtopo.MyRank();
3212 group.Recreate(1, &MyRank);
3213 groups.Insert(group);
3216 ldof_group.SetSize(GetNDof());
3217 for (int d = 0; d < GetNTotalDof(); d++)
3220 group.Recreate(dof_proc.RowSize(d), dof_proc.GetRow(d));
3221 ldof_group[dof] = groups.Insert(group);
3226 gtopo.Create(groups, 1822);
3228 #endif // MFEM_USE_MPI
3231 void NURBSPatchMap::GetPatchKnotVectors(int p, const KnotVector *kv[])
3233 Ext->patchTopo->GetElementVertices(p, verts);
3234 Ext->patchTopo->GetElementEdges(p, edges, oedge);
3235 if (Ext->Dimension() == 2)
3237 kv[0] = Ext->KnotVec(edges[0]);
3238 kv[1] = Ext->KnotVec(edges[1]);
3242 Ext->patchTopo->GetElementFaces(p, faces, oface);
3244 kv[0] = Ext->KnotVec(edges[0]);
3245 kv[1] = Ext->KnotVec(edges[3]);
3246 kv[2] = Ext->KnotVec(edges[8]);
3251 void NURBSPatchMap::GetBdrPatchKnotVectors(int p, const KnotVector *kv[],
3254 Ext->patchTopo->GetBdrElementVertices(p, verts);
3255 Ext->patchTopo->GetBdrElementEdges(p, edges, oedge);
3256 kv[0] = Ext->KnotVec(edges[0], oedge[0], &okv[0]);
3257 if (Ext->Dimension() == 3)
3260 Ext->patchTopo->GetBdrElementFace(p, &faces[0], &opatch);
3261 kv[1] = Ext->KnotVec(edges[1], oedge[1], &okv[1]);
3269 void NURBSPatchMap::SetPatchVertexMap(int p, const KnotVector *kv[])
3271 GetPatchKnotVectors(p, kv);
3273 I = kv[0]->GetNE() - 1;
3274 J = kv[1]->GetNE() - 1;
3276 for (int i = 0; i < verts.Size(); i++)
3278 verts[i] = Ext->v_meshOffsets[verts[i]];
3281 for (int i = 0; i < edges.Size(); i++)
3283 edges[i] = Ext->e_meshOffsets[edges[i]];
3286 if (Ext->Dimension() == 3)
3288 K = kv[2]->GetNE() - 1;
3290 for (int i = 0; i < faces.Size(); i++)
3292 faces[i] = Ext->f_meshOffsets[faces[i]];
3296 pOffset = Ext->p_meshOffsets[p];
3299 void NURBSPatchMap::SetPatchDofMap(int p, const KnotVector *kv[])
3301 GetPatchKnotVectors(p, kv);
3303 I = kv[0]->GetNCP() - 2;
3304 J = kv[1]->GetNCP() - 2;
3306 for (int i = 0; i < verts.Size(); i++)
3308 verts[i] = Ext->v_spaceOffsets[verts[i]];
3311 for (int i = 0; i < edges.Size(); i++)
3313 edges[i] = Ext->e_spaceOffsets[edges[i]];
3316 if (Ext->Dimension() == 3)
3318 K = kv[2]->GetNCP() - 2;
3320 for (int i = 0; i < faces.Size(); i++)
3322 faces[i] = Ext->f_spaceOffsets[faces[i]];
3326 pOffset = Ext->p_spaceOffsets[p];
3329 void NURBSPatchMap::SetBdrPatchVertexMap(int p, const KnotVector *kv[],
3332 GetBdrPatchKnotVectors(p, kv, okv);
3334 I = kv[0]->GetNE() - 1;
3336 for (int i = 0; i < verts.Size(); i++)
3338 verts[i] = Ext->v_meshOffsets[verts[i]];
3341 if (Ext->Dimension() == 2)
3343 pOffset = Ext->e_meshOffsets[edges[0]];
3347 J = kv[1]->GetNE() - 1;
3349 for (int i = 0; i < edges.Size(); i++)
3351 edges[i] = Ext->e_meshOffsets[edges[i]];
3354 pOffset = Ext->f_meshOffsets[faces[0]];
3358 void NURBSPatchMap::SetBdrPatchDofMap(int p, const KnotVector *kv[], int *okv)
3360 GetBdrPatchKnotVectors(p, kv, okv);
3362 I = kv[0]->GetNCP() - 2;
3364 for (int i = 0; i < verts.Size(); i++)
3366 verts[i] = Ext->v_spaceOffsets[verts[i]];
3369 if (Ext->Dimension() == 2)
3371 pOffset = Ext->e_spaceOffsets[edges[0]];
3375 J = kv[1]->GetNCP() - 2;
3377 for (int i = 0; i < edges.Size(); i++)
3379 edges[i] = Ext->e_spaceOffsets[edges[i]];
3382 pOffset = Ext->f_spaceOffsets[faces[0]];
KnotVector * DegreeElevate(int t) const
void DegreeElevate(int dir, int t)
NURBSPatch * Interpolate(NURBSPatch &p1, NURBSPatch &p2)
void KnotInsert(int dir, const KnotVector &knot)
void SetSize(int s)
Resize the vector to size s.
void Rotate3D(double normal[], double angle)
void GetElements()
Count the number of elements.
void SwapDirections(int dir1, int dir2)
KnotVector()
Create KnotVector.
static const int MaxOrder
void UniformRefinement(Vector &newknots) const
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
KnotVector & operator=(const KnotVector &kv)
void CalcShape(Vector &shape, int i, double xi) const
NURBSPatch * Revolve3D(NURBSPatch &patch, double n[], double ang, int times)
void Difference(const KnotVector &kv, Vector &diff) const
void Print(std::ostream &out) const
void CalcDShape(Vector &grad, int i, double xi) const
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
int SetLoopDirection(int dir)