MFEM v2.0
|
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at 00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights 00003 // reserved. See file COPYRIGHT for details. 00004 // 00005 // This file is part of the MFEM library. For more information and source code 00006 // availability see http://mfem.googlecode.com. 00007 // 00008 // MFEM is free software; you can redistribute it and/or modify it under the 00009 // terms of the GNU Lesser General Public License (as published by the Free 00010 // Software Foundation) version 2.1 dated February 1999. 00011 00012 #ifndef MFEM_NURBS 00013 #define MFEM_NURBS 00014 00015 class KnotVector 00016 { 00017 protected: 00018 static const int MaxOrder; 00019 00020 Vector knot; 00021 int Order, NumOfControlPoints, NumOfElements; 00022 00023 public: 00025 KnotVector() { } 00026 KnotVector(istream &input); 00027 KnotVector(int Order_, int NCP); 00028 KnotVector(const KnotVector &kv){ (*this) = kv; } 00029 00030 KnotVector &operator=(const KnotVector &kv); 00031 00032 int GetNE() const { return NumOfElements; } 00033 int GetNKS() const { return NumOfControlPoints - Order; } 00034 int GetNCP() const { return NumOfControlPoints; } 00035 int GetOrder() const { return Order; } 00036 int Size() const { return knot.Size(); } 00037 00039 void GetElements(); 00040 00041 bool isElement(int i) const { return (knot(Order+i) != knot(Order+i+1)); } 00042 00043 double getKnotLocation(double xi, int ni) const 00044 { return (xi*knot(ni+1) + (1. - xi)*knot(ni)); } 00045 00046 int findKnotSpan(double u) const; 00047 00048 void CalcShape (Vector &shape, int i, double xi); 00049 void CalcDShape(Vector &grad, int i, double xi); 00050 00051 void Difference(const KnotVector &kv, Vector &diff) const; 00052 void UniformRefinement(Vector &newknots) const; 00055 KnotVector *DegreeElevate(int t) const; 00056 00057 void Flip(); 00058 00059 void Print(ostream &out) const; 00060 00062 ~KnotVector() { } 00063 00064 double &operator[](int i) { return knot(i); } 00065 const double &operator[](int i) const { return knot(i); } 00066 }; 00067 00068 00069 class NURBSPatch 00070 { 00071 protected: 00072 int ni, nj, nk, Dim; 00073 double *data; 00074 00075 Array<KnotVector *> kv; 00076 00077 int sd, nd; 00078 00079 void swap(NURBSPatch *np); 00080 00081 // Special B-NET acces functions 00082 int SetLoopDirection(int dir); 00083 inline double &operator()(int i, int j); 00084 inline const double &operator()(int i, int j) const; 00085 00086 void init(int dim_); 00087 00088 NURBSPatch(NURBSPatch *parent, int dir, int Order, int NCP); 00089 00090 public: 00091 NURBSPatch(istream &input); 00092 NURBSPatch(KnotVector *kv0, KnotVector *kv1, int dim_); 00093 NURBSPatch(KnotVector *kv0, KnotVector *kv1, KnotVector *kv2, int dim_); 00094 NURBSPatch(Array<KnotVector *> &kv, int dim_); 00095 00096 ~NURBSPatch(); 00097 00098 void Print(ostream &out); 00099 00100 void DegreeElevate(int dir, int t); 00101 void KnotInsert (int dir, const KnotVector &knot); 00102 void KnotInsert (int dir, const Vector &knot); 00103 00104 void KnotInsert(Array<KnotVector *> &knot); 00105 void DegreeElevate(int t); 00106 void UniformRefinement(); 00107 00108 KnotVector *GetKV(int i) { return kv[i]; } 00109 00110 // Standard B-NET acces functions 00111 inline double &operator()(int i, int j, int l); 00112 inline const double &operator()(int i, int j, int l) const; 00113 00114 inline double &operator()(int i, int j, int k, int l); 00115 inline const double &operator()(int i, int j, int k, int l) const; 00116 00117 static void Get3DRotationMatrix(double n[], double angle, double r, 00118 DenseMatrix &T); 00119 void FlipDirection(int dir); 00120 void SwapDirections(int dir1, int dir2); 00121 void Rotate3D(double normal[], double angle); 00122 int MakeUniformDegree(); 00123 friend NURBSPatch *Interpolate(NURBSPatch &p1, NURBSPatch &p2); 00124 friend NURBSPatch *Revolve3D(NURBSPatch &patch, double n[], double ang, 00125 int times); 00126 }; 00127 00128 00129 #ifdef MFEM_USE_MPI 00130 class ParNURBSExtension; 00131 #endif 00132 00133 class NURBSPatchMap; 00134 00135 00136 class NURBSExtension 00137 { 00138 #ifdef MFEM_USE_MPI 00139 friend class ParNURBSExtension; 00140 #endif 00141 friend class NURBSPatchMap; 00142 00143 protected: 00144 int Order; 00145 int NumOfKnotVectors; 00146 // global entity counts 00147 int NumOfVertices, NumOfElements, NumOfBdrElements, NumOfDofs; 00148 // local entity counts 00149 int NumOfActiveVertices, NumOfActiveElems, NumOfActiveBdrElems; 00150 int NumOfActiveDofs; 00151 00152 Array<int> activeVert; // activeVert[glob_vert] = loc_vert or -1 00153 Array<bool> activeElem; 00154 Array<bool> activeBdrElem; 00155 Array<int> activeDof; // activeDof[glob_dof] = loc_dof + 1 or 0 00156 00157 Mesh *patchTopo; 00158 int own_topo; 00159 Array<int> edge_to_knot; 00160 Array<KnotVector *> knotVectors; 00161 Vector weights; 00162 00163 // global offsets, meshOffsets == meshVertexOffsets 00164 Array<int> v_meshOffsets; 00165 Array<int> e_meshOffsets; 00166 Array<int> f_meshOffsets; 00167 Array<int> p_meshOffsets; 00168 00169 // global offsets, spaceOffsets == dofOffsets 00170 Array<int> v_spaceOffsets; 00171 Array<int> e_spaceOffsets; 00172 Array<int> f_spaceOffsets; 00173 Array<int> p_spaceOffsets; 00174 00175 Table *el_dof, *bel_dof; 00176 00177 Array<int> el_to_patch; 00178 Array<int> bel_to_patch; 00179 Array2D<int> el_to_IJK; // IJK are "knot-span" indices! 00180 Array2D<int> bel_to_IJK; // they are NOT element indices! 00181 00182 Array<NURBSPatch *> patches; 00183 00184 inline int KnotInd(int edge); 00185 inline KnotVector *KnotVec(int edge); 00186 inline KnotVector *KnotVec(int edge, int oedge, int *okv); 00187 00188 void CheckPatches(); 00189 void CheckBdrPatches(); 00190 00191 void GetPatchKnotVectors (int p, Array<KnotVector *> &kv); 00192 void GetBdrPatchKnotVectors(int p, Array<KnotVector *> &kv); 00193 00194 // also count the global NumOfVertices and the global NumOfDofs 00195 void GenerateOffsets(); 00196 // count the global NumOfElements 00197 void CountElements(); 00198 // count the global NumOfBdrElements 00199 void CountBdrElements(); 00200 00201 // generate the mesh elements 00202 void Get2DElementTopo(Array<Element *> &elements); 00203 void Get3DElementTopo(Array<Element *> &elements); 00204 00205 // generate the boundary mesh elements 00206 void Get2DBdrElementTopo(Array<Element *> &boundary); 00207 void Get3DBdrElementTopo(Array<Element *> &boundary); 00208 00209 00210 // FE space generation functions 00211 00212 // based on activeElem, count NumOfActiveDofs, generate el_dof, 00213 // el_to_patch, el_to_IJK, activeDof map (global-to-local) 00214 void GenerateElementDofTable(); 00215 00216 // generate elem_to_global-dof table for the active elements 00217 // define el_to_patch, el_to_IJK, activeDof (as bool) 00218 void Generate2DElementDofTable(); 00219 void Generate3DElementDofTable(); 00220 00221 // call after GenerateElementDofTable 00222 void GenerateBdrElementDofTable(); 00223 00224 // generate the bdr-elem_to_global-dof table for the active bdr. elements 00225 // define bel_to_patch, bel_to_IJK 00226 void Generate2DBdrElementDofTable(); 00227 void Generate3DBdrElementDofTable(); 00228 00229 // Patch <--> FE translation functions 00230 void GetPatchNets (const Vector &Nodes); 00231 void Get2DPatchNets(const Vector &Nodes); 00232 void Get3DPatchNets(const Vector &Nodes); 00233 00234 void SetSolutionVector (Vector &Nodes); 00235 void Set2DSolutionVector(Vector &Nodes); 00236 void Set3DSolutionVector(Vector &Nodes); 00237 00238 // determine activeVert, NumOfActiveVertices from the activeElem array 00239 void GenerateActiveVertices(); 00240 00241 // determine activeBdrElem, NumOfActiveBdrElems 00242 void GenerateActiveBdrElems(); 00243 00244 void MergeWeights(Mesh *mesh_array[], int num_pieces); 00245 00246 // to be used by ParNURBSExtension constructor(s) 00247 NURBSExtension() { } 00248 00249 public: 00251 NURBSExtension(istream &input); 00254 NURBSExtension(NURBSExtension *parent, int Order); 00256 NURBSExtension(Mesh *mesh_array[], int num_pieces); 00257 00258 void MergeGridFunctions(GridFunction *gf_array[], int num_pieces, 00259 GridFunction &merged); 00260 00262 virtual ~NURBSExtension(); 00263 00264 // Print functions 00265 void Print(ostream &out) const; 00266 void PrintCharacteristics(ostream &out); 00267 00268 // Meta data functions 00269 int Dimension() { return patchTopo->Dimension(); } 00270 int GetNP() { return patchTopo->GetNE(); } 00271 int GetNBP() { return patchTopo->GetNBE(); } 00272 int GetOrder() { return Order; } 00273 int GetNKV() { return NumOfKnotVectors; } 00274 00275 int GetGNV() { return NumOfVertices; } 00276 int GetNV() { return NumOfActiveVertices; } 00277 int GetGNE() { return NumOfElements; } 00278 int GetNE() { return NumOfActiveElems; } 00279 int GetGNBE() { return NumOfBdrElements; } 00280 int GetNBE() { return NumOfActiveBdrElems; } 00281 00282 int GetNTotalDof() { return NumOfDofs; } 00283 int GetNDof() { return NumOfActiveDofs; } 00284 00285 // Knotvector acces function 00286 const KnotVector *GetKnotVector(int i) const { return knotVectors[i]; } 00287 00288 // Mesh generation functions 00289 void GetElementTopo (Array<Element *> &elements); 00290 void GetBdrElementTopo(Array<Element *> &boundary); 00291 00292 bool HavePatches() { return (patches.Size() != 0); } 00293 00294 Table *GetElementDofTable() { return el_dof; } 00295 Table *GetBdrElementDofTable() { return bel_dof; } 00296 00297 void GetVertexLocalToGlobal(Array<int> &lvert_vert); 00298 void GetElementLocalToGlobal(Array<int> &lelem_elem); 00299 00300 // Load functions 00301 void LoadFE(int i, const FiniteElement *FE); 00302 void LoadBE(int i, const FiniteElement *BE); 00303 00304 const Vector &GetWeights() const { return weights; } 00305 Vector &GetWeights() { return weights; } 00306 00307 // Translation functions: from FE coordinates into to IJK patch 00308 // format and vice versa 00309 void ConvertToPatches(const Vector &Nodes); 00310 void SetKnotsFromPatches(); 00311 void SetCoordsFromPatches(Vector &Nodes); 00312 00313 // Refinement methods 00314 void DegreeElevate(int t); 00315 void UniformRefinement(); 00316 void KnotInsert(Array<KnotVector *> &kv); 00317 }; 00318 00319 00320 #ifdef MFEM_USE_MPI 00321 class ParNURBSExtension : public NURBSExtension 00322 { 00323 private: 00324 int *partitioning; 00325 00326 Table *GetGlobalElementDofTable(); 00327 Table *Get2DGlobalElementDofTable(); 00328 Table *Get3DGlobalElementDofTable(); 00329 00330 void SetActive(int *partitioning, const Array<bool> &active_bel); 00331 void BuildGroups(int *partitioning, const Table &elem_dof); 00332 00333 public: 00334 GroupTopology gtopo; 00335 00336 Array<int> ldof_group; 00337 00338 ParNURBSExtension(MPI_Comm comm, NURBSExtension *parent, int *partitioning, 00339 const Array<bool> &active_bel); 00340 00341 // create a parallel version of 'parent' with partitioning as in 00342 // 'par_parent'; the 'parent' object is destroyed 00343 ParNURBSExtension(NURBSExtension *parent, ParNURBSExtension *par_parent); 00344 00345 virtual ~ParNURBSExtension() { delete [] partitioning; } 00346 }; 00347 #endif 00348 00349 00350 class NURBSPatchMap 00351 { 00352 private: 00353 NURBSExtension *Ext; 00354 00355 int I, J, K, pOffset, opatch; 00356 Array<int> verts, edges, faces, oedge, oface; 00357 00358 inline static int F(const int n, const int N) 00359 { return (n < 0) ? 0 : ((n >= N) ? 2 : 1); } 00360 00361 inline static int Or1D(const int n, const int N, const int Or) 00362 { return (Or > 0) ? n : (N - 1 - n); } 00363 00364 inline static int Or2D(const int n1, const int n2, 00365 const int N1, const int N2, const int Or); 00366 00367 // also set verts, edges, faces, orientations etc 00368 void GetPatchKnotVectors (int p, KnotVector *kv[]); 00369 void GetBdrPatchKnotVectors(int p, KnotVector *kv[], int *okv); 00370 00371 public: 00372 NURBSPatchMap(NURBSExtension *ext) { Ext = ext; } 00373 00374 int nx() { return I + 1; } 00375 int ny() { return J + 1; } 00376 int nz() { return K + 1; } 00377 00378 void SetPatchVertexMap(int p, KnotVector *kv[]); 00379 void SetPatchDofMap (int p, KnotVector *kv[]); 00380 00381 void SetBdrPatchVertexMap(int p, KnotVector *kv[], int *okv); 00382 void SetBdrPatchDofMap (int p, KnotVector *kv[], int *okv); 00383 00384 inline int operator()(const int i) const; 00385 inline int operator[](const int i) const { return (*this)(i); } 00386 00387 inline int operator()(const int i, const int j) const; 00388 00389 inline int operator()(const int i, const int j, const int k) const; 00390 }; 00391 00392 00393 // Inline function implementations 00394 00395 inline double &NURBSPatch::operator()(int i, int j) 00396 { 00397 return data[j%sd + sd*(i + (j/sd)*nd)]; 00398 } 00399 00400 inline const double &NURBSPatch::operator()(int i, int j) const 00401 { 00402 return data[j%sd + sd*(i + (j/sd)*nd)]; 00403 } 00404 00405 inline double &NURBSPatch::operator()(int i, int j, int l) 00406 { 00407 #ifdef MFEM_DEBUG 00408 if (data == 0 || i < 0 || i >= ni || j < 0 || j >= nj || nk > 0 || 00409 l < 0 || l >= Dim) 00410 mfem_error("NURBSPatch::operator() 2D"); 00411 #endif 00412 00413 return data[(i+j*ni)*Dim+l]; 00414 } 00415 00416 inline const double &NURBSPatch::operator()(int i, int j, int l) const 00417 { 00418 #ifdef MFEM_DEBUG 00419 if (data == 0 || i < 0 || i >= ni || j < 0 || j >= nj || nk > 0 || 00420 l < 0 || l >= Dim) 00421 mfem_error("NURBSPatch::operator() const 2D"); 00422 #endif 00423 00424 return data[(i+j*ni)*Dim+l]; 00425 } 00426 00427 inline double &NURBSPatch::operator()(int i, int j, int k, int l) 00428 { 00429 #ifdef MFEM_DEBUG 00430 if (data == 0 || i < 0 || i >= ni || j < 0 || j >= nj || k < 0 || 00431 k >= nk || l < 0 || l >= Dim) 00432 mfem_error("NURBSPatch::operator() 3D"); 00433 #endif 00434 00435 return data[(i+(j+k*nj)*ni)*Dim+l]; 00436 } 00437 00438 inline const double &NURBSPatch::operator()(int i, int j, int k, int l) const 00439 { 00440 #ifdef MFEM_DEBUG 00441 if (data == 0 || i < 0 || i >= ni || j < 0 || j >= nj || k < 0 || 00442 k >= nk || l < 0 || l >= Dim) 00443 mfem_error("NURBSPatch::operator() const 3D"); 00444 #endif 00445 00446 return data[(i+(j+k*nj)*ni)*Dim+l]; 00447 } 00448 00449 00450 inline int NURBSExtension::KnotInd(int edge) 00451 { 00452 int kv = edge_to_knot[edge]; 00453 return (kv >= 0) ? kv : (-1-kv); 00454 } 00455 00456 inline KnotVector *NURBSExtension::KnotVec(int edge) 00457 { 00458 return knotVectors[KnotInd(edge)]; 00459 } 00460 00461 inline KnotVector *NURBSExtension::KnotVec(int edge, int oedge, int *okv) 00462 { 00463 int kv = edge_to_knot[edge]; 00464 if (kv >= 0) 00465 { 00466 *okv = oedge; 00467 return knotVectors[kv]; 00468 } 00469 else 00470 { 00471 *okv = -oedge; 00472 return knotVectors[-1-kv]; 00473 } 00474 } 00475 00476 00477 inline int NURBSPatchMap::Or2D(const int n1, const int n2, 00478 const int N1, const int N2, const int Or) 00479 { 00480 // Needs testing 00481 switch (Or) 00482 { 00483 case 0: return n1 + n2*N1; 00484 case 1: return n2 + n1*N2; 00485 case 2: return n2 + (N1 - 1 - n1)*N2; 00486 case 3: return (N1 - 1 - n1) + n2*N1; 00487 case 4: return (N1 - 1 - n1) + (N2 - 1 - n2)*N1; 00488 case 5: return (N2 - 1 - n2) + (N1 - 1 - n1)*N2; 00489 case 6: return (N2 - 1 - n2) + n1*N2; 00490 case 7: return n1 + (N2 - 1 - n2)*N1; 00491 } 00492 #ifdef MFEM_DEBUG 00493 mfem_error("NURBSPatchMap::Or2D"); 00494 #endif 00495 return -1; 00496 } 00497 00498 inline int NURBSPatchMap::operator()(const int i) const 00499 { 00500 int i1 = i - 1; 00501 switch (F(i1, I)) 00502 { 00503 case 0: return verts[0]; 00504 case 1: return pOffset + Or1D(i1, I, opatch); 00505 case 2: return verts[1]; 00506 } 00507 #ifdef MFEM_DEBUG 00508 mfem_error("NURBSPatchMap::operator() const 1D"); 00509 #endif 00510 return -1; 00511 } 00512 00513 inline int NURBSPatchMap::operator()(const int i, const int j) const 00514 { 00515 int i1 = i - 1, j1 = j - 1; 00516 switch (3*F(j1, J) + F(i1, I)) 00517 { 00518 case 0: return verts[0]; 00519 case 1: return edges[0] + Or1D(i1, I, oedge[0]); 00520 case 2: return verts[1]; 00521 case 3: return edges[3] + Or1D(j1, J, -oedge[3]); 00522 case 4: return pOffset + Or2D(i1, j1, I, J, opatch); 00523 case 5: return edges[1] + Or1D(j1, J, oedge[1]); 00524 case 6: return verts[3]; 00525 case 7: return edges[2] + Or1D(i1, I, -oedge[2]); 00526 case 8: return verts[2]; 00527 } 00528 #ifdef MFEM_DEBUG 00529 mfem_error("NURBSPatchMap::operator() const 2D"); 00530 #endif 00531 return -1; 00532 } 00533 00534 inline int NURBSPatchMap::operator()(const int i, const int j, const int k) 00535 const 00536 { 00537 // Needs testing 00538 int i1 = i - 1, j1 = j - 1, k1 = k - 1; 00539 switch (3*(3*F(k1, K) + F(j1, J)) + F(i1, I)) 00540 { 00541 case 0: return verts[0]; 00542 case 1: return edges[0] + Or1D(i1, I, oedge[0]); 00543 case 2: return verts[1]; 00544 case 3: return edges[3] + Or1D(j1, J, oedge[3]); 00545 case 4: return faces[0] + Or2D(i1, J - 1 - j1, I, J, oface[0]); 00546 case 5: return edges[1] + Or1D(j1, J, oedge[1]); 00547 case 6: return verts[3]; 00548 case 7: return edges[2] + Or1D(i1, I, oedge[2]); 00549 case 8: return verts[2]; 00550 case 9: return edges[8] + Or1D(k1, K, oedge[8]); 00551 case 10: return faces[1] + Or2D(i1, k1, I, K, oface[1]); 00552 case 11: return edges[9] + Or1D(k1, K, oedge[9]); 00553 case 12: return faces[4] + Or2D(J - 1 - j1, k1, J, K, oface[4]); 00554 case 13: return pOffset + I*(J*k1 + j1) + i1; 00555 case 14: return faces[2] + Or2D(j1, k1, J, K, oface[2]); 00556 case 15: return edges[11] + Or1D(k1, K, oedge[11]); 00557 case 16: return faces[3] + Or2D(I - 1 - i1, k1, I, K, oface[3]); 00558 case 17: return edges[10] + Or1D(k1, K, oedge[10]); 00559 case 18: return verts[4]; 00560 case 19: return edges[4] + Or1D(i1, I, oedge[4]); 00561 case 20: return verts[5]; 00562 case 21: return edges[7] + Or1D(j1, J, oedge[7]); 00563 case 22: return faces[5] + Or2D(i1, j1, I, J, oface[5]); 00564 case 23: return edges[5] + Or1D(j1, J, oedge[5]); 00565 case 24: return verts[7]; 00566 case 25: return edges[6] + Or1D(i1, I, oedge[6]); 00567 case 26: return verts[6]; 00568 } 00569 #ifdef MFEM_DEBUG 00570 mfem_error("NURBSPatchMap::operator() const 3D"); 00571 #endif 00572 return -1; 00573 } 00574 00575 #endif