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 d_to_d(orig.d_to_d),
1202 master(orig.master),
1204 v_meshOffsets(orig.v_meshOffsets),
1205 e_meshOffsets(orig.e_meshOffsets),
1206 f_meshOffsets(orig.f_meshOffsets),
1207 p_meshOffsets(orig.p_meshOffsets),
1208 v_spaceOffsets(orig.v_spaceOffsets),
1209 e_spaceOffsets(orig.e_spaceOffsets),
1210 f_spaceOffsets(orig.f_spaceOffsets),
1211 p_spaceOffsets(orig.p_spaceOffsets),
1212 el_dof(orig.el_dof ? new Table(*orig.el_dof) : NULL),
1213 bel_dof(orig.bel_dof ? new Table(*orig.bel_dof) : NULL),
1214 el_to_patch(orig.el_to_patch),
1215 bel_to_patch(orig.bel_to_patch),
1216 el_to_IJK(orig.el_to_IJK),
1217 bel_to_IJK(orig.bel_to_IJK),
1218 patches(orig.patches.Size()) // patches are copied in the body
1220 // Copy the knot vectors:
1221 for (int i = 0; i < knotVectors.Size(); i++)
1223 knotVectors[i] = new KnotVector(*orig.knotVectors[i]);
1226 // Copy the patches:
1227 for (int p = 0; p < patches.Size(); p++)
1229 patches[p] = new NURBSPatch(*orig.patches[p]);
1233 NURBSExtension::NURBSExtension(std::istream &input)
1236 patchTopo = new Mesh;
1237 patchTopo->LoadPatchTopo(input, edge_to_knot);
1241 // CheckBdrPatches();
1243 skip_comment_lines(input, '#');
1245 // Read knotvectors or patches
1247 input >> ws >> ident; // 'knotvectors' or 'patches'
1248 if (ident == "knotvectors
")
1250 input >> NumOfKnotVectors;
1251 knotVectors.SetSize(NumOfKnotVectors);
1252 for (int i = 0; i < NumOfKnotVectors; i++)
1254 knotVectors[i] = new KnotVector(input);
1257 else if (ident == "patches
")
1259 patches.SetSize(GetNP());
1260 for (int p = 0; p < patches.Size(); p++)
1262 skip_comment_lines(input, '#');
1263 patches[p] = new NURBSPatch(input);
1266 NumOfKnotVectors = 0;
1267 for (int i = 0; i < patchTopo->GetNEdges(); i++)
1268 if (NumOfKnotVectors < KnotInd(i))
1270 NumOfKnotVectors = KnotInd(i);
1273 knotVectors.SetSize(NumOfKnotVectors);
1276 Array<int> edges, oedge;
1277 for (int p = 0; p < patches.Size(); p++)
1279 patchTopo->GetElementEdges(p, edges, oedge);
1280 if (Dimension() == 2)
1282 if (knotVectors[KnotInd(edges[0])] == NULL)
1284 knotVectors[KnotInd(edges[0])] =
1285 new KnotVector(*patches[p]->GetKV(0));
1287 if (knotVectors[KnotInd(edges[1])] == NULL)
1289 knotVectors[KnotInd(edges[1])] =
1290 new KnotVector(*patches[p]->GetKV(1));
1295 if (knotVectors[KnotInd(edges[0])] == NULL)
1297 knotVectors[KnotInd(edges[0])] =
1298 new KnotVector(*patches[p]->GetKV(0));
1300 if (knotVectors[KnotInd(edges[3])] == NULL)
1302 knotVectors[KnotInd(edges[3])] =
1303 new KnotVector(*patches[p]->GetKV(1));
1305 if (knotVectors[KnotInd(edges[8])] == NULL)
1307 knotVectors[KnotInd(edges[8])] =
1308 new KnotVector(*patches[p]->GetKV(2));
1315 MFEM_ABORT("invalid section:
" << ident);
1318 SetOrdersFromKnotVectors();
1323 // NumOfVertices, NumOfElements, NumOfBdrElements, NumOfDofs
1325 skip_comment_lines(input, '#');
1327 // Check for a list of mesh elements
1328 if (patches.Size() == 0)
1330 input >> ws >> ident;
1332 if (patches.Size() == 0 && ident == "mesh_elements
")
1334 input >> NumOfActiveElems;
1335 activeElem.SetSize(GetGNE());
1338 for (int i = 0; i < NumOfActiveElems; i++)
1341 activeElem[glob_elem] = true;
1344 skip_comment_lines(input, '#');
1345 input >> ws >> ident;
1349 NumOfActiveElems = NumOfElements;
1350 activeElem.SetSize(NumOfElements);
1354 GenerateActiveVertices();
1356 GenerateElementDofTable();
1357 GenerateActiveBdrElems();
1358 GenerateBdrElementDofTable();
1361 if (ident == "periodic
")
1366 skip_comment_lines(input, '#');
1367 input >> ws >> ident;
1370 if (patches.Size() == 0)
1373 if (ident == "weights
")
1375 weights.Load(input, GetNDof());
1377 else // e.g. ident = "unitweights
" or "autoweights
"
1379 weights.SetSize(GetNDof());
1385 ConnectBoundaries();
1388 NURBSExtension::NURBSExtension(NURBSExtension *parent, int newOrder)
1390 patchTopo = parent->patchTopo;
1393 parent->edge_to_knot.Copy(edge_to_knot);
1395 NumOfKnotVectors = parent->GetNKV();
1396 knotVectors.SetSize(NumOfKnotVectors);
1397 const Array<int> &pOrders = parent->GetOrders();
1398 for (int i = 0; i < NumOfKnotVectors; i++)
1400 if (newOrder > pOrders[i])
1403 parent->GetKnotVector(i)->DegreeElevate(newOrder - pOrders[i]);
1407 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
1411 // copy some data from parent
1412 NumOfElements = parent->NumOfElements;
1413 NumOfBdrElements = parent->NumOfBdrElements;
1415 SetOrdersFromKnotVectors();
1417 GenerateOffsets(); // dof offsets will be different from parent
1419 NumOfActiveVertices = parent->NumOfActiveVertices;
1420 NumOfActiveElems = parent->NumOfActiveElems;
1421 NumOfActiveBdrElems = parent->NumOfActiveBdrElems;
1422 parent->activeVert.Copy(activeVert);
1424 parent->activeElem.Copy(activeElem);
1425 parent->activeBdrElem.Copy(activeBdrElem);
1427 GenerateElementDofTable();
1428 GenerateBdrElementDofTable();
1430 weights.SetSize(GetNDof());
1434 parent->master.Copy(master);
1435 parent->slave.Copy(slave);
1436 ConnectBoundaries();
1439 NURBSExtension::NURBSExtension(NURBSExtension *parent,
1440 const Array<int> &newOrders)
1442 newOrders.Copy(mOrders);
1443 SetOrderFromOrders();
1445 patchTopo = parent->patchTopo;
1448 parent->edge_to_knot.Copy(edge_to_knot);
1450 NumOfKnotVectors = parent->GetNKV();
1451 MFEM_VERIFY(mOrders.Size() == NumOfKnotVectors, "invalid newOrders array
");
1452 knotVectors.SetSize(NumOfKnotVectors);
1453 const Array<int> &pOrders = parent->GetOrders();
1455 for (int i = 0; i < NumOfKnotVectors; i++)
1457 if (mOrders[i] > pOrders[i])
1460 parent->GetKnotVector(i)->DegreeElevate(mOrders[i] - pOrders[i]);
1464 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
1468 // copy some data from parent
1469 NumOfElements = parent->NumOfElements;
1470 NumOfBdrElements = parent->NumOfBdrElements;
1472 GenerateOffsets(); // dof offsets will be different from parent
1474 NumOfActiveVertices = parent->NumOfActiveVertices;
1475 NumOfActiveElems = parent->NumOfActiveElems;
1476 NumOfActiveBdrElems = parent->NumOfActiveBdrElems;
1477 parent->activeVert.Copy(activeVert);
1479 parent->activeElem.Copy(activeElem);
1480 parent->activeBdrElem.Copy(activeBdrElem);
1482 GenerateElementDofTable();
1483 GenerateBdrElementDofTable();
1485 weights.SetSize(GetNDof());
1488 parent->master.Copy(master);
1489 parent->slave.Copy(slave);
1490 ConnectBoundaries();
1493 NURBSExtension::NURBSExtension(Mesh *mesh_array[], int num_pieces)
1495 NURBSExtension *parent = mesh_array[0]->NURBSext;
1497 if (!parent->own_topo)
1500 " parent does not own the patch topology!
");
1502 patchTopo = parent->patchTopo;
1504 parent->own_topo = 0;
1506 parent->edge_to_knot.Copy(edge_to_knot);
1508 parent->GetOrders().Copy(mOrders);
1509 mOrder = parent->GetOrder();
1511 NumOfKnotVectors = parent->GetNKV();
1512 knotVectors.SetSize(NumOfKnotVectors);
1513 for (int i = 0; i < NumOfKnotVectors; i++)
1515 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i));
1522 // assuming the meshes define a partitioning of all the elements
1523 NumOfActiveElems = NumOfElements;
1524 activeElem.SetSize(NumOfElements);
1527 GenerateActiveVertices();
1529 GenerateElementDofTable();
1530 GenerateActiveBdrElems();
1531 GenerateBdrElementDofTable();
1533 weights.SetSize(GetNDof());
1534 MergeWeights(mesh_array, num_pieces);
1537 NURBSExtension::~NURBSExtension()
1539 if (patches.Size() == 0)
1545 for (int i = 0; i < knotVectors.Size(); i++)
1547 delete knotVectors[i];
1550 for (int i = 0; i < patches.Size(); i++)
1561 void NURBSExtension::Print(std::ostream &out) const
1563 patchTopo->PrintTopo(out, edge_to_knot);
1564 if (patches.Size() == 0)
1566 out << "\nknotvectors\n
" << NumOfKnotVectors << '\n';
1567 for (int i = 0; i < NumOfKnotVectors; i++)
1569 knotVectors[i]->Print(out);
1572 if (NumOfActiveElems < NumOfElements)
1574 out << "\nmesh_elements\n
" << NumOfActiveElems << '\n';
1575 for (int i = 0; i < NumOfElements; i++)
1582 out << "\nweights\n
";
1583 weights.Print(out, 1);
1587 out << "\npatches\n
";
1588 for (int p = 0; p < patches.Size(); p++)
1590 out << "\n# patch
" << p << "\n\n
";
1591 patches[p]->Print(out);
1596 void NURBSExtension::PrintCharacteristics(std::ostream &out) const
1599 "NURBS
Mesh entity sizes:\n
"
1600 "Dimension =
" << Dimension() << "\n
"
1602 Array<int> unique_orders(mOrders);
1603 unique_orders.Sort();
1604 unique_orders.Unique();
1605 unique_orders.Print(out, unique_orders.Size());
1607 "NumOfKnotVectors =
" << GetNKV() << "\n
"
1608 "NumOfPatches =
" << GetNP() << "\n
"
1609 "NumOfBdrPatches =
" << GetNBP() << "\n
"
1610 "NumOfVertices =
" << GetGNV() << "\n
"
1611 "NumOfElements =
" << GetGNE() << "\n
"
1612 "NumOfBdrElements =
" << GetGNBE() << "\n
"
1613 "NumOfDofs =
" << GetNTotalDof() << "\n
"
1614 "NumOfActiveVertices =
" << GetNV() << "\n
"
1615 "NumOfActiveElems =
" << GetNE() << "\n
"
1616 "NumOfActiveBdrElems =
" << GetNBE() << "\n
"
1617 "NumOfActiveDofs =
" << GetNDof() << '\n';
1618 for (int i = 0; i < NumOfKnotVectors; i++)
1620 out << ' ' << i + 1 << ")
";
1621 knotVectors[i]->Print(out);
1626 void NURBSExtension::InitDofMap()
1633 void NURBSExtension::ConnectBoundaries(Array<int> &bnds0, Array<int> &bnds1)
1637 ConnectBoundaries();
1640 void NURBSExtension::ConnectBoundaries()
1642 if (master.Size() != slave.Size())
1646 if (master.Size() == 0 ) {
return; }
1649 d_to_d.SetSize(NumOfDofs);
1650 for (
int i = 0; i < NumOfDofs; i++) { d_to_d[i] = i; }
1652 for (
int i = 0; i < master.Size(); i++)
1654 if (Dimension() == 2)
1656 ConnectBoundaries2D(master[i], slave[i]);
1660 ConnectBoundaries3D(master[i], slave[i]);
1665 GenerateElementDofTable();
1666 GenerateBdrElementDofTable();
1671 int idx0 = -1, idx1 = -1;
1672 for (
int b = 0; b < GetNBP(); b++)
1674 if (bnd0 == patchTopo->GetBdrAttribute(b)) { idx0 = b; }
1675 if (bnd1 == patchTopo->GetBdrAttribute(b)) { idx1 = b; }
1677 MFEM_VERIFY(idx0 != -1,
"Bdr 0 not found");
1678 MFEM_VERIFY(idx1 != -1,
"Bdr 1 not found");
1683 int okv0[1],okv1[1];
1690 int nks0 = kv0[0]->
GetNKS();
1693 bool compatible =
true;
1694 if (p2g0.
nx() != p2g1.
nx()) { compatible =
false; }
1695 if (kv0[0]->GetNKS() != kv1[0]->
GetNKS()) { compatible =
false; }
1696 if (kv0[0]->GetOrder() != kv1[0]->
GetOrder()) { compatible =
false; }
1703 mfem_error(
"NURBS boundaries not compatible");
1707 for (
int i = 0; i < nks0; i++)
1709 if (kv0[0]->isElement(i))
1711 if (!kv1[0]->isElement(i)) {
mfem_error(
"isElement does not match"); }
1712 for (
int ii = 0; ii <= kv0[0]->
GetOrder(); ii++)
1714 int ii0 = (okv0[0] >= 0) ? (i+ii) : (nx-i-ii);
1715 int ii1 = (okv1[0] >= 0) ? (i+ii) : (nx-i-ii);
1717 d_to_d[p2g0(ii0)] = d_to_d[p2g1(ii1)];
1727 for (
int i = 0; i < d_to_d.Size(); i++)
1733 for (
int i = 0; i < tmp.
Size(); i++)
1735 if (tmp[i] == 1) { tmp[i] = cnt++; }
1739 for (
int i = 0; i < d_to_d.Size(); i++)
1741 d_to_d[i] = tmp[d_to_d[i]];
1747 int idx0 = -1, idx1 = -1;
1748 for (
int b = 0; b < GetNBP(); b++)
1750 if (bnd0 == patchTopo->GetBdrAttribute(b)) { idx0 = b; }
1751 if (bnd1 == patchTopo->GetBdrAttribute(b)) { idx1 = b; }
1753 MFEM_VERIFY(idx0 != -1,
"Bdr 0 not found");
1754 MFEM_VERIFY(idx1 != -1,
"Bdr 1 not found");
1759 int okv0[2],okv1[2];
1768 int nks0 = kv0[0]->
GetNKS();
1769 int nks1 = kv0[1]->
GetNKS();
1772 bool compatible =
true;
1773 if (p2g0.
nx() != p2g1.
nx()) { compatible =
false; }
1774 if (p2g0.
ny() != p2g1.
ny()) { compatible =
false; }
1776 if (kv0[0]->GetNKS() != kv1[0]->
GetNKS()) { compatible =
false; }
1777 if (kv0[1]->GetNKS() != kv1[0]->
GetNKS()) { compatible =
false; }
1779 if (kv0[0]->GetOrder() != kv1[0]->
GetOrder()) { compatible =
false; }
1780 if (kv0[1]->GetOrder() != kv1[1]->
GetOrder()) { compatible =
false; }
1792 mfem_error(
"NURBS boundaries not compatible");
1796 for (
int j = 0; j < nks1; j++)
1798 if (kv0[1]->isElement(j))
1800 if (!kv1[1]->isElement(j)) {
mfem_error(
"isElement does not match #1"); }
1801 for (
int i = 0; i < nks0; i++)
1803 if (kv0[0]->isElement(i))
1805 if (!kv1[0]->isElement(i)) {
mfem_error(
"isElement does not match #0"); }
1806 for (
int jj = 0; jj <= kv0[1]->
GetOrder(); jj++)
1808 int jj0 = (okv0[1] >= 0) ? (j+jj) : (ny-j-jj);
1809 int jj1 = (okv1[1] >= 0) ? (j+jj) : (ny-j-jj);
1811 for (
int ii = 0; ii <= kv0[0]->
GetOrder(); ii++)
1813 int ii0 = (okv0[0] >= 0) ? (i+ii) : (nx-i-ii);
1814 int ii1 = (okv1[0] >= 0) ? (i+ii) : (nx-i-ii);
1816 d_to_d[p2g0(ii0,jj0)] = d_to_d[p2g1(ii1,jj1)];
1828 for (
int i = 0; i < d_to_d.Size(); i++)
1834 for (
int i = 0; i < tmp.
Size(); i++)
1836 if (tmp[i] == 1) { tmp[i] = cnt++; }
1840 for (
int i = 0; i < d_to_d.Size(); i++)
1842 d_to_d[i] = tmp[d_to_d[i]];
1848 int vert[8], nv, g_el, nx, ny, nz,
dim = Dimension();
1854 activeVert.SetSize(GetGNV());
1856 for (
int p = 0; p < GetNP(); p++)
1862 nz = (dim == 3) ? p2g.
nz() : 1;
1864 for (
int k = 0; k < nz; k++)
1866 for (
int j = 0; j < ny; j++)
1868 for (
int i = 0; i < nx; i++)
1870 if (activeElem[g_el])
1874 vert[0] = p2g(i, j );
1875 vert[1] = p2g(i+1,j );
1876 vert[2] = p2g(i+1,j+1);
1877 vert[3] = p2g(i, j+1);
1882 vert[0] = p2g(i, j, k);
1883 vert[1] = p2g(i+1,j, k);
1884 vert[2] = p2g(i+1,j+1,k);
1885 vert[3] = p2g(i, j+1,k);
1887 vert[4] = p2g(i, j, k+1);
1888 vert[5] = p2g(i+1,j, k+1);
1889 vert[6] = p2g(i+1,j+1,k+1);
1890 vert[7] = p2g(i, j+1,k+1);
1894 for (
int v = 0; v < nv; v++)
1896 activeVert[vert[v]] = 1;
1905 NumOfActiveVertices = 0;
1906 for (
int i = 0; i < GetGNV(); i++)
1907 if (activeVert[i] == 1)
1909 activeVert[i] = NumOfActiveVertices++;
1915 int dim = Dimension();
1918 activeBdrElem.SetSize(GetGNBE());
1919 if (GetGNE() == GetNE())
1921 activeBdrElem =
true;
1922 NumOfActiveBdrElems = GetGNBE();
1925 activeBdrElem =
false;
1926 NumOfActiveBdrElems = 0;
1939 for (
int i = 0; i < num_pieces; i++)
1945 for (
int lel = 0; lel < lext->
GetNE(); lel++)
1947 int gel = lelem_elem[lel];
1949 int nd = el_dof->RowSize(gel);
1950 int *gdofs = el_dof->GetRow(gel);
1952 for (
int j = 0; j < nd; j++)
1954 weights(gdofs[j]) = lext->
weights(ldofs[j]);
1967 for (
int i = 0; i < num_pieces; i++)
1974 for (
int lel = 0; lel < lext->
GetNE(); lel++)
1990 for (
int p = 0; p < GetNP(); p++)
1992 patchTopo->GetElementEdges(p, edges, oedge);
1994 for (
int i = 0; i < edges.
Size(); i++)
1996 edges[i] = edge_to_knot[edges[i]];
1999 edges[i] = -1 - edges[i];
2003 if ((Dimension() == 2 &&
2004 (edges[0] != -1 - edges[2] || edges[1] != -1 - edges[3])) ||
2006 (Dimension() == 3 &&
2007 (edges[0] != edges[2] || edges[0] != edges[4] ||
2008 edges[0] != edges[6] || edges[1] != edges[3] ||
2009 edges[1] != edges[5] || edges[1] != edges[7] ||
2010 edges[8] != edges[9] || edges[8] != edges[10] ||
2011 edges[8] != edges[11])))
2013 mfem::err <<
"NURBSExtension::CheckPatch (patch = " << p
2014 <<
")\n Inconsistent edge-to-knot mapping!\n";
2018 if ((Dimension() == 2 &&
2019 (edges[0] < 0 || edges[1] < 0)) ||
2021 (Dimension() == 3 &&
2022 (edges[0] < 0 || edges[3] < 0 || edges[8] < 0)))
2024 mfem::err <<
"NURBSExtension::CheckPatch (patch = " << p
2025 <<
") : Bad orientation!\n";
2036 for (
int p = 0; p < GetNBP(); p++)
2038 patchTopo->GetBdrElementEdges(p, edges, oedge);
2040 for (
int i = 0; i < edges.
Size(); i++)
2042 edges[i] = edge_to_knot[edges[i]];
2045 edges[i] = -1 - edges[i];
2049 if ((Dimension() == 2 && (edges[0] < 0)) ||
2050 (Dimension() == 3 && (edges[0] < 0 || edges[1] < 0)))
2052 mfem::err <<
"NURBSExtension::CheckBdrPatch (boundary patch = "
2053 << p <<
") : Bad orientation!\n";
2064 patchTopo->GetElementEdges(p, edges, orient);
2066 if (Dimension() == 2)
2068 kv[0] = KnotVec(edges[0]);
2069 kv[1] = KnotVec(edges[1]);
2073 kv[0] = KnotVec(edges[0]);
2074 kv[1] = KnotVec(edges[3]);
2075 kv[2] = KnotVec(edges[8]);
2085 patchTopo->GetElementEdges(p, edges, orient);
2087 if (Dimension() == 2)
2089 kv[0] = KnotVec(edges[0]);
2090 kv[1] = KnotVec(edges[1]);
2094 kv[0] = KnotVec(edges[0]);
2095 kv[1] = KnotVec(edges[3]);
2096 kv[2] = KnotVec(edges[8]);
2106 patchTopo->GetBdrElementEdges(p, edges, orient);
2108 if (Dimension() == 2)
2110 kv[0] = KnotVec(edges[0]);
2114 kv[0] = KnotVec(edges[0]);
2115 kv[1] = KnotVec(edges[1]);
2126 patchTopo->GetBdrElementEdges(p, edges, orient);
2128 if (Dimension() == 2)
2130 kv[0] = KnotVec(edges[0]);
2134 kv[0] = KnotVec(edges[0]);
2135 kv[1] = KnotVec(edges[1]);
2141 MFEM_VERIFY(mOrders.Size() > 0,
"");
2142 mOrder = mOrders[0];
2143 for (
int i = 1; i < mOrders.Size(); i++)
2145 if (mOrders[i] != mOrder)
2155 mOrders.SetSize(NumOfKnotVectors);
2156 for (
int i = 0; i < NumOfKnotVectors; i++)
2158 mOrders[i] = knotVectors[i]->GetOrder();
2160 SetOrderFromOrders();
2165 int nv = patchTopo->GetNV();
2166 int ne = patchTopo->GetNEdges();
2167 int nf = patchTopo->GetNFaces();
2168 int np = patchTopo->GetNE();
2169 int meshCounter, spaceCounter,
dim = Dimension();
2175 e_meshOffsets.SetSize(ne);
2176 f_meshOffsets.SetSize(nf);
2177 p_meshOffsets.SetSize(np);
2179 v_spaceOffsets.SetSize(nv);
2180 e_spaceOffsets.SetSize(ne);
2181 f_spaceOffsets.SetSize(nf);
2182 p_spaceOffsets.SetSize(np);
2185 for (meshCounter = 0; meshCounter < nv; meshCounter++)
2187 v_meshOffsets[meshCounter] = meshCounter;
2188 v_spaceOffsets[meshCounter] = meshCounter;
2190 spaceCounter = meshCounter;
2193 for (
int e = 0; e < ne; e++)
2195 e_meshOffsets[e] = meshCounter;
2196 e_spaceOffsets[e] = spaceCounter;
2197 meshCounter += KnotVec(e)->GetNE() - 1;
2198 spaceCounter += KnotVec(e)->GetNCP() - 2;
2202 for (
int f = 0; f < nf; f++)
2204 f_meshOffsets[f] = meshCounter;
2205 f_spaceOffsets[f] = spaceCounter;
2207 patchTopo->GetFaceEdges(f, edges, orient);
2210 (KnotVec(edges[0])->GetNE() - 1) *
2211 (KnotVec(edges[1])->GetNE() - 1);
2213 (KnotVec(edges[0])->GetNCP() - 2) *
2214 (KnotVec(edges[1])->GetNCP() - 2);
2218 for (
int p = 0; p < np; p++)
2220 p_meshOffsets[p] = meshCounter;
2221 p_spaceOffsets[p] = spaceCounter;
2223 patchTopo->GetElementEdges(p, edges, orient);
2228 (KnotVec(edges[0])->GetNE() - 1) *
2229 (KnotVec(edges[1])->GetNE() - 1);
2231 (KnotVec(edges[0])->GetNCP() - 2) *
2232 (KnotVec(edges[1])->GetNCP() - 2);
2237 (KnotVec(edges[0])->GetNE() - 1) *
2238 (KnotVec(edges[3])->GetNE() - 1) *
2239 (KnotVec(edges[8])->GetNE() - 1);
2241 (KnotVec(edges[0])->GetNCP() - 2) *
2242 (KnotVec(edges[3])->GetNCP() - 2) *
2243 (KnotVec(edges[8])->GetNCP() - 2);
2246 NumOfVertices = meshCounter;
2247 NumOfDofs = spaceCounter;
2252 int dim = Dimension();
2256 for (
int p = 0; p < GetNP(); p++)
2258 GetPatchKnotVectors(p, kv);
2260 int ne = kv[0]->GetNE();
2261 for (
int d = 1; d <
dim; d++)
2263 ne *= kv[d]->GetNE();
2266 NumOfElements += ne;
2272 int dim = Dimension() - 1;
2275 NumOfBdrElements = 0;
2276 for (
int p = 0; p < GetNBP(); p++)
2278 GetBdrPatchKnotVectors(p, kv);
2280 int ne = kv[0]->GetNE();
2281 for (
int d = 1; d <
dim; d++)
2283 ne *= kv[d]->GetNE();
2286 NumOfBdrElements += ne;
2294 if (Dimension() == 2)
2296 Get2DElementTopo(elements);
2300 Get3DElementTopo(elements);
2312 for (
int p = 0; p < GetNP(); p++)
2318 int patch_attr = patchTopo->GetAttribute(p);
2320 for (
int j = 0; j < ny; j++)
2322 for (
int i = 0; i < nx; i++)
2326 ind[0] = activeVert[p2g(i, j )];
2327 ind[1] = activeVert[p2g(i+1,j )];
2328 ind[2] = activeVert[p2g(i+1,j+1)];
2329 ind[3] = activeVert[p2g(i, j+1)];
2348 for (
int p = 0; p < GetNP(); p++)
2355 int patch_attr = patchTopo->GetAttribute(p);
2357 for (
int k = 0; k < nz; k++)
2359 for (
int j = 0; j < ny; j++)
2361 for (
int i = 0; i < nx; i++)
2365 ind[0] = activeVert[p2g(i, j, k)];
2366 ind[1] = activeVert[p2g(i+1,j, k)];
2367 ind[2] = activeVert[p2g(i+1,j+1,k)];
2368 ind[3] = activeVert[p2g(i, j+1,k)];
2370 ind[4] = activeVert[p2g(i, j, k+1)];
2371 ind[5] = activeVert[p2g(i+1,j, k+1)];
2372 ind[6] = activeVert[p2g(i+1,j+1,k+1)];
2373 ind[7] = activeVert[p2g(i, j+1,k+1)];
2375 elements[el] =
new Hexahedron(ind, patch_attr);
2389 if (Dimension() == 2)
2391 Get2DBdrElementTopo(boundary);
2395 Get3DBdrElementTopo(boundary);
2407 for (
int b = 0; b < GetNBP(); b++)
2412 int bdr_patch_attr = patchTopo->GetBdrAttribute(b);
2414 for (
int i = 0; i < nx; i++)
2416 if (activeBdrElem[g_be])
2418 int _i = (okv[0] >= 0) ? i : (nx - 1 - i);
2419 ind[0] = activeVert[p2g[_i ]];
2420 ind[1] = activeVert[p2g[_i+1]];
2422 boundary[l_be] =
new Segment(ind, bdr_patch_attr);
2438 for (
int b = 0; b < GetNBP(); b++)
2444 int bdr_patch_attr = patchTopo->GetBdrAttribute(b);
2446 for (
int j = 0; j < ny; j++)
2448 int _j = (okv[1] >= 0) ? j : (ny - 1 - j);
2449 for (
int i = 0; i < nx; i++)
2451 if (activeBdrElem[g_be])
2453 int _i = (okv[0] >= 0) ? i : (nx - 1 - i);
2454 ind[0] = activeVert[p2g(_i, _j )];
2455 ind[1] = activeVert[p2g(_i+1,_j )];
2456 ind[2] = activeVert[p2g(_i+1,_j+1)];
2457 ind[3] = activeVert[p2g(_i, _j+1)];
2470 activeDof.SetSize(GetNTotalDof());
2473 if (Dimension() == 2)
2475 Generate2DElementDofTable();
2479 Generate3DElementDofTable();
2482 NumOfActiveDofs = 0;
2483 for (
int d = 0; d < GetNTotalDof(); d++)
2487 activeDof[d] = NumOfActiveDofs;
2490 int *dof = el_dof->GetJ();
2491 int ndof = el_dof->Size_of_connections();
2492 for (
int i = 0; i < ndof; i++)
2494 dof[i] = activeDof[dof[i]] - 1;
2506 el_to_patch.
SetSize(NumOfActiveElems);
2507 el_to_IJK.SetSize(NumOfActiveElems, 2);
2509 for (
int p = 0; p < GetNP(); p++)
2514 const int ord0 = kv[0]->
GetOrder();
2515 const int ord1 = kv[1]->
GetOrder();
2516 for (
int j = 0; j < kv[1]->
GetNKS(); j++)
2518 if (kv[1]->isElement(j))
2520 for (
int i = 0; i < kv[0]->
GetNKS(); i++)
2522 if (kv[0]->isElement(i))
2527 for (
int jj = 0; jj <= ord1; jj++)
2529 for (
int ii = 0; ii <= ord0; ii++)
2531 conn.
to = DofMap(p2g(i+ii,j+jj));
2532 activeDof[conn.
to] = 1;
2533 el_dof_list.
Append(conn);
2536 el_to_patch[el] = p;
2537 el_to_IJK(el,0) = i;
2538 el_to_IJK(el,1) = j;
2549 el_dof =
new Table(NumOfActiveElems, el_dof_list);
2560 el_to_patch.
SetSize(NumOfActiveElems);
2561 el_to_IJK.SetSize(NumOfActiveElems, 3);
2563 for (
int p = 0; p < GetNP(); p++)
2568 const int ord0 = kv[0]->
GetOrder();
2569 const int ord1 = kv[1]->
GetOrder();
2570 const int ord2 = kv[2]->
GetOrder();
2571 for (
int k = 0; k < kv[2]->
GetNKS(); k++)
2573 if (kv[2]->isElement(k))
2575 for (
int j = 0; j < kv[1]->
GetNKS(); j++)
2577 if (kv[1]->isElement(j))
2579 for (
int i = 0; i < kv[0]->
GetNKS(); i++)
2581 if (kv[0]->isElement(i))
2586 for (
int kk = 0; kk <= ord2; kk++)
2588 for (
int jj = 0; jj <= ord1; jj++)
2590 for (
int ii = 0; ii <= ord0; ii++)
2592 conn.
to = DofMap(p2g(i+ii, j+jj, k+kk));
2593 activeDof[conn.
to] = 1;
2594 el_dof_list.
Append(conn);
2599 el_to_patch[el] = p;
2600 el_to_IJK(el,0) = i;
2601 el_to_IJK(el,1) = j;
2602 el_to_IJK(el,2) = k;
2615 el_dof =
new Table(NumOfActiveElems, el_dof_list);
2620 if (Dimension() == 2)
2622 Generate2DBdrElementDofTable();
2626 Generate3DBdrElementDofTable();
2629 int *dof = bel_dof->GetJ();
2630 int ndof = bel_dof->Size_of_connections();
2631 for (
int i = 0; i < ndof; i++)
2633 dof[i] = activeDof[dof[i]] - 1;
2640 int lbe = 0, okv[1];
2645 bel_to_patch.
SetSize(NumOfActiveBdrElems);
2646 bel_to_IJK.SetSize(NumOfActiveBdrElems, 1);
2648 for (
int b = 0; b < GetNBP(); b++)
2651 const int nx = p2g.
nx();
2654 const int nks0 = kv[0]->
GetNKS();
2655 const int ord0 = kv[0]->
GetOrder();
2656 for (
int i = 0; i < nks0; i++)
2658 if (kv[0]->isElement(i))
2660 if (activeBdrElem[gbe])
2663 for (
int ii = 0; ii <= ord0; ii++)
2665 conn.
to = DofMap(p2g[(okv[0] >= 0) ? (i+ii) : (nx-i-ii)]);
2666 bel_dof_list.
Append(conn);
2668 bel_to_patch[lbe] = b;
2669 bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
2677 bel_dof =
new Table(NumOfActiveBdrElems, bel_dof_list);
2683 int lbe = 0, okv[2];
2688 bel_to_patch.
SetSize(NumOfActiveBdrElems);
2689 bel_to_IJK.SetSize(NumOfActiveBdrElems, 2);
2691 for (
int b = 0; b < GetNBP(); b++)
2694 const int nx = p2g.
nx();
2695 const int ny = p2g.
ny();
2698 const int nks0 = kv[0]->
GetNKS();
2699 const int ord0 = kv[0]->
GetOrder();
2700 const int nks1 = kv[1]->
GetNKS();
2701 const int ord1 = kv[1]->
GetOrder();
2702 for (
int j = 0; j < nks1; j++)
2704 if (kv[1]->isElement(j))
2706 for (
int i = 0; i < nks0; i++)
2708 if (kv[0]->isElement(i))
2710 if (activeBdrElem[gbe])
2713 for (
int jj = 0; jj <= ord1; jj++)
2715 const int _jj = (okv[1] >= 0) ? (j+jj) : (ny-j-jj);
2716 for (
int ii = 0; ii <= ord0; ii++)
2718 const int _ii = (okv[0] >= 0) ? (i+ii) : (nx-i-ii);
2719 conn.
to = DofMap(p2g(_ii, _jj));
2720 bel_dof_list.
Append(conn);
2723 bel_to_patch[lbe] = b;
2724 bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
2725 bel_to_IJK(lbe,1) = (okv[1] >= 0) ? j : (-1-j);
2735 bel_dof =
new Table(NumOfActiveBdrElems, bel_dof_list);
2741 for (
int gv = 0; gv < GetGNV(); gv++)
2742 if (activeVert[gv] >= 0)
2744 lvert_vert[activeVert[gv]] = gv;
2751 for (
int le = 0, ge = 0; ge < GetGNE(); ge++)
2754 lelem_elem[le++] = ge;
2766 NURBSFE->
SetIJK(el_to_IJK.GetRow(i));
2767 if (el_to_patch[i] != NURBSFE->
GetPatch())
2769 GetPatchKnotVectors(el_to_patch[i], NURBSFE->
KnotVectors());
2773 el_dof->GetRow(i, dofs);
2774 weights.GetSubVector(dofs, NURBSFE->
Weights());
2787 NURBSFE->
SetIJK(bel_to_IJK.GetRow(i));
2788 if (bel_to_patch[i] != NURBSFE->
GetPatch())
2790 GetBdrPatchKnotVectors(bel_to_patch[i], NURBSFE->
KnotVectors());
2791 NURBSFE->
SetPatch(bel_to_patch[i]);
2794 bel_dof->GetRow(i, dofs);
2795 weights.GetSubVector(dofs, NURBSFE->
Weights());
2805 if (patches.Size() == 0)
2807 GetPatchNets(Nodes, Dimension());
2813 if (patches.Size() == 0) {
return; }
2815 SetSolutionVector(Nodes, Dimension());
2821 if (patches.Size() == 0)
2823 mfem_error(
"NURBSExtension::SetKnotsFromPatches :"
2824 " No patches available!");
2829 for (
int p = 0; p < patches.Size(); p++)
2831 GetPatchKnotVectors(p, kv);
2833 for (
int i = 0; i < kv.
Size(); i++)
2835 *kv[i] = *patches[p]->GetKV(i);
2839 SetOrdersFromKnotVectors();
2846 NumOfActiveElems = NumOfElements;
2847 activeElem.SetSize(NumOfElements);
2850 GenerateActiveVertices();
2852 GenerateElementDofTable();
2853 GenerateActiveBdrElems();
2854 GenerateBdrElementDofTable();
2856 ConnectBoundaries();
2868 const int vdim = fes->
GetVDim();
2870 for (
int p = 0; p < GetNP(); p++)
2875 const int nx = kv[0]->GetNCP();
2876 const int ny = kv[1]->GetNCP();
2877 const int nz = (kv.
Size() == 2) ? 1 : kv[2]->GetNCP();
2878 for (
int k = 0; k < nz; k++)
2880 for (
int j = 0; j < ny; j++)
2882 for (
int i = 0; i < nx; i++)
2884 const int ll = (kv.
Size() == 2) ? p2g(i,j) : p2g(i,j,k);
2885 const int l = DofMap(ll);
2886 for (
int vd = 0; vd < vdim; vd++)
2904 const int vdim = fes->
GetVDim();
2906 for (
int p = 0; p < GetNP(); p++)
2908 out <<
"\n# patch " << p <<
"\n\n";
2911 const int nx = kv[0]->GetNCP();
2912 const int ny = kv[1]->GetNCP();
2913 const int nz = (kv.Size() == 2) ? 1 : kv[2]->GetNCP();
2914 for (
int k = 0; k < nz; k++)
2916 for (
int j = 0; j < ny; j++)
2918 for (
int i = 0; i < nx; i++)
2920 const int ll = (kv.Size() == 2) ? p2g(i,j) : p2g(i,j,k);
2921 const int l = DofMap(ll);
2923 for (
int vd = 1; vd < vdim; vd++)
2925 out <<
' ' << sol(fes->
DofToVDof(l,vd));
2936 for (
int p = 0; p < patches.Size(); p++)
2938 for (
int dir = 0; dir < patches[p]->GetNKV(); dir++)
2940 int oldd = patches[p]->GetKV(dir)->GetOrder();
2941 int newd = std::min(oldd + rel_degree, degree);
2944 patches[p]->DegreeElevate(dir, newd - oldd);
2952 for (
int p = 0; p < patches.Size(); p++)
2954 patches[p]->UniformRefinement();
2965 for (
int p = 0; p < patches.Size(); p++)
2967 patchTopo->GetElementEdges(p, edges, orient);
2971 pkv[0] = kv[KnotInd(edges[0])];
2972 pkv[1] = kv[KnotInd(edges[1])];
2976 pkv[0] = kv[KnotInd(edges[0])];
2977 pkv[1] = kv[KnotInd(edges[3])];
2978 pkv[2] = kv[KnotInd(edges[8])];
2981 patches[p]->KnotInsert(pkv);
2987 if (Dimension() == 2)
2989 Get2DPatchNets(coords, vdim);
2993 Get3DPatchNets(coords, vdim);
3002 patches.SetSize(GetNP());
3003 for (
int p = 0; p < GetNP(); p++)
3009 for (
int j = 0; j < kv[1]->GetNCP(); j++)
3011 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3013 const int l = DofMap(p2g(i,j));
3014 for (
int d = 0; d < vdim; d++)
3016 Patch(i,j,d) = coords(l*vdim + d)*weights(l);
3018 Patch(i,j,vdim) = weights(l);
3029 patches.SetSize(GetNP());
3030 for (
int p = 0; p < GetNP(); p++)
3036 for (
int k = 0; k < kv[2]->GetNCP(); k++)
3038 for (
int j = 0; j < kv[1]->GetNCP(); j++)
3040 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3042 const int l = DofMap(p2g(i,j,k));
3043 for (
int d = 0; d < vdim; d++)
3045 Patch(i,j,k,d) = coords(l*vdim + d)*weights(l);
3047 Patch(i,j,k,vdim) = weights(l);
3056 if (Dimension() == 2)
3058 Set2DSolutionVector(coords, vdim);
3062 Set3DSolutionVector(coords, vdim);
3071 weights.SetSize(GetNDof());
3072 for (
int p = 0; p < GetNP(); p++)
3076 MFEM_ASSERT(vdim+1 == Patch.
GetNC(),
"");
3078 for (
int j = 0; j < kv[1]->GetNCP(); j++)
3080 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3082 const int l = p2g(i,j);
3083 for (
int d = 0; d < vdim; d++)
3085 coords(l*vdim + d) = Patch(i,j,d)/Patch(i,j,vdim);
3087 weights(l) = Patch(i,j,vdim);
3099 weights.SetSize(GetNDof());
3100 for (
int p = 0; p < GetNP(); p++)
3104 MFEM_ASSERT(vdim+1 == Patch.
GetNC(),
"");
3106 for (
int k = 0; k < kv[2]->GetNCP(); k++)
3108 for (
int j = 0; j < kv[1]->GetNCP(); j++)
3110 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3112 const int l = p2g(i,j,k);
3113 for (
int d = 0; d < vdim; d++)
3115 coords(l*vdim + d) = Patch(i,j,k,d)/Patch(i,j,k,vdim);
3117 weights(l) = Patch(i,j,k,vdim);
3129 partitioning(orig.partitioning ? new int[orig.GetGNE()] : NULL),
3131 ldof_group(orig.ldof_group)
3136 std::memcpy(partitioning, orig.partitioning, orig.
GetGNE()*
sizeof(int));
3148 mfem_error(
"ParNURBSExtension::ParNURBSExtension :\n"
3149 " all elements in the parent must be active!");
3156 mfem_error(
"ParNURBSExtension::ParNURBSExtension :\n"
3157 " parent does not own the patch topology!");
3179 partitioning =
new int[
GetGNE()];
3180 for (
int i = 0; i <
GetGNE(); i++)
3182 partitioning[i] = part[i];
3184 SetActive(partitioning, active_bel);
3192 BuildGroups(partitioning, *serial_elem_dof);
3196 for (
int gel = 0, lel = 0; gel <
GetGNE(); gel++)
3202 int *gdofs = serial_elem_dof->
GetRow(gel);
3203 for (
int i = 0; i < ndofs; i++)
3214 : gtopo(par_parent->gtopo.GetComm())
3272 partitioning = NULL;
3274 MFEM_VERIFY(par_parent->partitioning,
3275 "parent ParNURBSExtension has no partitioning!");
3280 bool extract_weights =
false;
3285 SetActive(par_parent->partitioning, par_parent->
activeBdrElem);
3296 extract_weights =
true;
3299 Table *glob_elem_dof = GetGlobalElementDofTable();
3300 BuildGroups(par_parent->partitioning, *glob_elem_dof);
3301 if (extract_weights)
3308 for (
int gel = 0, lel = 0; gel <
GetGNE(); gel++)
3314 int *gdofs = glob_elem_dof->
GetRow(gel);
3315 for (
int i = 0; i < ndofs; i++)
3317 weights(ldofs[i]) = glob_weights(gdofs[i]);
3323 delete glob_elem_dof;
3326 Table *ParNURBSExtension::GetGlobalElementDofTable()
3330 return Get2DGlobalElementDofTable();
3334 return Get3DGlobalElementDofTable();
3338 Table *ParNURBSExtension::Get2DGlobalElementDofTable()
3341 const KnotVector *kv[2];
3343 Array<Connection> gel_dof_list;
3345 for (
int p = 0; p <
GetNP(); p++)
3347 p2g.SetPatchDofMap(p, kv);
3350 const int ord0 = kv[0]->GetOrder();
3351 const int ord1 = kv[1]->GetOrder();
3352 for (
int j = 0; j < kv[1]->GetNKS(); j++)
3354 if (kv[1]->isElement(j))
3356 for (
int i = 0; i < kv[0]->GetNKS(); i++)
3358 if (kv[0]->isElement(i))
3360 Connection conn(el,0);
3361 for (
int jj = 0; jj <= ord1; jj++)
3363 for (
int ii = 0; ii <= ord0; ii++)
3365 conn.to = p2g(i+ii,j+jj);
3366 gel_dof_list.Append(conn);
3376 return (
new Table(
GetGNE(), gel_dof_list));
3379 Table *ParNURBSExtension::Get3DGlobalElementDofTable()
3382 const KnotVector *kv[3];
3384 Array<Connection> gel_dof_list;
3386 for (
int p = 0; p <
GetNP(); p++)
3388 p2g.SetPatchDofMap(p, kv);
3391 const int ord0 = kv[0]->GetOrder();
3392 const int ord1 = kv[1]->GetOrder();
3393 const int ord2 = kv[2]->GetOrder();
3394 for (
int k = 0; k < kv[2]->GetNKS(); k++)
3396 if (kv[2]->isElement(k))
3398 for (
int j = 0; j < kv[1]->GetNKS(); j++)
3400 if (kv[1]->isElement(j))
3402 for (
int i = 0; i < kv[0]->GetNKS(); i++)
3404 if (kv[0]->isElement(i))
3406 Connection conn(el,0);
3407 for (
int kk = 0; kk <= ord2; kk++)
3409 for (
int jj = 0; jj <= ord1; jj++)
3411 for (
int ii = 0; ii <= ord0; ii++)
3413 conn.to = p2g(i+ii,j+jj,k+kk);
3414 gel_dof_list.Append(conn);
3427 return (
new Table(
GetGNE(), gel_dof_list));
3430 void ParNURBSExtension::SetActive(
const int *_partitioning,
3431 const Array<bool> &active_bel)
3437 for (
int i = 0; i <
GetGNE(); i++)
3438 if (_partitioning[i] == MyRank)
3446 for (
int i = 0; i <
GetGNBE(); i++)
3453 void ParNURBSExtension::BuildGroups(
const int *_partitioning,
3454 const Table &elem_dof)
3458 ListOfIntegerSets groups;
3463 for (
int i = 0; i < dof_proc.Size_of_connections(); i++)
3465 dof_proc.GetJ()[i] = _partitioning[dof_proc.GetJ()[i]];
3470 group.Recreate(1, &MyRank);
3471 groups.Insert(group);
3478 group.Recreate(dof_proc.RowSize(d), dof_proc.GetRow(d));
3486 #endif // MFEM_USE_MPI
3489 void NURBSPatchMap::GetPatchKnotVectors(
int p,
const KnotVector *kv[])
3495 kv[0] = Ext->
KnotVec(edges[0]);
3496 kv[1] = Ext->
KnotVec(edges[1]);
3502 kv[0] = Ext->
KnotVec(edges[0]);
3503 kv[1] = Ext->
KnotVec(edges[3]);
3504 kv[2] = Ext->
KnotVec(edges[8]);
3509 void NURBSPatchMap::GetBdrPatchKnotVectors(
int p,
const KnotVector *kv[],
3514 kv[0] = Ext->
KnotVec(edges[0], oedge[0], &okv[0]);
3519 kv[1] = Ext->
KnotVec(edges[1], oedge[1], &okv[1]);
3529 GetPatchKnotVectors(p, kv);
3531 I = kv[0]->
GetNE() - 1;
3532 J = kv[1]->
GetNE() - 1;
3534 for (
int i = 0; i < verts.
Size(); i++)
3539 for (
int i = 0; i < edges.
Size(); i++)
3546 K = kv[2]->
GetNE() - 1;
3548 for (
int i = 0; i < faces.
Size(); i++)
3559 GetPatchKnotVectors(p, kv);
3564 for (
int i = 0; i < verts.
Size(); i++)
3569 for (
int i = 0; i < edges.
Size(); i++)
3578 for (
int i = 0; i < faces.
Size(); i++)
3590 GetBdrPatchKnotVectors(p, kv, okv);
3592 I = kv[0]->
GetNE() - 1;
3594 for (
int i = 0; i < verts.
Size(); i++)
3605 J = kv[1]->
GetNE() - 1;
3607 for (
int i = 0; i < edges.
Size(); i++)
3618 GetBdrPatchKnotVectors(p, kv, okv);
3622 for (
int i = 0; i < verts.
Size(); i++)
3635 for (
int i = 0; i < edges.
Size(); i++)
Array< KnotVector * > knotVectors
Abstract class for Finite Elements.
Array< int > f_meshOffsets
KnotVector * DegreeElevate(int t) const
void Create(ListOfIntegerSets &groups, int mpitag)
Array2D< int > bel_to_IJK
int Size() const
Logical size of the array.
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
void SetCoordsFromPatches(Vector &Nodes)
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
void ConnectBoundaries2D(int bnd0, int bnd1)
KnotVector * KnotVec(int edge)
Class for grid function - Vector with associated FE space.
int DofToVDof(int dof, int vd, int ndofs=-1) const
void GetBdrElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of bdr element i.
void DegreeElevate(int dir, int t)
NURBSPatch * Interpolate(NURBSPatch &p1, NURBSPatch &p2)
void LoadBE(int i, const FiniteElement *BE) const
void Generate2DElementDofTable()
void MergeGridFunctions(GridFunction *gf_array[], int num_pieces, GridFunction &merged)
Array< const KnotVector * > & KnotVectors() const
void Generate3DElementDofTable()
void KnotInsert(int dir, const KnotVector &knot)
void MergeWeights(Mesh *mesh_array[], int num_pieces)
void SetSize(int s)
Resize the vector to size s.
void GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
void Get3DBdrElementTopo(Array< Element * > &boundary) const
void GetElementFaces(int i, Array< int > &, Array< int > &) const
Return the indices and the orientations of all faces of element i.
void Copy(Array ©) const
Create a copy of the current array.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
void Rotate3D(double normal[], double angle)
Array< int > e_meshOffsets
void GetElements()
Count the number of elements.
void SetOrdersFromKnotVectors()
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
void Generate3DBdrElementDofTable()
Array< int > e_spaceOffsets
void GenerateBdrElementDofTable()
const KnotVector * GetKnotVector(int i) const
void GetElementLocalToGlobal(Array< int > &lelem_elem)
Data type quadrilateral element.
Array< int > edge_to_knot
void GenerateActiveVertices()
void GetVertexLocalToGlobal(Array< int > &lvert_vert)
void Set2DSolutionVector(Vector &Nodes, int vdim)
void skip_comment_lines(std::istream &is, const char comment_char)
void DeleteAll()
Delete whole array.
void SwapDirections(int dir1, int dir2)
friend class NURBSPatchMap
KnotVector()
Create KnotVector.
static const int MaxOrder
Array< int > v_spaceOffsets
void UniformRefinement(Vector &newknots) const
void Generate2DBdrElementDofTable()
Data type hexahedron element.
void ConnectBoundaries3D(int bnd0, int bnd1)
ParNURBSExtension(const ParNURBSExtension &orig)
void SetIJK(const int *IJK) const
void Set3DSolutionVector(Vector &Nodes, int vdim)
void SetPatch(int p) const
void GetPatchKnotVectors(int p, Array< KnotVector * > &kv)
void GenerateActiveBdrElems()
int Append(const T &el)
Append element to array, resize if necessary.
Mesh * GetMesh() const
Returns the mesh.
void PrintSolution(const GridFunction &sol, std::ostream &out) const
void Get3DPatchNets(const Vector &Nodes, int vdim)
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void Get2DPatchNets(const Vector &Nodes, int vdim)
void GetBdrElementTopo(Array< Element * > &boundary) const
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
void SetKnotsFromPatches()
void GetElementTopo(Array< Element * > &elements) const
const Array< int > & GetOrders() const
Read-only access to the orders of all knot vectors.
Array< int > f_spaceOffsets
Array< bool > activeBdrElem
int GetVDim() const
Returns vector dimension.
void LoadSolution(std::istream &input, GridFunction &sol) const
FiniteElementSpace * FESpace()
void SetElement(int e) const
int GetOrder() const
If all orders are identical, return that number. Otherwise, return NURBSFECollection::VariableOrder.
void GetBdrElementFace(int i, int *, int *) const
Return the index and the orientation of the face of bdr element i. (3D)
void Swap(Array< T > &, Array< T > &)
void LoadFE(int i, const FiniteElement *FE) const
const NURBSExtension * GetNURBSext() const
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Array< int > v_meshOffsets
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
void SetBdrPatchVertexMap(int p, const KnotVector *kv[], int *okv)
void GetBdrPatchKnotVectors(int p, Array< KnotVector * > &kv)
Array< int > p_meshOffsets
KnotVector & operator=(const KnotVector &kv)
void SetPatchVertexMap(int p, const KnotVector *kv[])
Helper struct for defining a connectivity table, see Table::MakeFromList.
Table * GetElementDofTable()
void SetOrderFromOrders()
void CalcShape(Vector &shape, int i, double xi) const
NURBSExtension * NURBSext
Optional NURBS mesh extension.
void GetPatchNets(const Vector &Nodes, int vdim)
void GetElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of element i.
NURBSPatch * Revolve3D(NURBSPatch &patch, double n[], double ang, int times)
Array< int > p_spaceOffsets
void SetSolutionVector(Vector &Nodes, int vdim)
void Get3DElementTopo(Array< Element * > &elements) const
void SetBdrPatchDofMap(int p, const KnotVector *kv[], int *okv)
void GenerateElementDofTable()
void Difference(const KnotVector &kv, Vector &diff) const
virtual void SetOrder() const
Update the NURBSFiniteElement according to the currently set knot vectors.
void Print(std::ostream &out) const
void DeleteAll()
Delete all dynamically allocated memory, reseting all dimentions to zero.
void CalcDShape(Vector &grad, int i, double xi) const
void DegreeElevate(int rel_degree, int degree=16)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void Get2DElementTopo(Array< Element * > &elements) const
Data type line segment element.
Array< int > bel_to_patch
void SetPatchDofMap(int p, const KnotVector *kv[])
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
void ConvertToPatches(const Vector &Nodes)
void KnotInsert(Array< KnotVector * > &kv)
void Get2DBdrElementTopo(Array< Element * > &boundary) const
int SetLoopDirection(int dir)