13 #include "../fem/fem.hpp" 14 #include "../general/text.hpp" 18 #if defined(_MSC_VER) && (_MSC_VER < 1800) 20 #define copysign _copysign 32 input >> Order >> NumOfControlPoints;
33 knot.Load(input, NumOfControlPoints + Order + 1);
40 NumOfControlPoints = NCP;
41 knot.SetSize(NumOfControlPoints + Order + 1);
63 " Parent KnotVector order higher than child");
66 const int nOrder = Order +
t;
69 for (
int i = 0; i <= nOrder; i++)
71 (*newkv)[i] = knot(0);
73 for (
int i = nOrder + 1; i < newkv->
GetNCP(); i++)
75 (*newkv)[i] = knot(i -
t);
77 for (
int i = 0; i <= nOrder; i++)
79 (*newkv)[newkv->
GetNCP() + i] = knot(knot.Size()-1);
89 newknots.
SetSize(NumOfElements);
91 for (
int i = 0; i < knot.Size()-1; i++)
93 if (knot(i) != knot(i+1))
95 newknots(j) = 0.5*(knot(i) + knot(i+1));
104 for (
int i = Order; i < NumOfControlPoints; i++)
106 if (knot(i) != knot(i+1))
115 double apb = knot(0) + knot(knot.Size()-1);
117 int ns = (NumOfControlPoints - Order)/2;
118 for (
int i = 1; i <= ns; i++)
120 double tmp = apb - knot(Order + i);
121 knot(Order + i) = apb - knot(NumOfControlPoints - i);
122 knot(NumOfControlPoints - i) = tmp;
128 os << Order <<
' ' << NumOfControlPoints <<
' ';
129 knot.Print(os, knot.Size());
137 double x, dx = 1.0/double (samples - 1);
139 for (
int i = 0; i <GetNE() ; i++)
141 for (
int j = 0; j <samples; j++)
146 CalcShape ( shape, i, x);
147 for (
int d = 0; d < Order+1; d++) { os<<
"\t"<<shape[d]; }
149 CalcDShape ( shape, i, x);
150 for (
int d = 0; d < Order+1; d++) { os<<
"\t"<<shape[d]; }
152 CalcD2Shape ( shape, i, x);
153 for (
int d = 0; d < Order+1; d++) { os<<
"\t"<<shape[d]; }
163 MFEM_ASSERT(Order <= MaxOrder, "Order > MaxOrder!
"); 166 int ip = (i >= 0) ? (i + p) : (-1 - i + p); 167 double u = getKnotLocation((i >= 0) ? xi : 1. - xi, ip), saved, tmp; 168 double left[MaxOrder+1], right[MaxOrder+1]; 171 for (int j = 1; j <= p; ++j) 173 left[j] = u - knot(ip+1-j); 174 right[j] = knot(ip+j) - u; 176 for (int r = 0; r < j; ++r) 178 tmp = shape(r)/(right[r+1] + left[j-r]); 179 shape(r) = saved + right[r+1]*tmp; 180 saved = left[j-r]*tmp; 186 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller 187 // Algorithm A2.3 p. 72 188 void KnotVector::CalcDShape(Vector &grad, int i, double xi) const 190 int p = Order, rk, pk; 191 int ip = (i >= 0) ? (i + p) : (-1 - i + p); 192 double u = getKnotLocation((i >= 0) ? xi : 1. - xi, ip), temp, saved, d; 193 double ndu[MaxOrder+1][MaxOrder+1], left[MaxOrder+1], right[MaxOrder+1]; 203 for (int j = 1; j <= p; j++) 205 left[j] = u - knot(ip-j+1); 206 right[j] = knot(ip+j) - u; 208 for (int r = 0; r < j; r++) 210 ndu[j][r] = right[r+1] + left[j-r]; 211 temp = ndu[r][j-1]/ndu[j][r]; 212 ndu[r][j] = saved + right[r+1]*temp; 213 saved = left[j-r]*temp; 218 for (int r = 0; r <= p; ++r) 225 d = ndu[rk][pk]/ndu[p][rk]; 229 d -= ndu[r][pk]/ndu[p][r]; 236 grad *= p*(knot(ip+1) - knot(ip)); 240 grad *= p*(knot(ip) - knot(ip+1)); 244 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller 245 void KnotVector::CalcDnShape(Vector &gradn, int n, int i, double xi) const 247 int p = Order, rk, pk, j1, j2,r,j,k; 248 int ip = (i >= 0) ? (i + p) : (-1 - i + p); 249 double u = getKnotLocation((i >= 0) ? xi : 1. - xi, ip); 250 double temp, saved, d; 251 double a[2][MaxOrder+1],ndu[MaxOrder+1][MaxOrder+1], left[MaxOrder+1], 262 for (j = 1; j <= p; j++) 264 left[j] = u - knot(ip-j+1); 265 right[j] = knot(ip+j)- u; 268 for (r = 0; r < j; r++) 270 ndu[j][r] = right[r+1] + left[j-r]; 271 temp = ndu[r][j-1]/ndu[j][r]; 272 ndu[r][j] = saved + right[r+1]*temp; 273 saved = left[j-r]*temp; 278 for (r = 0; r <= p; r++) 283 for (k = 1; k <= n; k++) 290 a[s2][0] = a[s1][0]/ndu[pk+1][rk]; 291 d = a[s2][0]*ndu[rk][pk]; 312 for (j = j1; j <= j2; j++) 314 a[s2][j] = (a[s1][j] - a[s1][j-1])/ndu[pk+1][rk+j]; 315 d += a[s2][j]*ndu[rk+j][pk]; 320 a[s2][k] = - a[s1][k-1]/ndu[pk+1][r]; 321 d += a[s2][j]*ndu[rk+j][pk]; 332 u = (knot(ip+1) - knot(ip)); 336 u = (knot(ip) - knot(ip+1)); 340 for (k = 1; k <= n-1; k++) { temp *= (p-k)*u; } 342 for (j = 0; j <= p; j++) { gradn[j] *= temp; } 346 void KnotVector::FindMaxima(Array<int> &ks, 350 Vector shape(Order+1); 351 Vector maxima(GetNCP()); 352 double arg1, arg2, arg, max1, max2, max; 354 xi.SetSize(GetNCP()); 356 ks.SetSize(GetNCP()); 357 for (int j = 0; j <GetNCP(); j++) 360 for (int d = 0; d < Order+1; d++) 366 CalcShape(shape, i, arg1); 370 CalcShape(shape, i, arg2); 373 arg = (arg1 + arg2)/2; 374 CalcShape(shape, i, arg); 377 while ( ( max > max1 ) || (max > max2) ) 390 arg = (arg1 + arg2)/2; 391 CalcShape ( shape, i, arg); 400 u[j] = getKnotLocation(arg, i+Order); 407 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller 408 // Algorithm A9.1 p. 369 409 void KnotVector::FindInterpolant(Array<Vector*> &x) 411 int order = GetOrder(); 414 // Find interpolation points 415 Vector xi_args, u_args; 417 FindMaxima(i_args,xi_args, u_args); 419 // Assemble collocation matrix 420 Vector shape(order+1); 421 DenseMatrix A(ncp,ncp); 423 for (int i = 0; i < ncp; i++) 425 CalcShape ( shape, i_args[i], xi_args[i]); 426 for (int p = 0; p < order+1; p++) 428 A(i,i_args[i] + p) = shape[p]; 435 for (int i= 0; i < x.Size(); i++) 442 int KnotVector::findKnotSpan(double u) const 446 if (u == knot(NumOfControlPoints+Order)) 448 mid = NumOfControlPoints; 453 high = NumOfControlPoints + 1; 454 mid = (low + high)/2; 455 while ( (u < knot(mid-1)) || (u > knot(mid)) ) 465 mid = (low + high)/2; 471 void KnotVector::Difference(const KnotVector &kv, Vector &diff) const 473 if (Order != kv.GetOrder()) 476 " Can not compare knot vectors with different orders!
"); 479 int s = kv.Size() - Size(); 482 kv.Difference(*this, diff); 490 for (int j = 0; j < kv.Size(); j++) 492 if (abs(knot(i) - kv[j]) < 2 * std::numeric_limits<double>::epsilon()) 504 void NURBSPatch::init(int dim_) 511 ni = kv[0]->GetNCP(); 515 data = new double[ni*Dim]; 518 for (int i = 0; i < ni*Dim; i++) 524 else if (kv.Size() == 2) 526 ni = kv[0]->GetNCP(); 527 nj = kv[1]->GetNCP(); 530 data = new double[ni*nj*Dim]; 533 for (int i = 0; i < ni*nj*Dim; i++) 539 else if (kv.Size() == 3) 541 ni = kv[0]->GetNCP(); 542 nj = kv[1]->GetNCP(); 543 nk = kv[2]->GetNCP(); 545 data = new double[ni*nj*nk*Dim]; 548 for (int i = 0; i < ni*nj*nk*Dim; i++) 560 NURBSPatch::NURBSPatch(const NURBSPatch &orig) 561 : ni(orig.ni), nj(orig.nj), nk(orig.nk), Dim(orig.Dim), 562 data(NULL), kv(orig.kv.Size()), nd(orig.nd), ls(orig.ls), sd(orig.sd) 564 // Allocate and copy data: 565 const int data_size = Dim*ni*nj*((kv.Size() == 2) ? 1 : nk); 566 data = new double[data_size]; 567 std::memcpy(data, orig.data, data_size*sizeof(double)); 569 // Copy the knot vectors: 570 for (int i = 0; i < kv.Size(); i++) 572 kv[i] = new KnotVector(*orig.kv[i]); 576 NURBSPatch::NURBSPatch(std::istream &input) 578 int pdim, dim, size = 1; 581 input >> ws >> ident >> pdim; // knotvectors 583 for (int i = 0; i < pdim; i++) 585 kv[i] = new KnotVector(input); 586 size *= kv[i]->GetNCP(); 589 input >> ws >> ident >> dim; // dimension 592 input >> ws >> ident; // controlpoints (homogeneous coordinates) 593 if (ident == "controlpoints
" || ident == "controlpoints_homogeneous
") 595 for (int j = 0, i = 0; i < size; i++) 596 for (int d = 0; d <= dim; d++, j++) 601 else // "controlpoints_cartesian
" (Cartesian coordinates with weight) 603 for (int j = 0, i = 0; i < size; i++) 605 for (int d = 0; d <= dim; d++) 609 for (int d = 0; d < dim; d++) 611 data[j+d] *= data[j+dim]; 618 NURBSPatch::NURBSPatch(const KnotVector *kv0, const KnotVector *kv1, int dim_) 621 kv[0] = new KnotVector(*kv0); 622 kv[1] = new KnotVector(*kv1); 626 NURBSPatch::NURBSPatch(const KnotVector *kv0, const KnotVector *kv1, 627 const KnotVector *kv2, int dim_) 630 kv[0] = new KnotVector(*kv0); 631 kv[1] = new KnotVector(*kv1); 632 kv[2] = new KnotVector(*kv2); 636 NURBSPatch::NURBSPatch(Array<const KnotVector *> &kv_, int dim_) 638 kv.SetSize(kv_.Size()); 639 for (int i = 0; i < kv.Size(); i++) 641 kv[i] = new KnotVector(*kv_[i]); 646 NURBSPatch::NURBSPatch(NURBSPatch *parent, int dir, int Order, int NCP) 648 kv.SetSize(parent->kv.Size()); 649 for (int i = 0; i < kv.Size(); i++) 652 kv[i] = new KnotVector(*parent->kv[i]); 656 kv[i] = new KnotVector(Order, NCP); 661 void NURBSPatch::swap(NURBSPatch *np) 668 for (int i = 0; i < kv.Size(); i++) 670 if (kv[i]) { delete kv[i]; } 687 NURBSPatch::~NURBSPatch() 694 for (int i = 0; i < kv.Size(); i++) 696 if (kv[i]) { delete kv[i]; } 700 void NURBSPatch::Print(std::ostream &os) const 704 os << "knotvectors\n
" << kv.Size() << '\n'; 705 for (int i = 0; i < kv.Size(); i++) 708 size *= kv[i]->GetNCP(); 711 os << "\ndimension\n
" << Dim - 1 712 << "\n\ncontrolpoints\n
"; 713 for (int j = 0, i = 0; i < size; i++) 716 for (int d = 1; d < Dim; d++) 718 os << ' ' << data[j++]; 724 int NURBSPatch::SetLoopDirection(int dir) 738 " Direction error in 1D patch, dir =
" << dir << '\n'; 761 " Direction error in 2D patch, dir =
" << dir << '\n'; 791 " Direction error in 3D patch, dir =
" << dir << '\n'; 799 void NURBSPatch::UniformRefinement() 802 for (int dir = 0; dir < kv.Size(); dir++) 804 kv[dir]->UniformRefinement(newknots); 805 KnotInsert(dir, newknots); 809 void NURBSPatch::KnotInsert(Array<KnotVector *> &newkv) 811 for (int dir = 0; dir < kv.Size(); dir++) 813 KnotInsert(dir, *newkv[dir]); 817 void NURBSPatch::KnotInsert(int dir, const KnotVector &newkv) 819 if (dir >= kv.Size() || dir < 0) 824 int t = newkv.GetOrder() - kv[dir]->GetOrder(); 828 DegreeElevate(dir, t); 836 GetKV(dir)->Difference(newkv, diff); 839 KnotInsert(dir, diff); 843 void NURBSPatch::KnotInsert(Array<Vector *> &newkv) 845 for (int dir = 0; dir < kv.Size(); dir++) 847 KnotInsert(dir, *newkv[dir]); 851 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller 852 void NURBSPatch::KnotInsert(int dir, const Vector &knot) 854 if (knot.Size() == 0 ) { return; } 856 if (dir >= kv.Size() || dir < 0) 861 NURBSPatch &oldp = *this; 862 KnotVector &oldkv = *kv[dir]; 864 NURBSPatch *newpatch = new NURBSPatch(this, dir, oldkv.GetOrder(), 865 oldkv.GetNCP() + knot.Size()); 866 NURBSPatch &newp = *newpatch; 867 KnotVector &newkv = *newp.GetKV(dir); 869 int size = oldp.SetLoopDirection(dir); 870 if (size != newp.SetLoopDirection(dir)) 875 int rr = knot.Size() - 1; 876 int a = oldkv.findKnotSpan(knot(0)) - 1; 877 int b = oldkv.findKnotSpan(knot(rr)) - 1; 878 int pl = oldkv.GetOrder(); 879 int ml = oldkv.GetNCP(); 881 for (int j = 0; j <= a; j++) 885 for (int j = b+pl; j <= ml+pl; j++) 887 newkv[j+rr+1] = oldkv[j]; 889 for (int k = 0; k <= (a-pl); k++) 891 for (int ll = 0; ll < size; ll++) 893 newp.slice(k,ll) = oldp.slice(k,ll); 896 for (int k = (b-1); k < ml; k++) 898 for (int ll = 0; ll < size; ll++) 900 newp.slice(k+rr+1,ll) = oldp.slice(k,ll); 907 for (int j = rr; j >= 0; j--) 909 while ( (knot(j) <= oldkv[i]) && (i > a) ) 912 for (int ll = 0; ll < size; ll++) 914 newp.slice(k-pl-1,ll) = oldp.slice(i-pl-1,ll); 921 for (int ll = 0; ll < size; ll++) 923 newp.slice(k-pl-1,ll) = newp.slice(k-pl,ll); 926 for (int l = 1; l <= pl; l++) 929 double alfa = newkv[k+l] - knot(j); 930 if (fabs(alfa) == 0.0) 932 for (int ll = 0; ll < size; ll++) 934 newp.slice(ind-1,ll) = newp.slice(ind,ll); 939 alfa = alfa/(newkv[k+l] - oldkv[i-pl+l]); 940 for (int ll = 0; ll < size; ll++) 942 newp.slice(ind-1,ll) = alfa*newp.slice(ind-1,ll) + (1.0-alfa)*newp.slice(ind, 957 void NURBSPatch::DegreeElevate(int t) 959 for (int dir = 0; dir < kv.Size(); dir++) 961 DegreeElevate(dir, t); 965 // Routine from "The NURBS book
" - 2nd ed - Piegl and Tiller 966 void NURBSPatch::DegreeElevate(int dir, int t) 968 if (dir >= kv.Size() || dir < 0) 973 int i, j, k, kj, mpi, mul, mh, kind, cind, first, last; 974 int r, a, b, oldr, save, s, tr, lbz, rbz, l; 975 double inv, ua, ub, numer, alf, den, bet, gam; 977 NURBSPatch &oldp = *this; 978 KnotVector &oldkv = *kv[dir]; 981 NURBSPatch *newpatch = new NURBSPatch(this, dir, oldkv.GetOrder() + t, 982 oldkv.GetNCP() + oldkv.GetNE()*t); 983 NURBSPatch &newp = *newpatch; 984 KnotVector &newkv = *newp.GetKV(dir); 986 int size = oldp.SetLoopDirection(dir); 987 if (size != newp.SetLoopDirection(dir)) 992 int p = oldkv.GetOrder(); 993 int n = oldkv.GetNCP()-1; 995 DenseMatrix bezalfs (p+t+1, p+1); 996 DenseMatrix bpts (p+1, size); 997 DenseMatrix ebpts (p+t+1, size); 998 DenseMatrix nextbpts(p-1, size); 1006 Array2D<int> binom(ph+1, ph+1); 1007 for (i = 0; i <= ph; i++) 1009 binom(i,0) = binom(i,i) = 1; 1010 for (j = 1; j < i; j++) 1012 binom(i,j) = binom(i-1,j) + binom(i-1,j-1); 1017 bezalfs(ph,p) = 1.0; 1019 for (i = 1; i <= ph2; i++) 1021 inv = 1.0/binom(ph,i); 1023 for (j = max(0,i-t); j <= mpi; j++) 1025 bezalfs(i,j) = inv*binom(p,j)*binom(t,i-j); 1030 for (i = ph2+1; i < ph; i++) 1033 for (j = max(0,i-t); j <= mpi; j++) 1035 bezalfs(i,j) = bezalfs(ph-i,p-j); 1046 for (l = 0; l < size; l++) 1048 newp.slice(0,l) = oldp.slice(0,l); 1050 for (i = 0; i <= ph; i++) 1055 for (i = 0; i <= p; i++) 1057 for (l = 0; l < size; l++) 1059 bpts(i,l) = oldp.slice(i,l); 1066 while (b < m && oldkv[b] == oldkv[b+1]) { b++; } 1074 if (oldr > 0) { lbz = (oldr+2)/2; } 1077 if (r > 0) { rbz = ph-(r+1)/2; } 1083 for (k = p ; k > mul; k--) 1085 alphas[k-mul-1] = numer/(oldkv[a+k]-ua); 1088 for (j = 1; j <= r; j++) 1092 for (k = p; k >= s; k--) 1094 for (l = 0; l < size; l++) 1095 bpts(k,l) = (alphas[k-s]*bpts(k,l) + 1096 (1.0-alphas[k-s])*bpts(k-1,l)); 1098 for (l = 0; l < size; l++) 1100 nextbpts(save,l) = bpts(p,l); 1105 for (i = lbz; i <= ph; i++) 1107 for (l = 0; l < size; l++) 1112 for (j = max(0,i-t); j <= mpi; j++) 1114 for (l = 0; l < size; l++) 1116 ebpts(i,l) += bezalfs(i,j)*bpts(j,l); 1126 bet = (ub-newkv[kind-1])/den; 1128 for (tr = 1; tr < oldr; tr++) 1137 alf = (ub-newkv[i])/(ua-newkv[i]); 1138 for (l = 0; l < size; l++) 1140 newp.slice(i,l) = alf*newp.slice(i,l)-(1.0-alf)*newp.slice(i-1,l); 1145 if ((j-tr) <= (kind-ph+oldr)) 1147 gam = (ub-newkv[j-tr])/den; 1148 for (l = 0; l < size; l++) 1150 ebpts(kj,l) = gam*ebpts(kj,l) + (1.0-gam)*ebpts(kj+1,l); 1155 for (l = 0; l < size; l++) 1157 ebpts(kj,l) = bet*ebpts(kj,l) + (1.0-bet)*ebpts(kj+1,l); 1172 for (i = 0; i < (ph-oldr); i++) 1178 for (j = lbz; j <= rbz; j++) 1180 for (l = 0; l < size; l++) 1182 newp.slice(cind,l) = ebpts(j,l); 1189 for (j = 0; j <r; j++) 1190 for (l = 0; l < size; l++) 1192 bpts(j,l) = nextbpts(j,l); 1195 for (j = r; j <= p; j++) 1196 for (l = 0; l < size; l++) 1198 bpts(j,l) = oldp.slice(b-p+j,l); 1207 for (i = 0; i <= ph; i++) 1213 newkv.GetElements(); 1218 void NURBSPatch::FlipDirection(int dir) 1220 int size = SetLoopDirection(dir); 1222 for (int id = 0; id < nd/2; id++) 1223 for (int i = 0; i < size; i++) 1225 Swap<double>((*this).slice(id,i), (*this).slice(nd-1-id,i)); 1230 void NURBSPatch::SwapDirections(int dir1, int dir2) 1232 if (abs(dir1-dir2) == 2) 1235 " directions 0 and 2 are not supported!
"); 1238 Array<const KnotVector *> nkv(kv); 1240 Swap<const KnotVector *>(nkv[dir1], nkv[dir2]); 1241 NURBSPatch *newpatch = new NURBSPatch(nkv, Dim); 1243 int size = SetLoopDirection(dir1); 1244 newpatch->SetLoopDirection(dir2); 1246 for (int id = 0; id < nd; id++) 1247 for (int i = 0; i < size; i++) 1249 (*newpatch).slice(id,i) = (*this).slice(id,i); 1255 void NURBSPatch::Rotate(double angle, double n[]) 1272 void NURBSPatch::Get2DRotationMatrix(double angle, DenseMatrix &T) 1274 double s = sin(angle); 1275 double c = cos(angle); 1284 void NURBSPatch::Rotate2D(double angle) 1288 mfem_error("NURBSPatch::Rotate2D : not
a NURBSPatch in 2D!
"); 1292 Vector x(2), y(NULL, 2); 1294 Get2DRotationMatrix(angle, T); 1297 for (int i = 0; i < kv.Size(); i++) 1299 size *= kv[i]->GetNCP(); 1302 for (int i = 0; i < size; i++) 1304 y.SetData(data + i*Dim); 1310 void NURBSPatch::Get3DRotationMatrix(double n[], double angle, double r, 1314 double l2 = n[0]*n[0] + n[1]*n[1] + n[2]*n[2]; 1315 double l = sqrt(l2); 1317 if (fabs(angle) == M_PI_2) 1319 s = r*copysign(1., angle); 1323 else if (fabs(angle) == M_PI) 1338 T(0,0) = (n[0]*n[0] + (n[1]*n[1] + n[2]*n[2])*c)/l2; 1339 T(0,1) = -(n[0]*n[1]*c1)/l2 - (n[2]*s)/l; 1340 T(0,2) = -(n[0]*n[2]*c1)/l2 + (n[1]*s)/l; 1341 T(1,0) = -(n[0]*n[1]*c1)/l2 + (n[2]*s)/l; 1342 T(1,1) = (n[1]*n[1] + (n[0]*n[0] + n[2]*n[2])*c)/l2; 1343 T(1,2) = -(n[1]*n[2]*c1)/l2 - (n[0]*s)/l; 1344 T(2,0) = -(n[0]*n[2]*c1)/l2 - (n[1]*s)/l; 1345 T(2,1) = -(n[1]*n[2]*c1)/l2 + (n[0]*s)/l; 1346 T(2,2) = (n[2]*n[2] + (n[0]*n[0] + n[1]*n[1])*c)/l2; 1349 void NURBSPatch::Rotate3D(double n[], double angle) 1357 Vector x(3), y(NULL, 3); 1359 Get3DRotationMatrix(n, angle, 1., T); 1362 for (int i = 0; i < kv.Size(); i++) 1364 size *= kv[i]->GetNCP(); 1367 for (int i = 0; i < size; i++) 1369 y.SetData(data + i*Dim); 1375 int NURBSPatch::MakeUniformDegree(int degree) 1381 for (int dir = 0; dir < kv.Size(); dir++) 1383 maxd = std::max(maxd, kv[dir]->GetOrder()); 1387 for (int dir = 0; dir < kv.Size(); dir++) 1389 if (maxd > kv[dir]->GetOrder()) 1391 DegreeElevate(dir, maxd - kv[dir]->GetOrder()); 1398 NURBSPatch *Interpolate(NURBSPatch &p1, NURBSPatch &p2) 1400 if (p1.kv.Size() != p2.kv.Size() || p1.Dim != p2.Dim) 1405 int size = 1, dim = p1.Dim; 1406 Array<const KnotVector *> kv(p1.kv.Size() + 1); 1408 for (int i = 0; i < p1.kv.Size(); i++) 1410 if (p1.kv[i]->GetOrder() < p2.kv[i]->GetOrder()) 1412 p1.KnotInsert(i, *p2.kv[i]); 1413 p2.KnotInsert(i, *p1.kv[i]); 1417 p2.KnotInsert(i, *p1.kv[i]); 1418 p1.KnotInsert(i, *p2.kv[i]); 1421 size *= kv[i]->GetNCP(); 1424 KnotVector &nkv = *(new KnotVector(1, 2)); 1425 nkv[0] = nkv[1] = 0.0; 1426 nkv[2] = nkv[3] = 1.0; 1430 NURBSPatch *patch = new NURBSPatch(kv, dim); 1433 for (int i = 0; i < size; i++) 1435 for (int d = 0; d < dim; d++) 1437 patch->data[i*dim+d] = p1.data[i*dim+d]; 1438 patch->data[(i+size)*dim+d] = p2.data[i*dim+d]; 1445 NURBSPatch *Revolve3D(NURBSPatch &patch, double n[], double ang, int times) 1453 Array<const KnotVector *> nkv(patch.kv.Size() + 1); 1455 for (int i = 0; i < patch.kv.Size(); i++) 1457 nkv[i] = patch.kv[i]; 1458 size *= nkv[i]->GetNCP(); 1461 KnotVector &lkv = *(new KnotVector(2, ns)); 1463 lkv[0] = lkv[1] = lkv[2] = 0.0; 1464 for (int i = 1; i < times; i++) 1466 lkv[2*i+1] = lkv[2*i+2] = i; 1468 lkv[ns] = lkv[ns+1] = lkv[ns+2] = times; 1470 NURBSPatch *newpatch = new NURBSPatch(nkv, 4); 1473 DenseMatrix T(3), T2(3); 1474 Vector u(NULL, 3), v(NULL, 3); 1476 NURBSPatch::Get3DRotationMatrix(n, ang, 1., T); 1477 double c = cos(ang/2); 1478 NURBSPatch::Get3DRotationMatrix(n, ang/2, 1./c, T2); 1481 double *op = patch.data, *np; 1482 for (int i = 0; i < size; i++) 1484 np = newpatch->data + 4*i; 1485 for (int j = 0; j < 4; j++) 1489 for (int j = 0; j < times; j++) 1492 v.SetData(np += 4*size); 1495 v.SetData(np += 4*size); 1506 NURBSExtension::NURBSExtension(const NURBSExtension &orig) 1507 : mOrder(orig.mOrder), mOrders(orig.mOrders), 1508 NumOfKnotVectors(orig.NumOfKnotVectors), 1509 NumOfVertices(orig.NumOfVertices), 1510 NumOfElements(orig.NumOfElements), 1511 NumOfBdrElements(orig.NumOfBdrElements), 1512 NumOfDofs(orig.NumOfDofs), 1513 NumOfActiveVertices(orig.NumOfActiveVertices), 1514 NumOfActiveElems(orig.NumOfActiveElems), 1515 NumOfActiveBdrElems(orig.NumOfActiveBdrElems), 1516 NumOfActiveDofs(orig.NumOfActiveDofs), 1517 activeVert(orig.activeVert), 1518 activeElem(orig.activeElem), 1519 activeBdrElem(orig.activeBdrElem), 1520 activeDof(orig.activeDof), 1521 patchTopo(new Mesh(*orig.patchTopo)), 1523 edge_to_knot(orig.edge_to_knot), 1524 knotVectors(orig.knotVectors.Size()), // knotVectors are copied in the body 1525 knotVectorsCompr(orig.knotVectorsCompr.Size()), 1526 weights(orig.weights), 1527 d_to_d(orig.d_to_d), 1528 master(orig.master), 1530 v_meshOffsets(orig.v_meshOffsets), 1531 e_meshOffsets(orig.e_meshOffsets), 1532 f_meshOffsets(orig.f_meshOffsets), 1533 p_meshOffsets(orig.p_meshOffsets), 1534 v_spaceOffsets(orig.v_spaceOffsets), 1535 e_spaceOffsets(orig.e_spaceOffsets), 1536 f_spaceOffsets(orig.f_spaceOffsets), 1537 p_spaceOffsets(orig.p_spaceOffsets), 1538 el_dof(orig.el_dof ? new Table(*orig.el_dof) : NULL), 1539 bel_dof(orig.bel_dof ? new Table(*orig.bel_dof) : NULL), 1540 el_to_patch(orig.el_to_patch), 1541 bel_to_patch(orig.bel_to_patch), 1542 el_to_IJK(orig.el_to_IJK), 1543 bel_to_IJK(orig.bel_to_IJK), 1544 patches(orig.patches.Size()) // patches are copied in the body 1546 // Copy the knot vectors: 1547 for (int i = 0; i < knotVectors.Size(); i++) 1549 knotVectors[i] = new KnotVector(*orig.knotVectors[i]); 1551 CreateComprehensiveKV(); 1553 // Copy the patches: 1554 for (int p = 0; p < patches.Size(); p++) 1556 patches[p] = new NURBSPatch(*orig.patches[p]); 1560 NURBSExtension::NURBSExtension(std::istream &input) 1563 patchTopo = new Mesh; 1564 patchTopo->LoadPatchTopo(input, edge_to_knot); 1568 // CheckBdrPatches(); 1570 skip_comment_lines(input, '#'); 1572 // Read knotvectors or patches 1574 input >> ws >> ident; // 'knotvectors' or 'patches' 1575 if (ident == "knotvectors
") 1577 input >> NumOfKnotVectors; 1578 knotVectors.SetSize(NumOfKnotVectors); 1579 for (int i = 0; i < NumOfKnotVectors; i++) 1581 knotVectors[i] = new KnotVector(input); 1584 else if (ident == "patches
") 1586 patches.SetSize(GetNP()); 1587 for (int p = 0; p < patches.Size(); p++) 1589 skip_comment_lines(input, '#'); 1590 patches[p] = new NURBSPatch(input); 1593 NumOfKnotVectors = 0; 1594 for (int i = 0; i < patchTopo->GetNEdges(); i++) 1595 if (NumOfKnotVectors < KnotInd(i)) 1597 NumOfKnotVectors = KnotInd(i); 1600 knotVectors.SetSize(NumOfKnotVectors); 1603 Array<int> edges, oedge; 1604 for (int p = 0; p < patches.Size(); p++) 1606 if (Dimension() == 1) 1608 if (knotVectors[KnotInd(p)] == NULL) 1610 knotVectors[KnotInd(p)] = 1611 new KnotVector(*patches[p]->GetKV(0)); 1614 if (Dimension() == 2) 1616 patchTopo->GetElementEdges(p, edges, oedge); 1617 if (knotVectors[KnotInd(edges[0])] == NULL) 1619 knotVectors[KnotInd(edges[0])] = 1620 new KnotVector(*patches[p]->GetKV(0)); 1622 if (knotVectors[KnotInd(edges[1])] == NULL) 1624 knotVectors[KnotInd(edges[1])] = 1625 new KnotVector(*patches[p]->GetKV(1)); 1628 else if (Dimension() == 3) 1630 patchTopo->GetElementEdges(p, edges, oedge); 1631 if (knotVectors[KnotInd(edges[0])] == NULL) 1633 knotVectors[KnotInd(edges[0])] = 1634 new KnotVector(*patches[p]->GetKV(0)); 1636 if (knotVectors[KnotInd(edges[3])] == NULL) 1638 knotVectors[KnotInd(edges[3])] = 1639 new KnotVector(*patches[p]->GetKV(1)); 1641 if (knotVectors[KnotInd(edges[8])] == NULL) 1643 knotVectors[KnotInd(edges[8])] = 1644 new KnotVector(*patches[p]->GetKV(2)); 1651 MFEM_ABORT("invalid section:
" << ident); 1654 CreateComprehensiveKV(); 1656 SetOrdersFromKnotVectors(); 1661 // NumOfVertices, NumOfElements, NumOfBdrElements, NumOfDofs 1663 skip_comment_lines(input, '#'); 1665 // Check for a list of mesh elements 1666 if (patches.Size() == 0) 1668 input >> ws >> ident; 1670 if (patches.Size() == 0 && ident == "mesh_elements
") 1672 input >> NumOfActiveElems; 1673 activeElem.SetSize(GetGNE()); 1676 for (int i = 0; i < NumOfActiveElems; i++) 1679 activeElem[glob_elem] = true; 1682 skip_comment_lines(input, '#'); 1683 input >> ws >> ident; 1687 NumOfActiveElems = NumOfElements; 1688 activeElem.SetSize(NumOfElements); 1692 GenerateActiveVertices(); 1694 GenerateElementDofTable(); 1695 GenerateActiveBdrElems(); 1696 GenerateBdrElementDofTable(); 1699 if (ident == "periodic
") 1704 skip_comment_lines(input, '#'); 1705 input >> ws >> ident; 1708 if (patches.Size() == 0) 1711 if (ident == "weights
") 1713 weights.Load(input, GetNDof()); 1715 else // e.g. ident = "unitweights
" or "autoweights
" 1717 weights.SetSize(GetNDof()); 1723 ConnectBoundaries(); 1726 NURBSExtension::NURBSExtension(NURBSExtension *parent, int newOrder) 1728 patchTopo = parent->patchTopo; 1731 parent->edge_to_knot.Copy(edge_to_knot); 1733 NumOfKnotVectors = parent->GetNKV(); 1734 knotVectors.SetSize(NumOfKnotVectors); 1735 knotVectorsCompr.SetSize(parent->GetNP()*parent->Dimension()); 1736 const Array<int> &pOrders = parent->GetOrders(); 1737 for (int i = 0; i < NumOfKnotVectors; i++) 1739 if (newOrder > pOrders[i]) 1742 parent->GetKnotVector(i)->DegreeElevate(newOrder - pOrders[i]); 1746 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i)); 1749 CreateComprehensiveKV(); 1751 // copy some data from parent 1752 NumOfElements = parent->NumOfElements; 1753 NumOfBdrElements = parent->NumOfBdrElements; 1755 SetOrdersFromKnotVectors(); 1757 GenerateOffsets(); // dof offsets will be different from parent 1759 NumOfActiveVertices = parent->NumOfActiveVertices; 1760 NumOfActiveElems = parent->NumOfActiveElems; 1761 NumOfActiveBdrElems = parent->NumOfActiveBdrElems; 1762 parent->activeVert.Copy(activeVert); 1764 parent->activeElem.Copy(activeElem); 1765 parent->activeBdrElem.Copy(activeBdrElem); 1767 GenerateElementDofTable(); 1768 GenerateBdrElementDofTable(); 1770 weights.SetSize(GetNDof()); 1774 parent->master.Copy(master); 1775 parent->slave.Copy(slave); 1776 ConnectBoundaries(); 1779 NURBSExtension::NURBSExtension(NURBSExtension *parent, 1780 const Array<int> &newOrders) 1782 newOrders.Copy(mOrders); 1783 SetOrderFromOrders(); 1785 patchTopo = parent->patchTopo; 1788 parent->edge_to_knot.Copy(edge_to_knot); 1790 NumOfKnotVectors = parent->GetNKV(); 1791 MFEM_VERIFY(mOrders.Size() == NumOfKnotVectors, "invalid newOrders array
"); 1792 knotVectors.SetSize(NumOfKnotVectors); 1793 const Array<int> &pOrders = parent->GetOrders(); 1795 for (int i = 0; i < NumOfKnotVectors; i++) 1797 if (mOrders[i] > pOrders[i]) 1800 parent->GetKnotVector(i)->DegreeElevate(mOrders[i] - pOrders[i]); 1804 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i)); 1807 CreateComprehensiveKV(); 1809 // copy some data from parent 1810 NumOfElements = parent->NumOfElements; 1811 NumOfBdrElements = parent->NumOfBdrElements; 1813 GenerateOffsets(); // dof offsets will be different from parent 1815 NumOfActiveVertices = parent->NumOfActiveVertices; 1816 NumOfActiveElems = parent->NumOfActiveElems; 1817 NumOfActiveBdrElems = parent->NumOfActiveBdrElems; 1818 parent->activeVert.Copy(activeVert); 1820 parent->activeElem.Copy(activeElem); 1821 parent->activeBdrElem.Copy(activeBdrElem); 1823 GenerateElementDofTable(); 1824 GenerateBdrElementDofTable(); 1826 weights.SetSize(GetNDof()); 1829 parent->master.Copy(master); 1830 parent->slave.Copy(slave); 1831 ConnectBoundaries(); 1834 NURBSExtension::NURBSExtension(Mesh *mesh_array[], int num_pieces) 1836 NURBSExtension *parent = mesh_array[0]->NURBSext; 1838 if (!parent->own_topo) 1841 " parent does not own the patch topology!
"); 1843 patchTopo = parent->patchTopo; 1845 parent->own_topo = 0; 1847 parent->edge_to_knot.Copy(edge_to_knot); 1849 parent->GetOrders().Copy(mOrders); 1850 mOrder = parent->GetOrder(); 1852 NumOfKnotVectors = parent->GetNKV(); 1853 knotVectors.SetSize(NumOfKnotVectors); 1854 for (int i = 0; i < NumOfKnotVectors; i++) 1856 knotVectors[i] = new KnotVector(*parent->GetKnotVector(i)); 1858 CreateComprehensiveKV(); 1864 // assuming the meshes define a partitioning of all the elements 1865 NumOfActiveElems = NumOfElements; 1866 activeElem.SetSize(NumOfElements); 1869 GenerateActiveVertices(); 1871 GenerateElementDofTable(); 1872 GenerateActiveBdrElems(); 1873 GenerateBdrElementDofTable(); 1875 weights.SetSize(GetNDof()); 1876 MergeWeights(mesh_array, num_pieces); 1879 NURBSExtension::~NURBSExtension() 1881 if (patches.Size() == 0) 1887 for (int i = 0; i < knotVectors.Size(); i++) 1889 delete knotVectors[i]; 1892 for (int i = 0; i < knotVectorsCompr.Size(); i++) 1894 delete knotVectorsCompr[i]; 1897 for (int i = 0; i < patches.Size(); i++) 1908 void NURBSExtension::Print(std::ostream &os) const 1910 patchTopo->PrintTopo(os, edge_to_knot); 1911 if (patches.Size() == 0) 1913 os << "\nknotvectors\n
" << NumOfKnotVectors << '\n'; 1914 for (int i = 0; i < NumOfKnotVectors; i++) 1916 knotVectors[i]->Print(os); 1919 if (NumOfActiveElems < NumOfElements) 1921 os << "\nmesh_elements\n
" << NumOfActiveElems << '\n'; 1922 for (int i = 0; i < NumOfElements; i++) 1929 os << "\nweights\n
"; 1930 weights.Print(os, 1); 1934 os << "\npatches\n
"; 1935 for (int p = 0; p < patches.Size(); p++) 1937 os << "\n# patch
" << p << "\n\n
"; 1938 patches[p]->Print(os); 1943 void NURBSExtension::PrintCharacteristics(std::ostream &os) const 1946 "NURBS
Mesh entity sizes:\n
" 1947 "Dimension =
" << Dimension() << "\n
" 1949 Array<int> unique_orders(mOrders); 1950 unique_orders.Sort(); 1951 unique_orders.Unique(); 1952 unique_orders.Print(os, unique_orders.Size()); 1954 "NumOfKnotVectors =
" << GetNKV() << "\n
" 1955 "NumOfPatches =
" << GetNP() << "\n
" 1956 "NumOfBdrPatches =
" << GetNBP() << "\n
" 1957 "NumOfVertices =
" << GetGNV() << "\n
" 1958 "NumOfElements =
" << GetGNE() << "\n
" 1959 "NumOfBdrElements =
" << GetGNBE() << "\n
" 1960 "NumOfDofs =
" << GetNTotalDof() << "\n
" 1961 "NumOfActiveVertices =
" << GetNV() << "\n
" 1962 "NumOfActiveElems =
" << GetNE() << "\n
" 1963 "NumOfActiveBdrElems =
" << GetNBE() << "\n
" 1964 "NumOfActiveDofs =
" << GetNDof() << '\n'; 1965 for (int i = 0; i < NumOfKnotVectors; i++) 1967 os << ' ' << i + 1 << ")
"; 1968 knotVectors[i]->Print(os); 1973 void NURBSExtension::PrintFunctions(const char *basename, int samples) const 1976 for (int i = 0; i < NumOfKnotVectors; i++) 1978 std::ostringstream filename; 1979 filename << basename<<"_
"<<i<<".dat
"; 1980 os.open(filename.str().c_str()); 1981 knotVectors[i]->PrintFunctions(os,samples); 1986 void NURBSExtension::InitDofMap() 1993 void NURBSExtension::ConnectBoundaries(Array<int> &bnds0, Array<int> &bnds1) 1997 ConnectBoundaries(); 2000 void NURBSExtension::ConnectBoundaries() 2002 if (master.Size() != slave.Size()) 2006 if (master.Size() == 0 ) {
return; }
2009 d_to_d.SetSize(NumOfDofs);
2010 for (
int i = 0; i < NumOfDofs; i++) { d_to_d[i] = i; }
2013 for (
int i = 0; i < master.Size(); i++)
2015 int bnd0 = -1, bnd1 = -1;
2016 for (
int b = 0;
b < GetNBP();
b++)
2018 if (master[i] == patchTopo->GetBdrAttribute(
b)) { bnd0 =
b; }
2019 if (slave[i]== patchTopo->GetBdrAttribute(
b)) { bnd1 =
b; }
2021 MFEM_VERIFY(bnd0 != -1,
"Bdr 0 not found");
2022 MFEM_VERIFY(bnd1 != -1,
"Bdr 1 not found");
2024 if (Dimension() == 1)
2026 ConnectBoundaries1D(bnd0, bnd1);
2028 else if (Dimension() == 2)
2030 ConnectBoundaries2D(bnd0, bnd1);
2034 ConnectBoundaries3D(bnd0, bnd1);
2039 Array<int> tmp(d_to_d.Size()+1);
2042 for (
int i = 0; i < d_to_d.Size(); i++)
2048 for (
int i = 0; i < tmp.Size(); i++)
2050 if (tmp[i] == 1) { tmp[i] = cnt++; }
2054 for (
int i = 0; i < d_to_d.Size(); i++)
2056 d_to_d[i] = tmp[d_to_d[i]];
2060 if (el_dof) {
delete el_dof; }
2061 if (bel_dof) {
delete bel_dof; }
2062 GenerateElementDofTable();
2063 GenerateBdrElementDofTable();
2071 int okv0[1],okv1[1];
2077 d_to_d[p2g0(0)] = d_to_d[p2g1(0)];
2085 int okv0[1],okv1[1];
2092 int nks0 = kv0[0]->
GetNKS();
2095 bool compatible =
true;
2096 if (p2g0.
nx() != p2g1.
nx()) { compatible =
false; }
2097 if (kv0[0]->GetNKS() != kv1[0]->
GetNKS()) { compatible =
false; }
2098 if (kv0[0]->GetOrder() != kv1[0]->
GetOrder()) { compatible =
false; }
2105 mfem_error(
"NURBS boundaries not compatible");
2109 for (
int i = 0; i < nks0; i++)
2111 if (kv0[0]->isElement(i))
2113 if (!kv1[0]->isElement(i)) {
mfem_error(
"isElement does not match"); }
2114 for (
int ii = 0; ii <= kv0[0]->
GetOrder(); ii++)
2116 int ii0 = (okv0[0] >= 0) ? (i+ii) : (nx-i-ii);
2117 int ii1 = (okv1[0] >= 0) ? (i+ii) : (nx-i-ii);
2119 d_to_d[p2g0(ii0)] = d_to_d[p2g1(ii1)];
2131 int okv0[2],okv1[2];
2140 int nks0 = kv0[0]->
GetNKS();
2141 int nks1 = kv0[1]->
GetNKS();
2144 bool compatible =
true;
2145 if (p2g0.
nx() != p2g1.
nx()) { compatible =
false; }
2146 if (p2g0.
ny() != p2g1.
ny()) { compatible =
false; }
2148 if (kv0[0]->GetNKS() != kv1[0]->
GetNKS()) { compatible =
false; }
2149 if (kv0[1]->GetNKS() != kv1[1]->
GetNKS()) { compatible =
false; }
2151 if (kv0[0]->GetOrder() != kv1[0]->
GetOrder()) { compatible =
false; }
2152 if (kv0[1]->GetOrder() != kv1[1]->
GetOrder()) { compatible =
false; }
2164 mfem_error(
"NURBS boundaries not compatible");
2168 for (
int j = 0; j < nks1; j++)
2170 if (kv0[1]->isElement(j))
2172 if (!kv1[1]->isElement(j)) {
mfem_error(
"isElement does not match #1"); }
2173 for (
int i = 0; i < nks0; i++)
2175 if (kv0[0]->isElement(i))
2177 if (!kv1[0]->isElement(i)) {
mfem_error(
"isElement does not match #0"); }
2178 for (
int jj = 0; jj <= kv0[1]->
GetOrder(); jj++)
2180 int jj0 = (okv0[1] >= 0) ? (j+jj) : (ny-j-jj);
2181 int jj1 = (okv1[1] >= 0) ? (j+jj) : (ny-j-jj);
2183 for (
int ii = 0; ii <= kv0[0]->
GetOrder(); ii++)
2185 int ii0 = (okv0[0] >= 0) ? (i+ii) : (nx-i-ii);
2186 int ii1 = (okv1[0] >= 0) ? (i+ii) : (nx-i-ii);
2188 d_to_d[p2g0(ii0,jj0)] = d_to_d[p2g1(ii1,jj1)];
2199 int vert[8], nv, g_el, nx, ny, nz,
dim = Dimension();
2205 activeVert.SetSize(GetGNV());
2207 for (
int p = 0;
p < GetNP();
p++)
2212 ny = (
dim >= 2) ? p2g.
ny() : 1;
2213 nz = (
dim == 3) ? p2g.
nz() : 1;
2215 for (
int k = 0; k < nz; k++)
2217 for (
int j = 0; j < ny; j++)
2219 for (
int i = 0; i < nx; i++)
2221 if (activeElem[g_el])
2231 vert[0] = p2g(i, j );
2232 vert[1] = p2g(i+1,j );
2233 vert[2] = p2g(i+1,j+1);
2234 vert[3] = p2g(i, j+1);
2239 vert[0] = p2g(i, j, k);
2240 vert[1] = p2g(i+1,j, k);
2241 vert[2] = p2g(i+1,j+1,k);
2242 vert[3] = p2g(i, j+1,k);
2244 vert[4] = p2g(i, j, k+1);
2245 vert[5] = p2g(i+1,j, k+1);
2246 vert[6] = p2g(i+1,j+1,k+1);
2247 vert[7] = p2g(i, j+1,k+1);
2251 for (
int v = 0; v < nv; v++)
2253 activeVert[vert[v]] = 1;
2262 NumOfActiveVertices = 0;
2263 for (
int i = 0; i < GetGNV(); i++)
2264 if (activeVert[i] == 1)
2266 activeVert[i] = NumOfActiveVertices++;
2272 int dim = Dimension();
2275 activeBdrElem.SetSize(GetGNBE());
2276 if (GetGNE() == GetNE())
2278 activeBdrElem =
true;
2279 NumOfActiveBdrElems = GetGNBE();
2282 activeBdrElem =
false;
2283 NumOfActiveBdrElems = 0;
2296 for (
int i = 0; i < num_pieces; i++)
2302 for (
int lel = 0; lel < lext->
GetNE(); lel++)
2304 int gel = lelem_elem[lel];
2306 int nd = el_dof->RowSize(gel);
2307 int *gdofs = el_dof->GetRow(gel);
2309 for (
int j = 0; j < nd; j++)
2311 weights(gdofs[j]) = lext->
weights(ldofs[j]);
2324 for (
int i = 0; i < num_pieces; i++)
2331 for (
int lel = 0; lel < lext->
GetNE(); lel++)
2344 if (Dimension() == 1 ) {
return; }
2349 for (
int p = 0;
p < GetNP();
p++)
2351 patchTopo->GetElementEdges(
p, edges, oedge);
2353 for (
int i = 0; i < edges.
Size(); i++)
2355 edges[i] = edge_to_knot[edges[i]];
2358 edges[i] = -1 - edges[i];
2362 if ((Dimension() == 2 &&
2363 (edges[0] != -1 - edges[2] || edges[1] != -1 - edges[3])) ||
2365 (Dimension() == 3 &&
2366 (edges[0] != edges[2] || edges[0] != edges[4] ||
2367 edges[0] != edges[6] || edges[1] != edges[3] ||
2368 edges[1] != edges[5] || edges[1] != edges[7] ||
2369 edges[8] != edges[9] || edges[8] != edges[10] ||
2370 edges[8] != edges[11])))
2372 mfem::err <<
"NURBSExtension::CheckPatch (patch = " <<
p 2373 <<
")\n Inconsistent edge-to-knot mapping!\n";
2384 for (
int p = 0;
p < GetNBP();
p++)
2386 patchTopo->GetBdrElementEdges(
p, edges, oedge);
2388 for (
int i = 0; i < edges.
Size(); i++)
2390 edges[i] = edge_to_knot[edges[i]];
2393 edges[i] = -1 - edges[i];
2397 if ((Dimension() == 2 && (edges[0] < 0)) ||
2398 (Dimension() == 3 && (edges[0] < 0 || edges[1] < 0)))
2400 mfem::err <<
"NURBSExtension::CheckBdrPatch (boundary patch = " 2401 <<
p <<
") : Bad orientation!\n";
2410 MFEM_VERIFY(Dimension()>1,
"1D not yet implemented.");
2415 Array<int> patchvert, edges, orient, edgevert;
2417 patchTopo->GetElementVertices(
p, patchvert);
2419 patchTopo->GetElementEdges(
p, edges, orient);
2427 for (
int i = 0; i < edges.
Size(); i++)
2430 patchTopo->GetEdgeVertices(edges[i], edgevert);
2431 if (edgevert[0] == patchvert[0] && edgevert[1] == patchvert[1])
2436 if (edgevert[0] == patchvert[1] && edgevert[1] == patchvert[0])
2442 if (edgevert[0] == patchvert[1] && edgevert[1] == patchvert[2])
2447 if (edgevert[0] == patchvert[2] && edgevert[1] == patchvert[1])
2453 if (Dimension() == 3)
2456 for (
int i = 0; i < edges.
Size(); i++)
2458 patchTopo->GetEdgeVertices(edges[i], edgevert);
2460 if (edgevert[0] == patchvert[0] && edgevert[1] == patchvert[4])
2465 if (edgevert[0] == patchvert[4] && edgevert[1] == patchvert[0])
2472 MFEM_VERIFY(kvdir.
Find(0) == -1,
"Could not find direction of knotvector.");
2481 if (Dimension() == 1)
2483 knotVectorsCompr.SetSize(GetNKV());
2484 for (
int i = 0; i < GetNKV(); i++)
2486 knotVectorsCompr[i] =
new KnotVector(*(KnotVec(i)));
2490 else if (Dimension() == 2)
2492 knotVectorsCompr.SetSize(GetNP()*Dimension());
2496 else if (Dimension() == 3)
2498 knotVectorsCompr.
SetSize(GetNP()*Dimension());
2504 for (
int p = 0;
p < GetNP();
p++)
2506 CheckKVDirection(
p, kvdir);
2508 patchTopo->GetElementEdges(
p, edges, orient);
2510 for (
int d = 0; d < Dimension(); d++)
2513 int iun = edges[e[d]];
2514 int icomp = Dimension()*
p+d;
2516 knotVectorsCompr[icomp] =
new KnotVector(*(KnotVec(iun)));
2518 if (kvdir[d] == -1) {knotVectorsCompr[icomp]->Flip();}
2522 MFEM_VERIFY(ConsistentKVSets(),
"Mismatch in KnotVectors");
2530 if (Dimension() == 1)
2532 for (
int i = 0; i < GetNKV(); i++)
2534 *(KnotVec(i)) = *(knotVectorsCompr[i]);
2538 else if (Dimension() == 2)
2543 else if (Dimension() == 3)
2550 for (
int p = 0;
p < GetNP();
p++)
2554 patchTopo->GetElementEdges(
p, edges, orient);
2555 CheckKVDirection(
p, kvdir);
2557 for (
int d = 0; d < Dimension(); d++)
2560 if (kvdir[d] == -1) {flip =
true;}
2563 int iun = edges[e[d]];
2564 int icomp = Dimension()*
p+d;
2567 int o1 = KnotVec(iun)->GetOrder();
2568 int o2 = knotVectorsCompr[icomp]->GetOrder();
2569 int diffo = abs(o1 - o2);
2574 *(KnotVec(iun)) = *(knotVectorsCompr[icomp]);
2577 if (flip) { KnotVec(iun)->Flip(); }
2583 if (flip) { knotVectorsCompr[icomp]->Flip(); }
2585 KnotVec(iun)->Difference(*(knotVectorsCompr[icomp]), diffknot);
2587 if (flip) { knotVectorsCompr[icomp]->Flip(); }
2589 if (diffknot.
Size() > 0)
2592 *(KnotVec(iun)) = *(knotVectorsCompr[icomp]);
2595 if (flip) {KnotVec(iun)->Flip();}
2600 MFEM_VERIFY(ConsistentKVSets(),
"Mismatch in KnotVectors");
2606 MFEM_VERIFY(Dimension()>1,
"1D not yet implemented.");
2615 if (Dimension() == 2)
2619 else if (Dimension() == 3)
2625 for (
int p = 0;
p < GetNP();
p++)
2627 patchTopo->GetElementEdges(
p, edges, orient);
2629 CheckKVDirection(
p, kvdir);
2631 for (
int d = 0; d < Dimension(); d++)
2634 if (kvdir[d] == -1) {flip =
true;}
2637 int iun = edges[e[d]];
2638 int icomp = Dimension()*
p+d;
2641 int o1 = KnotVec(iun)->GetOrder();
2642 int o2 = knotVectorsCompr[icomp]->GetOrder();
2643 int diffo = abs(o1 - o2);
2647 mfem::out <<
"\norder of knotVectorsCompr " << d <<
" of patch " <<
p;
2648 mfem::out <<
" does not agree with knotVectors " << KnotInd(iun) <<
"\n";
2653 if (flip) {knotVectorsCompr[icomp]->Flip();}
2655 KnotVec(iun)->Difference(*(knotVectorsCompr[icomp]), diff);
2657 if (flip) {knotVectorsCompr[icomp]->Flip();}
2659 if (diff.
Size() > 0)
2661 mfem::out <<
"\nknotVectorsCompr " << d <<
" of patch " <<
p;
2662 mfem::out <<
" does not agree with knotVectors " << KnotInd(iun) <<
"\n";
2676 if (Dimension() == 1)
2678 kv[0] = knotVectorsCompr[Dimension()*
p];
2680 else if (Dimension() == 2)
2682 kv[0] = knotVectorsCompr[Dimension()*
p];
2683 kv[1] = knotVectorsCompr[Dimension()*
p + 1];
2687 kv[0] = knotVectorsCompr[Dimension()*
p];
2688 kv[1] = knotVectorsCompr[Dimension()*
p + 1];
2689 kv[2] = knotVectorsCompr[Dimension()*
p + 2];
2700 if (Dimension() == 1)
2702 kv[0] = knotVectorsCompr[Dimension()*
p];
2704 else if (Dimension() == 2)
2706 kv[0] = knotVectorsCompr[Dimension()*
p];
2707 kv[1] = knotVectorsCompr[Dimension()*
p + 1];
2711 kv[0] = knotVectorsCompr[Dimension()*
p];
2712 kv[1] = knotVectorsCompr[Dimension()*
p + 1];
2713 kv[2] = knotVectorsCompr[Dimension()*
p + 2];
2724 if (Dimension() == 2)
2726 patchTopo->GetBdrElementEdges(
p, edges, orient);
2727 kv[0] = KnotVec(edges[0]);
2729 else if (Dimension() == 3)
2731 patchTopo->GetBdrElementEdges(
p, edges, orient);
2732 kv[0] = KnotVec(edges[0]);
2733 kv[1] = KnotVec(edges[1]);
2745 if (Dimension() == 2)
2747 patchTopo->GetBdrElementEdges(
p, edges, orient);
2748 kv[0] = KnotVec(edges[0]);
2750 else if (Dimension() == 3)
2752 patchTopo->GetBdrElementEdges(
p, edges, orient);
2753 kv[0] = KnotVec(edges[0]);
2754 kv[1] = KnotVec(edges[1]);
2760 MFEM_VERIFY(mOrders.Size() > 0,
"");
2761 mOrder = mOrders[0];
2762 for (
int i = 1; i < mOrders.Size(); i++)
2764 if (mOrders[i] != mOrder)
2774 mOrders.SetSize(NumOfKnotVectors);
2775 for (
int i = 0; i < NumOfKnotVectors; i++)
2777 mOrders[i] = knotVectors[i]->GetOrder();
2779 SetOrderFromOrders();
2784 int nv = patchTopo->GetNV();
2785 int ne = patchTopo->GetNEdges();
2786 int nf = patchTopo->GetNFaces();
2787 int np = patchTopo->GetNE();
2788 int meshCounter, spaceCounter,
dim = Dimension();
2794 e_meshOffsets.SetSize(ne);
2795 f_meshOffsets.SetSize(nf);
2796 p_meshOffsets.SetSize(np);
2798 v_spaceOffsets.SetSize(nv);
2799 e_spaceOffsets.SetSize(ne);
2800 f_spaceOffsets.SetSize(nf);
2801 p_spaceOffsets.SetSize(np);
2804 for (meshCounter = 0; meshCounter < nv; meshCounter++)
2806 v_meshOffsets[meshCounter] = meshCounter;
2807 v_spaceOffsets[meshCounter] = meshCounter;
2809 spaceCounter = meshCounter;
2812 for (
int e = 0; e < ne; e++)
2814 e_meshOffsets[e] = meshCounter;
2815 e_spaceOffsets[e] = spaceCounter;
2816 meshCounter += KnotVec(e)->GetNE() - 1;
2817 spaceCounter += KnotVec(e)->GetNCP() - 2;
2821 for (
int f = 0;
f < nf;
f++)
2823 f_meshOffsets[
f] = meshCounter;
2824 f_spaceOffsets[
f] = spaceCounter;
2826 patchTopo->GetFaceEdges(
f, edges, orient);
2829 (KnotVec(edges[0])->GetNE() - 1) *
2830 (KnotVec(edges[1])->GetNE() - 1);
2832 (KnotVec(edges[0])->GetNCP() - 2) *
2833 (KnotVec(edges[1])->GetNCP() - 2);
2837 for (
int p = 0;
p < np;
p++)
2839 p_meshOffsets[
p] = meshCounter;
2840 p_spaceOffsets[
p] = spaceCounter;
2846 meshCounter += KnotVec(0)->GetNE() - 1;
2847 spaceCounter += KnotVec(0)->GetNCP() - 2;
2851 patchTopo->GetElementEdges(
p, edges, orient);
2853 (KnotVec(edges[0])->GetNE() - 1) *
2854 (KnotVec(edges[1])->GetNE() - 1);
2856 (KnotVec(edges[0])->GetNCP() - 2) *
2857 (KnotVec(edges[1])->GetNCP() - 2);
2861 patchTopo->GetElementEdges(
p, edges, orient);
2863 (KnotVec(edges[0])->GetNE() - 1) *
2864 (KnotVec(edges[3])->GetNE() - 1) *
2865 (KnotVec(edges[8])->GetNE() - 1);
2867 (KnotVec(edges[0])->GetNCP() - 2) *
2868 (KnotVec(edges[3])->GetNCP() - 2) *
2869 (KnotVec(edges[8])->GetNCP() - 2);
2872 NumOfVertices = meshCounter;
2873 NumOfDofs = spaceCounter;
2878 int dim = Dimension();
2882 for (
int p = 0;
p < GetNP();
p++)
2884 GetPatchKnotVectors(
p, kv);
2886 int ne = kv[0]->GetNE();
2887 for (
int d = 1; d <
dim; d++)
2889 ne *= kv[d]->GetNE();
2892 NumOfElements += ne;
2898 int dim = Dimension() - 1;
2901 NumOfBdrElements = 0;
2902 for (
int p = 0;
p < GetNBP();
p++)
2904 GetBdrPatchKnotVectors(
p, kv);
2907 for (
int d = 0; d <
dim; d++)
2909 ne *= kv[d]->GetNE();
2912 NumOfBdrElements += ne;
2920 if (Dimension() == 1)
2922 Get1DElementTopo(elements);
2924 else if (Dimension() == 2)
2926 Get2DElementTopo(elements);
2930 Get3DElementTopo(elements);
2942 for (
int p = 0;
p < GetNP();
p++)
2947 int patch_attr = patchTopo->GetAttribute(
p);
2949 for (
int i = 0; i < nx; i++)
2953 ind[0] = activeVert[p2g(i)];
2954 ind[1] = activeVert[p2g(i+1)];
2956 elements[el] =
new Segment(ind, patch_attr);
2972 for (
int p = 0;
p < GetNP();
p++)
2978 int patch_attr = patchTopo->GetAttribute(
p);
2980 for (
int j = 0; j < ny; j++)
2982 for (
int i = 0; i < nx; i++)
2986 ind[0] = activeVert[p2g(i, j )];
2987 ind[1] = activeVert[p2g(i+1,j )];
2988 ind[2] = activeVert[p2g(i+1,j+1)];
2989 ind[3] = activeVert[p2g(i, j+1)];
3008 for (
int p = 0;
p < GetNP();
p++)
3015 int patch_attr = patchTopo->GetAttribute(
p);
3017 for (
int k = 0; k < nz; k++)
3019 for (
int j = 0; j < ny; j++)
3021 for (
int i = 0; i < nx; i++)
3025 ind[0] = activeVert[p2g(i, j, k)];
3026 ind[1] = activeVert[p2g(i+1,j, k)];
3027 ind[2] = activeVert[p2g(i+1,j+1,k)];
3028 ind[3] = activeVert[p2g(i, j+1,k)];
3030 ind[4] = activeVert[p2g(i, j, k+1)];
3031 ind[5] = activeVert[p2g(i+1,j, k+1)];
3032 ind[6] = activeVert[p2g(i+1,j+1,k+1)];
3033 ind[7] = activeVert[p2g(i, j+1,k+1)];
3035 elements[el] =
new Hexahedron(ind, patch_attr);
3049 if (Dimension() == 1)
3051 Get1DBdrElementTopo(boundary);
3053 else if (Dimension() == 2)
3055 Get2DBdrElementTopo(boundary);
3059 Get3DBdrElementTopo(boundary);
3071 for (
int b = 0;
b < GetNBP();
b++)
3074 int bdr_patch_attr = patchTopo->GetBdrAttribute(
b);
3076 if (activeBdrElem[g_be])
3078 ind[0] = activeVert[p2g[0]];
3079 boundary[l_be] =
new Point(ind, bdr_patch_attr);
3094 for (
int b = 0;
b < GetNBP();
b++)
3099 int bdr_patch_attr = patchTopo->GetBdrAttribute(
b);
3101 for (
int i = 0; i < nx; i++)
3103 if (activeBdrElem[g_be])
3105 int i_ = (okv[0] >= 0) ? i : (nx - 1 - i);
3106 ind[0] = activeVert[p2g[i_ ]];
3107 ind[1] = activeVert[p2g[i_+1]];
3109 boundary[l_be] =
new Segment(ind, bdr_patch_attr);
3125 for (
int b = 0;
b < GetNBP();
b++)
3131 int bdr_patch_attr = patchTopo->GetBdrAttribute(
b);
3133 for (
int j = 0; j < ny; j++)
3135 int j_ = (okv[1] >= 0) ? j : (ny - 1 - j);
3136 for (
int i = 0; i < nx; i++)
3138 if (activeBdrElem[g_be])
3140 int i_ = (okv[0] >= 0) ? i : (nx - 1 - i);
3141 ind[0] = activeVert[p2g(i_, j_ )];
3142 ind[1] = activeVert[p2g(i_+1,j_ )];
3143 ind[2] = activeVert[p2g(i_+1,j_+1)];
3144 ind[3] = activeVert[p2g(i_, j_+1)];
3157 activeDof.SetSize(GetNTotalDof());
3160 if (Dimension() == 1)
3162 Generate1DElementDofTable();
3164 else if (Dimension() == 2)
3166 Generate2DElementDofTable();
3170 Generate3DElementDofTable();
3173 SetPatchToElements();
3175 NumOfActiveDofs = 0;
3176 for (
int d = 0; d < GetNTotalDof(); d++)
3180 activeDof[d] = NumOfActiveDofs;
3183 int *dof = el_dof->GetJ();
3184 int ndof = el_dof->Size_of_connections();
3185 for (
int i = 0; i < ndof; i++)
3187 dof[i] = activeDof[dof[i]] - 1;
3199 el_to_patch.
SetSize(NumOfActiveElems);
3200 el_to_IJK.SetSize(NumOfActiveElems, 2);
3202 for (
int p = 0;
p < GetNP();
p++)
3207 const int ord0 = kv[0]->
GetOrder();
3208 for (
int i = 0; i < kv[0]->
GetNKS(); i++)
3210 if (kv[0]->isElement(i))
3215 for (
int ii = 0; ii <= ord0; ii++)
3217 conn.
to = DofMap(p2g(i+ii));
3218 activeDof[conn.
to] = 1;
3219 el_dof_list.
Append(conn);
3221 el_to_patch[el] =
p;
3222 el_to_IJK(el,0) = i;
3231 el_dof =
new Table(NumOfActiveElems, el_dof_list);
3242 el_to_patch.
SetSize(NumOfActiveElems);
3243 el_to_IJK.SetSize(NumOfActiveElems, 2);
3245 for (
int p = 0;
p < GetNP();
p++)
3250 const int ord0 = kv[0]->
GetOrder();
3251 const int ord1 = kv[1]->
GetOrder();
3252 for (
int j = 0; j < kv[1]->
GetNKS(); j++)
3254 if (kv[1]->isElement(j))
3256 for (
int i = 0; i < kv[0]->
GetNKS(); i++)
3258 if (kv[0]->isElement(i))
3263 for (
int jj = 0; jj <= ord1; jj++)
3265 for (
int ii = 0; ii <= ord0; ii++)
3267 conn.
to = DofMap(p2g(i+ii,j+jj));
3268 activeDof[conn.
to] = 1;
3269 el_dof_list.
Append(conn);
3272 el_to_patch[el] =
p;
3273 el_to_IJK(el,0) = i;
3274 el_to_IJK(el,1) = j;
3285 el_dof =
new Table(NumOfActiveElems, el_dof_list);
3296 el_to_patch.
SetSize(NumOfActiveElems);
3297 el_to_IJK.SetSize(NumOfActiveElems, 3);
3299 for (
int p = 0;
p < GetNP();
p++)
3304 const int ord0 = kv[0]->
GetOrder();
3305 const int ord1 = kv[1]->
GetOrder();
3306 const int ord2 = kv[2]->
GetOrder();
3307 for (
int k = 0; k < kv[2]->
GetNKS(); k++)
3309 if (kv[2]->isElement(k))
3311 for (
int j = 0; j < kv[1]->
GetNKS(); j++)
3313 if (kv[1]->isElement(j))
3315 for (
int i = 0; i < kv[0]->
GetNKS(); i++)
3317 if (kv[0]->isElement(i))
3322 for (
int kk = 0; kk <= ord2; kk++)
3324 for (
int jj = 0; jj <= ord1; jj++)
3326 for (
int ii = 0; ii <= ord0; ii++)
3328 conn.
to = DofMap(p2g(i+ii, j+jj, k+kk));
3329 activeDof[conn.
to] = 1;
3330 el_dof_list.
Append(conn);
3335 el_to_patch[el] =
p;
3336 el_to_IJK(el,0) = i;
3337 el_to_IJK(el,1) = j;
3338 el_to_IJK(el,2) = k;
3351 el_dof =
new Table(NumOfActiveElems, el_dof_list);
3361 if (Dimension() == 1)
3363 const int nx = kv[0]->
GetNCP();
3366 for (
int i=0; i<nx; ++i)
3368 dofs[i] = DofMap(p2g(i));
3371 else if (Dimension() == 2)
3373 const int nx = kv[0]->
GetNCP();
3374 const int ny = kv[1]->
GetNCP();
3377 for (
int j=0; j<ny; ++j)
3378 for (
int i=0; i<nx; ++i)
3380 dofs[i + (nx * j)] = DofMap(p2g(i, j));
3383 else if (Dimension() == 3)
3385 const int nx = kv[0]->
GetNCP();
3386 const int ny = kv[1]->
GetNCP();
3387 const int nz = kv[2]->
GetNCP();
3390 for (
int k=0; k<nz; ++k)
3391 for (
int j=0; j<ny; ++j)
3392 for (
int i=0; i<nx; ++i)
3394 dofs[i + (nx * (j + (k * ny)))] = DofMap(p2g(i, j, k));
3399 MFEM_ABORT(
"Only 1D/2D/3D supported currently in NURBSExtension::GetPatchDofs");
3405 if (Dimension() == 1)
3407 Generate1DBdrElementDofTable();
3409 else if (Dimension() == 2)
3411 Generate2DBdrElementDofTable();
3415 Generate3DBdrElementDofTable();
3418 SetPatchToBdrElements();
3420 int *dof = bel_dof->GetJ();
3421 int ndof = bel_dof->Size_of_connections();
3422 for (
int i = 0; i < ndof; i++)
3424 dof[i] = activeDof[dof[i]] - 1;
3431 int lbe = 0, okv[1];
3436 bel_to_patch.
SetSize(NumOfActiveBdrElems);
3437 bel_to_IJK.SetSize(NumOfActiveBdrElems, 1);
3439 for (
int b = 0;
b < GetNBP();
b++)
3443 if (activeBdrElem[gbe])
3446 conn.
to = DofMap(p2g[0]);
3447 bel_dof_list.
Append(conn);
3448 bel_to_patch[lbe] =
b;
3449 bel_to_IJK(lbe,0) = 0;
3455 bel_dof =
new Table(NumOfActiveBdrElems, bel_dof_list);
3461 int lbe = 0, okv[1];
3466 bel_to_patch.
SetSize(NumOfActiveBdrElems);
3467 bel_to_IJK.SetSize(NumOfActiveBdrElems, 1);
3469 for (
int b = 0;
b < GetNBP();
b++)
3472 const int nx = p2g.
nx();
3474 const int nks0 = kv[0]->
GetNKS();
3475 const int ord0 = kv[0]->
GetOrder();
3476 for (
int i = 0; i < nks0; i++)
3478 if (kv[0]->isElement(i))
3480 if (activeBdrElem[gbe])
3483 for (
int ii = 0; ii <= ord0; ii++)
3485 conn.
to = DofMap(p2g[(okv[0] >= 0) ? (i+ii) : (nx-i-ii)]);
3486 bel_dof_list.
Append(conn);
3488 bel_to_patch[lbe] =
b;
3489 bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
3497 bel_dof =
new Table(NumOfActiveBdrElems, bel_dof_list);
3504 int lbe = 0, okv[2];
3509 bel_to_patch.
SetSize(NumOfActiveBdrElems);
3510 bel_to_IJK.SetSize(NumOfActiveBdrElems, 2);
3512 for (
int b = 0;
b < GetNBP();
b++)
3515 const int nx = p2g.
nx();
3516 const int ny = p2g.
ny();
3519 const int nks0 = kv[0]->
GetNKS();
3520 const int ord0 = kv[0]->
GetOrder();
3521 const int nks1 = kv[1]->
GetNKS();
3522 const int ord1 = kv[1]->
GetOrder();
3523 for (
int j = 0; j < nks1; j++)
3525 if (kv[1]->isElement(j))
3527 for (
int i = 0; i < nks0; i++)
3529 if (kv[0]->isElement(i))
3531 if (activeBdrElem[gbe])
3534 for (
int jj = 0; jj <= ord1; jj++)
3536 const int jj_ = (okv[1] >= 0) ? (j+jj) : (ny-j-jj);
3537 for (
int ii = 0; ii <= ord0; ii++)
3539 const int ii_ = (okv[0] >= 0) ? (i+ii) : (nx-i-ii);
3540 conn.
to = DofMap(p2g(ii_, jj_));
3541 bel_dof_list.
Append(conn);
3544 bel_to_patch[lbe] =
b;
3545 bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
3546 bel_to_IJK(lbe,1) = (okv[1] >= 0) ? j : (-1-j);
3556 bel_dof =
new Table(NumOfActiveBdrElems, bel_dof_list);
3562 for (
int gv = 0; gv < GetGNV(); gv++)
3563 if (activeVert[gv] >= 0)
3565 lvert_vert[activeVert[gv]] = gv;
3572 for (
int le = 0, ge = 0; ge < GetGNE(); ge++)
3575 lelem_elem[le++] = ge;
3587 NURBSFE->
SetIJK(el_to_IJK.GetRow(i));
3588 if (el_to_patch[i] != NURBSFE->
GetPatch())
3590 GetPatchKnotVectors(el_to_patch[i], NURBSFE->
KnotVectors());
3594 el_dof->GetRow(i, dofs);
3595 weights.GetSubVector(dofs, NURBSFE->
Weights());
3602 if (Dimension() == 1) {
return; }
3610 NURBSFE->
SetIJK(bel_to_IJK.GetRow(i));
3611 if (bel_to_patch[i] != NURBSFE->
GetPatch())
3613 GetBdrPatchKnotVectors(bel_to_patch[i], NURBSFE->
KnotVectors());
3614 NURBSFE->
SetPatch(bel_to_patch[i]);
3617 bel_dof->GetRow(i, dofs);
3618 weights.GetSubVector(dofs, NURBSFE->
Weights());
3628 if (patches.Size() == 0)
3630 GetPatchNets(Nodes, Dimension());
3636 if (patches.Size() == 0) {
return; }
3638 SetSolutionVector(Nodes, Dimension());
3644 if (patches.Size() == 0)
3646 mfem_error(
"NURBSExtension::SetKnotsFromPatches :" 3647 " No patches available!");
3652 for (
int p = 0;
p < patches.Size();
p++)
3654 GetPatchKnotVectors(
p, kv);
3656 for (
int i = 0; i < kv.
Size(); i++)
3658 *kv[i] = *patches[
p]->GetKV(i);
3663 SetOrdersFromKnotVectors();
3670 NumOfActiveElems = NumOfElements;
3671 activeElem.SetSize(NumOfElements);
3674 GenerateActiveVertices();
3676 GenerateElementDofTable();
3677 GenerateActiveBdrElems();
3678 GenerateBdrElementDofTable();
3680 ConnectBoundaries();
3692 const int vdim = fes->
GetVDim();
3694 for (
int p = 0;
p < GetNP();
p++)
3699 const int nx = kv[0]->GetNCP();
3700 const int ny = kv[1]->GetNCP();
3701 const int nz = (kv.
Size() == 2) ? 1 : kv[2]->GetNCP();
3702 for (
int k = 0; k < nz; k++)
3704 for (
int j = 0; j < ny; j++)
3706 for (
int i = 0; i < nx; i++)
3708 const int ll = (kv.
Size() == 2) ? p2g(i,j) : p2g(i,j,k);
3709 const int l = DofMap(ll);
3710 for (
int vd = 0; vd < vdim; vd++)
3728 const int vdim = fes->
GetVDim();
3730 for (
int p = 0;
p < GetNP();
p++)
3732 os <<
"\n# patch " <<
p <<
"\n\n";
3735 const int nx = kv[0]->GetNCP();
3736 const int ny = kv[1]->GetNCP();
3737 const int nz = (kv.Size() == 2) ? 1 : kv[2]->GetNCP();
3738 for (
int k = 0; k < nz; k++)
3740 for (
int j = 0; j < ny; j++)
3742 for (
int i = 0; i < nx; i++)
3744 const int ll = (kv.Size() == 2) ? p2g(i,j) : p2g(i,j,k);
3745 const int l = DofMap(ll);
3747 for (
int vd = 1; vd < vdim; vd++)
3760 for (
int p = 0;
p < patches.Size();
p++)
3762 for (
int dir = 0; dir < patches[
p]->GetNKV(); dir++)
3764 int oldd = patches[
p]->GetKV(dir)->GetOrder();
3765 int newd = std::min(oldd + rel_degree, degree);
3768 patches[
p]->DegreeElevate(dir, newd - oldd);
3776 for (
int p = 0;
p < patches.Size();
p++)
3778 patches[
p]->UniformRefinement();
3790 for (
int p = 0;
p < patches.Size();
p++)
3794 pkv[0] = kv[KnotInd(
p)];
3796 else if (Dimension()==2)
3798 patchTopo->GetElementEdges(
p, edges, orient);
3799 pkv[0] = kv[KnotInd(edges[0])];
3800 pkv[1] = kv[KnotInd(edges[1])];
3802 else if (Dimension()==3)
3804 patchTopo->GetElementEdges(
p, edges, orient);
3805 pkv[0] = kv[KnotInd(edges[0])];
3806 pkv[1] = kv[KnotInd(edges[3])];
3807 pkv[2] = kv[KnotInd(edges[8])];
3815 CheckKVDirection(
p, kvdir);
3818 for (
int d = 0; d < Dimension(); d++)
3828 patches[
p]->KnotInsert(pkvc);
3829 for (
int d = 0; d < Dimension(); d++) {
delete pkvc[d]; }
3841 for (
int p = 0;
p < patches.Size();
p++)
3845 pkv[0] = kv[KnotInd(
p)];
3847 else if (Dimension()==2)
3849 patchTopo->GetElementEdges(
p, edges, orient);
3850 pkv[0] = kv[KnotInd(edges[0])];
3851 pkv[1] = kv[KnotInd(edges[1])];
3853 else if (Dimension()==3)
3855 patchTopo->GetElementEdges(
p, edges, orient);
3856 pkv[0] = kv[KnotInd(edges[0])];
3857 pkv[1] = kv[KnotInd(edges[3])];
3858 pkv[2] = kv[KnotInd(edges[8])];
3865 CheckKVDirection(
p, kvdir);
3868 for (
int d = 0; d < Dimension(); d++)
3870 pkvc[d] =
new Vector(*(pkv[d]));
3875 KnotVector *kva = knotVectorsCompr[Dimension()*
p+d];
3876 double apb = (*kva)[0] + (*kva)[kva->
Size()-1];
3879 int size = pkvc[d]->
Size();
3880 int ns = ceil(size/2.0);
3881 for (
int j = 0; j < ns; j++)
3883 double tmp = apb - pkvc[d]->Elem(j);
3884 pkvc[d]->Elem(j) = apb - pkvc[d]->Elem(size-1-j);
3885 pkvc[d]->Elem(size-1-j) = tmp;
3890 patches[
p]->KnotInsert(pkvc);
3892 for (
int i = 0; i < Dimension(); i++) {
delete pkvc[i]; }
3898 if (Dimension() == 1)
3900 Get1DPatchNets(coords, vdim);
3902 else if (Dimension() == 2)
3904 Get2DPatchNets(coords, vdim);
3908 Get3DPatchNets(coords, vdim);
3917 patches.SetSize(GetNP());
3918 for (
int p = 0;
p < GetNP();
p++)
3924 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3926 const int l = DofMap(p2g(i));
3927 for (
int d = 0; d < vdim; d++)
3929 Patch(i,d) = coords(l*vdim + d)*weights(l);
3931 Patch(i,vdim) = weights(l);
3942 patches.SetSize(GetNP());
3943 for (
int p = 0;
p < GetNP();
p++)
3949 for (
int j = 0; j < kv[1]->GetNCP(); j++)
3951 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3953 const int l = DofMap(p2g(i,j));
3954 for (
int d = 0; d < vdim; d++)
3956 Patch(i,j,d) = coords(l*vdim + d)*weights(l);
3958 Patch(i,j,vdim) = weights(l);
3969 patches.SetSize(GetNP());
3970 for (
int p = 0;
p < GetNP();
p++)
3976 for (
int k = 0; k < kv[2]->GetNCP(); k++)
3978 for (
int j = 0; j < kv[1]->GetNCP(); j++)
3980 for (
int i = 0; i < kv[0]->GetNCP(); i++)
3982 const int l = DofMap(p2g(i,j,k));
3983 for (
int d = 0; d < vdim; d++)
3985 Patch(i,j,k,d) = coords(l*vdim + d)*weights(l);
3987 Patch(i,j,k,vdim) = weights(l);
3996 if (Dimension() == 1)
3998 Set1DSolutionVector(coords, vdim);
4000 else if (Dimension() == 2)
4002 Set2DSolutionVector(coords, vdim);
4006 Set3DSolutionVector(coords, vdim);
4015 weights.SetSize(GetNDof());
4016 for (
int p = 0;
p < GetNP();
p++)
4020 MFEM_ASSERT(vdim+1 == patch.
GetNC(),
"");
4022 for (
int i = 0; i < kv[0]->GetNCP(); i++)
4024 const int l = p2g(i);
4025 for (
int d = 0; d < vdim; d++)
4027 coords(l*vdim + d) = patch(i,d)/patch(i,vdim);
4029 weights(l) = patch(i,vdim);
4042 weights.SetSize(GetNDof());
4043 for (
int p = 0;
p < GetNP();
p++)
4047 MFEM_ASSERT(vdim+1 == patch.
GetNC(),
"");
4049 for (
int j = 0; j < kv[1]->GetNCP(); j++)
4051 for (
int i = 0; i < kv[0]->GetNCP(); i++)
4053 const int l = p2g(i,j);
4054 for (
int d = 0; d < vdim; d++)
4056 coords(l*vdim + d) = patch(i,j,d)/patch(i,j,vdim);
4058 weights(l) = patch(i,j,vdim);
4070 weights.SetSize(GetNDof());
4071 for (
int p = 0;
p < GetNP();
p++)
4075 MFEM_ASSERT(vdim+1 == patch.
GetNC(),
"");
4077 for (
int k = 0; k < kv[2]->GetNCP(); k++)
4079 for (
int j = 0; j < kv[1]->GetNCP(); j++)
4081 for (
int i = 0; i < kv[0]->GetNCP(); i++)
4083 const int l = p2g(i,j,k);
4084 for (
int d = 0; d < vdim; d++)
4086 coords(l*vdim + d) = patch(i,j,k,d)/patch(i,j,k,vdim);
4088 weights(l) = patch(i,j,k,vdim);
4098 MFEM_VERIFY(ijk.
Size() == el_to_IJK.NumCols(),
"");
4099 el_to_IJK.GetRow(elem, ijk);
4104 const int np = GetNP();
4105 patch_to_el.resize(np);
4107 for (
int e=0; e<el_to_patch.Size(); ++e)
4109 patch_to_el[el_to_patch[e]].Append(e);
4115 const int nbp = GetNBP();
4116 patch_to_bel.resize(nbp);
4118 for (
int e=0; e<bel_to_patch.Size(); ++e)
4120 patch_to_bel[bel_to_patch[e]].Append(e);
4126 MFEM_ASSERT(patch_to_el.size() > 0,
"patch_to_el not set");
4128 return patch_to_el[patch];
4133 MFEM_ASSERT(patch_to_bel.size() > 0,
"patch_to_el not set");
4135 return patch_to_bel[patch];
4141 partitioning(orig.partitioning ? new int[orig.GetGNE()] : NULL),
4143 ldof_group(orig.ldof_group)
4148 std::memcpy(partitioning, orig.partitioning, orig.
GetGNE()*
sizeof(int));
4160 mfem_error(
"ParNURBSExtension::ParNURBSExtension :\n" 4161 " all elements in the parent must be active!");
4168 mfem_error(
"ParNURBSExtension::ParNURBSExtension :\n" 4169 " parent does not own the patch topology!");
4192 partitioning =
new int[
GetGNE()];
4193 for (
int i = 0; i <
GetGNE(); i++)
4195 partitioning[i] = part[i];
4197 SetActive(partitioning, active_bel);
4205 BuildGroups(partitioning, *serial_elem_dof);
4209 for (
int gel = 0, lel = 0; gel <
GetGNE(); gel++)
4215 int *gdofs = serial_elem_dof->
GetRow(gel);
4216 for (
int i = 0; i < ndofs; i++)
4227 : gtopo(par_parent->gtopo.GetComm())
4286 partitioning = NULL;
4288 MFEM_VERIFY(par_parent->partitioning,
4289 "parent ParNURBSExtension has no partitioning!");
4294 bool extract_weights =
false;
4299 SetActive(par_parent->partitioning, par_parent->
activeBdrElem);
4310 extract_weights =
true;
4313 Table *glob_elem_dof = GetGlobalElementDofTable();
4314 BuildGroups(par_parent->partitioning, *glob_elem_dof);
4315 if (extract_weights)
4322 for (
int gel = 0, lel = 0; gel <
GetGNE(); gel++)
4328 int *gdofs = glob_elem_dof->
GetRow(gel);
4329 for (
int i = 0; i < ndofs; i++)
4331 weights(ldofs[i]) = glob_weights(gdofs[i]);
4337 delete glob_elem_dof;
4340 Table *ParNURBSExtension::GetGlobalElementDofTable()
4344 return Get1DGlobalElementDofTable();
4348 return Get2DGlobalElementDofTable();
4352 return Get3DGlobalElementDofTable();
4356 Table *ParNURBSExtension::Get1DGlobalElementDofTable()
4359 const KnotVector *kv[1];
4361 Array<Connection> gel_dof_list;
4365 p2g.SetPatchDofMap(
p, kv);
4368 const int ord0 = kv[0]->GetOrder();
4370 for (
int i = 0; i < kv[0]->GetNKS(); i++)
4372 if (kv[0]->isElement(i))
4374 Connection conn(el,0);
4375 for (
int ii = 0; ii <= ord0; ii++)
4377 conn.to =
DofMap(p2g(i+ii));
4378 gel_dof_list.Append(conn);
4385 return (
new Table(
GetGNE(), gel_dof_list));
4388 Table *ParNURBSExtension::Get2DGlobalElementDofTable()
4391 const KnotVector *kv[2];
4393 Array<Connection> gel_dof_list;
4397 p2g.SetPatchDofMap(
p, kv);
4400 const int ord0 = kv[0]->GetOrder();
4401 const int ord1 = kv[1]->GetOrder();
4402 for (
int j = 0; j < kv[1]->GetNKS(); j++)
4404 if (kv[1]->isElement(j))
4406 for (
int i = 0; i < kv[0]->GetNKS(); i++)
4408 if (kv[0]->isElement(i))
4410 Connection conn(el,0);
4411 for (
int jj = 0; jj <= ord1; jj++)
4413 for (
int ii = 0; ii <= ord0; ii++)
4415 conn.to =
DofMap(p2g(i+ii,j+jj));
4416 gel_dof_list.Append(conn);
4426 return (
new Table(
GetGNE(), gel_dof_list));
4429 Table *ParNURBSExtension::Get3DGlobalElementDofTable()
4432 const KnotVector *kv[3];
4434 Array<Connection> gel_dof_list;
4438 p2g.SetPatchDofMap(
p, kv);
4441 const int ord0 = kv[0]->GetOrder();
4442 const int ord1 = kv[1]->GetOrder();
4443 const int ord2 = kv[2]->GetOrder();
4444 for (
int k = 0; k < kv[2]->GetNKS(); k++)
4446 if (kv[2]->isElement(k))
4448 for (
int j = 0; j < kv[1]->GetNKS(); j++)
4450 if (kv[1]->isElement(j))
4452 for (
int i = 0; i < kv[0]->GetNKS(); i++)
4454 if (kv[0]->isElement(i))
4456 Connection conn(el,0);
4457 for (
int kk = 0; kk <= ord2; kk++)
4459 for (
int jj = 0; jj <= ord1; jj++)
4461 for (
int ii = 0; ii <= ord0; ii++)
4463 conn.to =
DofMap(p2g(i+ii,j+jj,k+kk));
4464 gel_dof_list.Append(conn);
4477 return (
new Table(
GetGNE(), gel_dof_list));
4480 void ParNURBSExtension::SetActive(
const int *partitioning_,
4481 const Array<bool> &active_bel)
4487 for (
int i = 0; i <
GetGNE(); i++)
4488 if (partitioning_[i] == MyRank)
4496 for (
int i = 0; i <
GetGNBE(); i++)
4503 void ParNURBSExtension::BuildGroups(
const int *partitioning_,
4504 const Table &elem_dof)
4508 ListOfIntegerSets groups;
4513 for (
int i = 0; i < dof_proc.Size_of_connections(); i++)
4515 dof_proc.GetJ()[i] = partitioning_[dof_proc.GetJ()[i]];
4520 group.Recreate(1, &MyRank);
4521 groups.Insert(group);
4528 group.Recreate(dof_proc.RowSize(d), dof_proc.GetRow(d));
4536 #endif // MFEM_USE_MPI 4539 void NURBSPatchMap::GetPatchKnotVectors(
int p,
const KnotVector *kv[])
4566 void NURBSPatchMap::GetBdrPatchKnotVectors(
int p,
const KnotVector *kv[],
4574 kv[0] = Ext->
KnotVec(edges[0], oedge[0], &okv[0]);
4583 kv[0] = Ext->
KnotVec(edges[0], oedge[0], &okv[0]);
4584 kv[1] = Ext->
KnotVec(edges[1], oedge[1], &okv[1]);
4591 GetPatchKnotVectors(
p, kv);
4593 I = kv[0]->
GetNE() - 1;
4595 for (
int i = 0; i < verts.
Size(); i++)
4602 J = kv[1]->
GetNE() - 1;
4603 for (
int i = 0; i < edges.
Size(); i++)
4610 K = kv[2]->
GetNE() - 1;
4612 for (
int i = 0; i < faces.
Size(); i++)
4623 GetPatchKnotVectors(
p, kv);
4627 for (
int i = 0; i < verts.
Size(); i++)
4634 for (
int i = 0; i < edges.
Size(); i++)
4643 for (
int i = 0; i < faces.
Size(); i++)
4655 GetBdrPatchKnotVectors(
p, kv, okv);
4657 for (
int i = 0; i < verts.
Size(); i++)
4668 I = kv[0]->
GetNE() - 1;
4673 I = kv[0]->
GetNE() - 1;
4674 J = kv[1]->
GetNE() - 1;
4676 for (
int i = 0; i < edges.
Size(); i++)
4687 GetBdrPatchKnotVectors(
p, kv, okv);
4689 for (
int i = 0; i < verts.
Size(); i++)
4708 for (
int i = 0; i < edges.
Size(); i++)
Array< KnotVector * > knotVectors
Abstract class for all finite elements.
Array< int > f_meshOffsets
void Create(ListOfIntegerSets &groups, int mpitag)
Set up the group topology given the list of sets of shared entities.
Array2D< int > bel_to_IJK
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
void SetCoordsFromPatches(Vector &Nodes)
Array< KnotVector * > knotVectorsCompr
void ConnectBoundaries2D(int bnd0, int bnd1)
KnotVector * KnotVec(int edge)
Class for grid function - Vector with associated FE space.
void GetElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of element i.
void DegreeElevate(int dir, int t)
NURBSPatch * Interpolate(NURBSPatch &p1, NURBSPatch &p2)
void Generate2DElementDofTable()
void MergeGridFunctions(GridFunction *gf_array[], int num_pieces, GridFunction &merged)
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void PrintSolution(const GridFunction &sol, std::ostream &out) const
void LoadFE(int i, const FiniteElement *FE) 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 Print(std::ostream &out) const
void CalcDShape(Vector &grad, int i, double xi) const
int DofMap(int dof) const
void Get2DBdrElementTopo(Array< Element *> &boundary) const
void Rotate3D(double normal[], double angle)
Array< int > e_meshOffsets
int Size() const
Returns the size of the vector.
void GetElements()
Count the number of elements.
void SetOrdersFromKnotVectors()
void GetPatchDofs(const int patch, Array< int > &dofs)
const NURBSExtension * GetNURBSext() const
An arbitrary order and dimension NURBS element.
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
void Generate1DBdrElementDofTable()
void Generate3DBdrElementDofTable()
void SetIJK(const int *IJK) const
Array< int > e_spaceOffsets
void GetBdrElementTopo(Array< Element *> &boundary) const
void GenerateBdrElementDofTable()
int MyRank() const
Return the MPI rank within this object's communicator.
void GetElementIJK(int elem, Array< int > &ijk)
void LoadSolution(std::istream &input, GridFunction &sol) const
void GetElementLocalToGlobal(Array< int > &lelem_elem)
void Get2DElementTopo(Array< Element *> &elements) const
void KnotInsert(Array< KnotVector *> &kv)
void Set1DSolutionVector(Vector &Nodes, int vdim)
void SetPatchToBdrElements()
void ConnectBoundaries1D(int bnd0, int bnd1)
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
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)
Check if the stream starts with comment_char. If so skip it.
void DeleteAll()
Delete the whole array.
void SwapDirections(int dir1, int dir2)
friend class NURBSPatchMap
virtual void SetOrder() const
Update the NURBSFiniteElement according to the currently set knot vectors.
KnotVector()
Create KnotVector.
static const int MaxOrder
Array< int > v_spaceOffsets
std::function< double(const Vector &)> f(double mass_coeff)
void GetElementTopo(Array< Element *> &elements) const
void Generate2DBdrElementDofTable()
Data type hexahedron element.
void Generate1DElementDofTable()
void GetBdrElementFace(int i, int *f, int *o) const
Return the index and the orientation of the face of bdr element i. (3D)
void GetBdrPatchKnotVectors(int p, Array< KnotVector *> &kv)
void ConnectBoundaries3D(int bnd0, int bnd1)
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
ParNURBSExtension(const ParNURBSExtension &orig)
void Set3DSolutionVector(Vector &Nodes, int vdim)
void GenerateActiveBdrElems()
int Append(const T &el)
Append element 'el' to array, resize if necessary.
int GetOrder() const
If all orders are identical, return that number. Otherwise, return NURBSFECollection::VariableOrder.
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.
const Array< int > & GetOrders() const
Read-only access to the orders of all knot vectors.
void Get2DPatchNets(const Vector &Nodes, int vdim)
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
void UniformRefinement(Vector &newknots) const
void CalcDnShape(Vector &gradn, int n, int i, double xi) const
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
void SetKnotsFromPatches()
void GetBdrElementEdges(int i, Array< int > &edges, Array< int > &cor) const
Return the indices and the orientations of all edges of bdr element i.
Array< const KnotVector * > & KnotVectors() const
Array< int > f_spaceOffsets
Array< bool > activeBdrElem
FiniteElementSpace * FESpace()
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
const Array< int > & GetPatchBdrElements(int patch)
void Get3DElementTopo(Array< Element *> &elements) const
void Get3DBdrElementTopo(Array< Element *> &boundary) const
int GetVDim() const
Returns vector dimension.
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
void SetPatchToElements()
Mesh * GetMesh() const
Returns the mesh.
void Swap(Array< T > &, Array< T > &)
void Difference(const KnotVector &kv, Vector &diff) const
double p(const Vector &x, double t)
void LoadBE(int i, const FiniteElement *BE) const
void SetElement(int e) const
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Array< int > v_meshOffsets
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void SetBdrPatchVertexMap(int p, const KnotVector *kv[], int *okv)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
Array< int > p_meshOffsets
void GetPatchKnotVectors(int p, Array< KnotVector *> &kv)
KnotVector & operator=(const KnotVector &kv)
void SetPatchVertexMap(int p, const KnotVector *kv[])
Helper struct for defining a connectivity table, see Table::MakeFromList.
const Array< int > & GetPatchElements(int patch)
Table * GetElementDofTable()
void SetOrderFromOrders()
void Get1DBdrElementTopo(Array< Element *> &boundary) const
void CreateComprehensiveKV()
void Rotate(double angle, double normal[]=NULL)
Rotate the NURBSPatch.
void CheckKVDirection(int p, Array< int > &kvdir)
NURBSExtension * NURBSext
Optional NURBS mesh extension.
void GetPatchNets(const Vector &Nodes, int vdim)
const KnotVector * GetKnotVector(int i) const
NURBSPatch * Revolve3D(NURBSPatch &patch, double n[], double ang, int times)
Array< int > p_spaceOffsets
void SetSolutionVector(Vector &Nodes, int vdim)
void SetBdrPatchDofMap(int p, const KnotVector *kv[], int *okv)
void CalcShape(Vector &shape, int i, double xi) const
void GenerateElementDofTable()
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
constexpr int dimension
This example only works in 3D. Kernels for 2D are not implemented.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
void Get1DElementTopo(Array< Element *> &elements) const
int Size() const
Return the logical size of the array.
int DofToVDof(int dof, int vd, int ndofs=-1) const
Compute a single vdof corresponding to the index dof and the vector index vd.
void DeleteAll()
Delete all dynamically allocated memory, resetting all dimensions to zero.
void Get1DPatchNets(const Vector &Nodes, int vdim)
void DegreeElevate(int rel_degree, int degree=16)
void PrintFunctions(std::ostream &out, int samples=11) const
void SetPatch(int p) const
Data type line segment element.
Array< int > bel_to_patch
void SetPatchDofMap(int p, const KnotVector *kv[])
void ConvertToPatches(const Vector &Nodes)
int SetLoopDirection(int dir)
KnotVector * DegreeElevate(int t) const