1 /* *****************************************************************
2     MESQUITE -- The Mesh Quality Improvement Toolkit
3 
4     Copyright 2004 Sandia Corporation and Argonne National
5     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
6     with Sandia Corporation, the U.S. Government retains certain
7     rights in this software.
8 
9     This library is free software; you can redistribute it and/or
10     modify it under the terms of the GNU Lesser General Public
11     License as published by the Free Software Foundation; either
12     version 2.1 of the License, or (at your option) any later version.
13 
14     This library is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17     Lesser General Public License for more details.
18 
19     You should have received a copy of the GNU Lesser General Public License
20     (lgpl.txt) along with this library; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 
23     diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
24     pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov
25 
26   ***************************************************************** */
27 //
28 //    AUTHOR: Thomas Leurent <tleurent@mcs.anl.gov>
29 //       ORG: Argonne National Laboratory
30 //    E-MAIL: tleurent@mcs.anl.gov
31 //
32 // ORIG-DATE: 12-Nov-02 at 18:05:56
33 //  LAST-MOD:  9-Jun-04 at 14:43:39 by Thomas Leurent
34 //
35 // DESCRIPTION:
36 // ============
37 /*! \file PatchDataInstances.hpp
38 
39 This header file contains some functions to instantiates particular PatchData Objects.
40 Those objects can be used in unit tests.
41 Patches must be allocated and dealocated by the caller.
42 
43 \author Thomas Leurent
44 \author Michael Brewer
45 
46 */
47 // DESCRIP-END.
48 //
49 
50 #ifndef PatchDataInstances_hpp
51 #define PatchDataInstances_hpp
52 
53 #include "MsqVertex.hpp"
54 #include "PatchData.hpp"
55 #include "PlanarDomain.hpp"
56 #include "IdealElements.hpp"
57 #include "TopologyInfo.hpp"
58 
59 #include <math.h>
60 #include <iostream>
61 
62 #include "cppunit/extensions/HelperMacros.h"
63 
64 namespace MBMesquite
65 {
66   //! must be called in sync with create_...._patch_with_domain
destroy_patch_with_domain(PatchData & pd)67   inline void destroy_patch_with_domain(PatchData &pd)
68   {
69     MeshDomain* domain = pd.get_domain();
70     pd.set_domain( 0 );
71     delete domain;
72 
73     //Mesh* mesh = pd.get_mesh();
74     //pd.set_mesh( 0 );
75     //delete mesh;
76   }
77 
move_vertex(PatchData & pd,const Vector3D & position,const Vector3D & delta,MsqError & err)78   inline void move_vertex( PatchData& pd,
79                            const Vector3D& position,
80                            const Vector3D& delta,
81                            MsqError& err )
82   {
83     const MsqVertex* array = pd.get_vertex_array( err );
84     if (err) return;
85 
86     int idx = 0, cnt = 0;
87     for (size_t i = 0; i < pd.num_nodes(); ++i)
88       if ((array[i] - position).length_squared() < DBL_EPSILON)
89         { idx = i; ++cnt; }
90 
91     CPPUNIT_ASSERT_EQUAL( cnt, 1 );
92 
93     pd.move_vertex( delta, idx, err );
94   }
95 
96 
97   /*! creates a patch containing one ideal hexahedra
98   */
create_one_hex_patch(PatchData & one_hex_patch,MsqError & err)99    inline void create_one_hex_patch(PatchData &one_hex_patch, MsqError &err)
100    {
101      double coords[] = { 1.0, 1.0, 1.0,
102                          2.0, 1.0, 1.0,
103                          2.0, 2.0, 1.0,
104                          1.0, 2.0, 1.0,
105                          1.0, 1.0, 2.0,
106                          2.0, 1.0, 2.0,
107                          2.0, 2.0, 2.0,
108                          1.0, 2.0, 2.0 };
109 
110      size_t indices[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
111 
112      one_hex_patch.fill( 8, coords, 1, HEXAHEDRON, indices, 0, err );
113    }
114 
115 
116    //! creates a Patch containing an ideal tetrahedra
create_one_tet_patch(PatchData & one_tet_patch,MsqError & err)117    inline void create_one_tet_patch(PatchData &one_tet_patch, MsqError &err)
118    {
119      double coords[] = { 1.0, 1.0, 1.0,
120                          2.0, 1.0, 1.0,
121                          1.5, 1+sqrt(3.0)/2.0, 1.0,
122                          1.5, 1+sqrt(3.0)/6.0, 1+sqrt(2.0)/sqrt(3.0) };
123 
124      size_t indices[4] = { 0, 1, 2, 3 };
125 
126      one_tet_patch.fill( 4, coords, 1, TETRAHEDRON, indices, 0, err );
127    }
128 
129    //! create patch containing one ideal pyramid
create_one_pyr_patch(PatchData & one_pyr_patch,MsqError & err)130    inline void create_one_pyr_patch( PatchData& one_pyr_patch, MsqError& err )
131    {
132      /* Equilateral triangles
133      double coords[] = { 1, -1, 0,
134                          1,  1, 0,
135                         -1,  1, 0,
136                         -1, -1, 0,
137                          0,  0, sqrt(2) };
138      */
139      /* Unit height */
140      double coords[] = { 1, -1, 0,
141                          1,  1, 0,
142                         -1,  1, 0,
143                         -1, -1, 0,
144                          0,  0, 2 };
145 
146      size_t indices[5] = { 0, 1, 2, 3, 4 };
147 
148      one_pyr_patch.fill( 5, coords, 1, PYRAMID, indices, 0, err );
149    }
150 
151    //! create patch containing one ideal wedge
create_one_wdg_patch(PatchData & one_wdg_patch,MsqError & err)152    inline void create_one_wdg_patch( PatchData& one_wdg_patch, MsqError& err )
153    {
154      double hgt = 0.5 * MSQ_SQRT_THREE;
155      double coords[] = { 0.0, 0.0, 0.0,
156                          1.0, 0.0, 0.0,
157                          0.5, hgt, 0.0,
158                          0.0, 0.0, 1.0,
159                          1.0, 0.0, 1.0,
160                          0.5, hgt, 1.0 };
161 
162      size_t indices[6] = { 0, 1, 2, 3, 4, 5 };
163 
164      one_wdg_patch.fill( 6, coords, 1, PRISM, indices, 0, err );
165    }
166 
167       //! creates a Patch containing an ideal tetrahedra, inverted
create_one_inverted_tet_patch(PatchData & one_tet_patch,MsqError & err)168    inline void create_one_inverted_tet_patch(PatchData &one_tet_patch,
169                                              MsqError &err)
170    {
171      double coords[] = { 1, 1, 1,
172                          2, 1, 1,
173                          1.5, 1+sqrt(3.0)/2.0, 1,
174                          1.5, 1+sqrt(3.0)/6.0, 1-sqrt(2.0)/sqrt(3.0), };
175 
176      size_t indices[4] = { 0, 1, 2, 3 };
177 
178      one_tet_patch.fill( 4, coords, 1, TETRAHEDRON, indices, 0, err );
179    }
180 
181    //! creates a Patch containing an ideal quadrilateral
create_one_quad_patch(PatchData & one_qua_patch,MsqError & err)182    inline void create_one_quad_patch(PatchData &one_qua_patch, MsqError &err)
183    {
184      double coords[] = { 1, 1, 1,
185                          2, 1, 1,
186                          2, 2, 1,
187                          1, 2 , 1 };
188 
189      size_t indices[4] = { 0, 1, 2, 3 };
190 
191      one_qua_patch.fill( 4, coords, 1, QUADRILATERAL, indices, 0, err );
192    }
193 
194 
195      /*! \fn create_one_tri_patch(PatchData &one_tri_patch, MsqError &err)
196             2
197            / \      creates a Patch containing an ideal triangle
198           /   \
199          0-----1
200          This Patch also has the normal information.
201      */
create_one_tri_patch(PatchData & one_tri_patch,MsqError & err)202    inline void create_one_tri_patch(PatchData &one_tri_patch, MsqError &err)
203    {
204        /* ************** Creates normal info ******************* */
205      Vector3D pnt(0,0,0);
206      Vector3D s_norm(0,0,3);
207      one_tri_patch.set_domain( new PlanarDomain( s_norm, pnt ) );
208 
209        /* *********************FILL tri************************* */
210      double coords[] = { 1, 1, 1,
211                          2, 1, 1,
212                          1.5, 1+sqrt(3.0)/2.0, 1 };
213 
214      size_t indices[3] = { 0, 1, 2 };
215      one_tri_patch.fill( 3, coords, 1, TRIANGLE, indices, 0, err );
216    }
217 
218 
219    /*! \fn create_two_tri_patch(PatchData &one_tri_patch, MsqError &err)
220             2
221            / \      creates a Patch containing two ideal triangles
222           / 0 \
223          0-----1
224           \ 1 /
225            \ /
226             3
227          This Patch also has the normal information.
228    */
create_two_tri_patch(PatchData & pd,MsqError & err)229    inline void create_two_tri_patch(PatchData &pd, MsqError &err)
230    {
231        /* ************** Creates normal info ******************* */
232      Vector3D pnt(0,0,1);
233      Vector3D s_norm(0,0,3);
234      pd.set_domain( new PlanarDomain(s_norm, pnt) );
235 
236        // **********************FILL tri*************************
237 
238      double coords[] = { 1, 1, 1,
239                          2, 1, 1,
240                          1.5, 1+sqrt(3.0)/2.0, 1,
241                          1.5, 1-sqrt(3.0)/2.0, 1 };
242 
243      size_t indices[] = { 0, 1, 2, 0, 3, 1 };
244 
245      pd.fill( 4, coords, 2, TRIANGLE, indices, 0, err );
246   }
247 
248 
249    /*! \fn create_four_quads_patch(PatchData &four_quads, MsqError &err)
250      our 2D set up: 4 quads, center vertex outcentered by (0,-0.5)
251       7____6____5
252       |    |    |
253       | 2  |  3 |
254       8-_  |  _-4       vertex 1 is at (0,0)
255       |  -_0_-  |       vertex 5 is at (2,2)
256       | 0  |  1 |
257       1----2----3
258    */
create_four_quads_patch(PatchData & four_quads,MsqError & err)259    inline void create_four_quads_patch(PatchData &four_quads, MsqError &err)
260    {
261      double coords[] = { 1, .5, 0,
262                          0, 0, 0,
263                          1, 0, 0,
264                          2, 0, 0,
265                          2, 1, 0,
266                          2, 2, 0,
267                          1, 2, 0,
268                          0, 2, 0,
269                          0, 1, 0 };
270 
271      size_t indices[] = { 1, 2, 0, 8,
272                           2, 3, 4, 0,
273                           8, 0, 6, 7,
274                           0, 4, 5, 6 };
275 
276 
277      four_quads.fill( 9, coords, 4, QUADRILATERAL, indices, 0, err );
278    }
279 
280 
281    /*! \fn create_six_quads_patch(PatchData &four_quads, MsqError &err)
282      our 2D set up: 6 quads, 1 center vertex outcentered by (0,-0.5), the other centered
283       7____6____5___11
284       |    |    |    |
285       | 2  |  3 | 5  |
286       8-_  |  _-4---10       vertex 1 is at (0,0)
287       |  -_0_-  |    |       vertex 11 is at (3,2)
288       | 0  |  1 | 4  |
289       1----2----3----9
290 
291       use destroy_patch_with_domain() in sync.
292    */
create_six_quads_patch_with_domain(PatchData & pd,MsqError & err)293    inline void create_six_quads_patch_with_domain(PatchData &pd, MsqError &err)
294    {
295      // associates domain
296      Vector3D pnt(0,0,0);
297      Vector3D s_norm(0,0,3);
298      pd.set_domain( new PlanarDomain(s_norm, pnt) );
299 
300      double coords[] = { 1,.5, 0,
301                          0, 0, 0,
302                          1, 0, 0,
303                          2, 0, 0,
304                          2, 1, 0,
305                          2, 2, 0,
306                          1, 2, 0,
307                          0, 2, 0,
308                          0, 1, 0,
309                          3, 0, 0,
310                          3, 1, 0,
311                          3, 2, 0 };
312 
313      size_t indices[] = { 1,  2,  0, 8,
314                           2,  3,  4, 0,
315                           8,  0,  6, 7,
316                           0,  4,  5, 6,
317                           3,  9, 10, 4,
318                           4, 10, 11, 5 };
319 
320      bool fixed[] = { false, true, true, true,
321                       false, true, true, true,
322                       true, true, true, true };
323 
324      pd.fill( 12, coords, 6, QUADRILATERAL, indices, fixed, err );
325    }
326 
327 
328    /*! \fn create_six_quads_patch_inverted_with_domain(PatchData &four_quads, MsqError &err)
329      our 2D set up: 6 quads, 1 center vertex outcentered by (0,-0.5), the other centered
330       7____6____5___11
331       |    |    |    |
332       | 2  |  3 | 5  |
333       8    |    4---10       vertex 1 is at (0,0)
334       |\       /|    |       vertex 11 is at (3,2)
335       |    |    | 4  |
336       1----2----3----9
337          \  /
338           0
339       use destroy_patch_with_domain() in sync.
340    */
create_six_quads_patch_inverted_with_domain(PatchData & pd,MsqError & err)341    inline void create_six_quads_patch_inverted_with_domain(PatchData &pd, MsqError &err)
342    {
343      create_six_quads_patch_with_domain(pd,err); MSQ_CHKERR(err);
344 
345      Vector3D displacement(0,-1.5,0);
346 
347      pd.move_vertex( displacement, 0, err );
348    }
349 
350 
351    /*! \fn create_twelve_hex_patch(PatchData &pd, MsqError &err)
352      3D set up: 12 quads, one center vertex outcentered by (0,-0.5),
353      the other centered. Vertex 1 is at (0,0,-1). Vertex 35 is at (3,2,1).
354 
355       7____6____5___11     19___18____17__23     31___30___29___35
356       |    |    |    |      |    |    |    |      |    |    |    |
357       | 2  |  3 | 5  |      |    |    |    |      | 8  |  9 | 11 |
358       8----0----4---10     20-_  |  _16---22     32---24---28---34
359       |    |    |    |      |  -12_-  |    |      |    |    |    |
360       | 0  |  1 | 4  |      |    |    |    |      | 6  |  7 | 10 |
361       1----2----3----9     13---14---15---21     25---26---27---33
362    */
create_twelve_hex_patch(PatchData & pd,MsqError & err)363    inline void create_twelve_hex_patch(PatchData &pd, MsqError &err)
364    {
365      double coords[] = { 1, 1, -1,
366                          0, 0, -1,
367                          1, 0, -1,
368                          2, 0, -1,
369                          2, 1, -1,
370                          2, 2, -1,
371                          1, 2, -1,
372                          0, 2, -1,
373                          0, 1, -1,
374                          3, 0, -1,
375                          3, 1, -1,
376                          3, 2, -1,
377 
378                          1,.5, 0,
379                          0, 0, 0,
380                          1, 0, 0,
381                          2, 0, 0,
382                          2, 1, 0,
383                          2, 2, 0,
384                          1, 2, 0,
385                          0, 2, 0,
386                          0, 1, 0,
387                          3, 0, 0,
388                          3, 1, 0,
389                          3, 2, 0,
390 
391                          1, 1, 1,
392                          0, 0, 1,
393                          1, 0, 1,
394                          2, 0, 1,
395                          2, 1, 1,
396                          2, 2, 1,
397                          1, 2, 1,
398                          0, 2, 1,
399                          0, 1, 1,
400                          3, 0, 1,
401                          3, 1, 1,
402                          3, 2, 1 };
403 
404      size_t connectivity[] = { 1, 2, 0, 8, 13, 14, 12, 20, // 0
405                                2, 3, 4, 0, 14, 15, 16, 12, // 1
406                                8, 0, 6, 7, 20, 12, 18, 19, // 2
407                                0, 4, 5, 6, 12, 16, 17, 18, // 3
408                                3, 9, 10, 4, 15, 21, 22, 16, // 4
409                                4, 10, 11, 5, 16, 22, 23, 17, // 5
410                                13, 14, 12, 20, 25, 26, 24, 32, // 6
411                                14, 15, 16, 12, 26, 27, 28, 24, // 7
412                                20, 12, 18, 19, 32, 24, 30, 31, // 8
413                                12, 16, 17, 18, 24, 28, 29, 30, // 9
414                                15, 21, 22, 16, 27, 33, 34, 28, // 10
415                                16, 22, 23, 17, 28, 34, 35, 29 }; // 11
416 
417      bool fixed[] = { true,  true,  true,  true,  true,  true,  true,  true,
418                       true,  true,  true,  true,  false, true,  true,  true,
419                       false, true,  true,  true,  true,  true,  true,  true,
420                       true,  true,  true,  true,  true,  true,  true,  true,
421                       true,  true,  true,  true };
422 
423 
424      pd.fill( 36, coords, 12, HEXAHEDRON, connectivity, fixed, err );
425    }
426 
create_twelve_hex_patch_inverted(PatchData & pd,MsqError & err)427    inline void create_twelve_hex_patch_inverted(PatchData &pd, MsqError &err)
428    {
429      create_twelve_hex_patch(pd,err); MSQ_CHKERR(err);
430      move_vertex( pd, Vector3D(2,1,0), Vector3D(0,0,1.5), err ); MSQ_CHKERR(err);
431    }
432 
433 
434    /* Patch used in several quality metric tests.
435       Our triangular patch is made of two tris.  tri_1 is a perfect
436       equilateral (the ideal for most metrics).  tri_2 is an arbitrary
437       triangle.
438       Memory allocated in this function must be deallocated with
439       destroy_patch_with_domain().
440    */
create_qm_two_tri_patch_with_domain(PatchData & triPatch,MsqError & err)441    inline void create_qm_two_tri_patch_with_domain(PatchData &triPatch, MsqError &err)
442    {
443      Vector3D pnt(0,0,0);
444      Vector3D s_norm(0,0,3);
445      triPatch.set_domain( new PlanarDomain(s_norm, pnt) );
446 
447      double coords[] = { 0.0, 0.0, 0.0,
448                          1.0, 0.0, 0.0,
449                          0.5, sqrt(3.0)/2.0, 0.0,
450                          2.0, -4.0, 2.0 };
451 
452 
453      const size_t conn[] = { 0, 1, 2, 0, 3, 1 };
454 
455      triPatch.fill( 4, coords, 2, TRIANGLE, conn, 0, err );
456    }
457 
458      /* Patch used in several quality metric tests.
459        Our quad patch is made of two quads.  quad_1 is a perfect
460        square (the ideal for most metrics).  quad_2 is an arbitrary
461        quad.
462        Memory allocated in this function must be deallocated with
463        destroy_patch_with_domain().
464      */
create_qm_two_quad_patch_with_domain(PatchData & quadPatch,MsqError & err)465    inline void create_qm_two_quad_patch_with_domain(PatchData &quadPatch, MsqError &err)
466    {
467      Vector3D pnt(0,0,0);
468      Vector3D s_norm(0,0,3);
469      quadPatch.set_domain( new PlanarDomain(s_norm, pnt) );
470 
471      double coords[] = { 0.0, 0.0, 0.0,
472                          1.0, 0.0, 0.0,
473                          1.0, 1.0, 0.0,
474                          0.0, 1.0, 0.0,
475                          2.0, -1.0, .5,
476                          1.5, 1.0, 1.0 };
477 
478      const size_t conn[] = { 0, 1, 2, 3, 1, 4, 5, 2 };
479 
480      quadPatch.fill( 6, coords, 2, QUADRILATERAL, conn, 0, err );
481    }
482 
483      /* Patch used in several quality metric tests.
484         Our tet patch is made of two tets.  tet_1 is a perfect
485         equilateral (the ideal for most metrics).  tet_2 is an arbitrary
486         tet.
487      */
create_qm_two_tet_patch(PatchData & tetPatch,MsqError & err)488    inline void create_qm_two_tet_patch(PatchData &tetPatch, MsqError &err)
489    {
490      double coords[] = { 0.0, 0.0, 0.0,
491                          1.0, 0.0, 0.0,
492                          0.5, sqrt(3.0)/2.0, 0.0,
493                          0.5, sqrt(3.0)/6.0, sqrt(2.0)/sqrt(3.0),
494                          2.0, 3.0, -.5 };
495 
496 
497      const size_t conn[] = { 0, 1, 2, 3, 1, 4, 2, 3 };
498 
499      tetPatch.fill( 5, coords, 2, TETRAHEDRON, conn, 0, err );
500    }
501 
502      /* Patch used in several quality metric tests.
503         Our pyr patch is made of two pyramids.  The first is a perfect
504         pyramid (the ideal for most metrics).  The second is an arbitrary
505         pyramid.
506      */
create_qm_two_pyr_patch(PatchData & pyrPatch,MsqError & err)507    inline void create_qm_two_pyr_patch(PatchData &pyrPatch, MsqError &err)
508    {
509      /* Equilateral triangles
510      double coords[] = { 1, -1, 0,
511                          1,  1, 0,
512                         -1,  1, 0,
513                         -1, -1, 0,
514                          0,  0, sqrt(2) };
515      */
516      /* Unit height */
517      double coords[] = {
518                          /* Equilateral triangles */
519                     /*   1, -1, 0,
520                          1,  1, 0,
521                         -1,  1, 0,
522                         -1, -1, 0,
523                          0,  0, sqrt(2)  */
524                          /* Unit height */
525                          1, -1, 0,
526                          1,  1, 0,
527                         -1,  1, 0,
528                         -1, -1, 0,
529                          0,  0, 2,
530                          /* Apex for a squashed pyramid */
531                          0,  0, -1
532                          };
533 
534 
535      const size_t conn[] = { 0, 1, 2, 3, 4,
536                              3, 2, 1, 0, 5 };
537 
538      pyrPatch.fill( 6, coords, 2, PYRAMID, conn, 0, err );
539    }
540 
541      /* Patch used in several quality metric tests.
542         Our prism patch is made of two prisms.  The first is a perfect
543         prism (the ideal for most metrics).  The second is an arbitrary
544         wedge.
545      */
create_qm_two_wdg_patch(PatchData & wdgPatch,MsqError & err)546    inline void create_qm_two_wdg_patch(PatchData &wdgPatch, MsqError &err)
547    {
548      double hgt = 0.5 * MSQ_SQRT_THREE;
549      double coords[] = {  // ideal prism vertices
550                          0.0, 0.0, 0.0,
551                          1.0, 0.0, 0.0,
552                          0.5, hgt, 0.0,
553                          0.0, 0.0, 1.0,
554                          1.0, 0.0, 1.0,
555                          0.5, hgt, 1.0,
556                           // top vertices for stretched wedge
557                          0.5,-3.0, 0.0,
558                          0.5,-4.0, 1.0 };
559 
560      const size_t conn[] = { 0, 1, 2, 3, 4, 5,
561                              1, 0, 6, 4, 3, 7 };
562 
563      wdgPatch.fill( 8, coords, 2, PRISM, conn, 0, err );
564    }
565 
566    /* Patch used in seveal quality metric tests.
567       Our hex patch is made of two hexes.  hex_1 is a perfect
568       unit cube (the ideal for most metrics).  hex_2 is an arbitrary
569       hex.
570    */
create_qm_two_hex_patch(PatchData & hexPatch,MsqError & err)571    inline void create_qm_two_hex_patch(PatchData &hexPatch, MsqError &err)
572    {
573      double coords[] = { 0.0, 0.0, 0.0,
574                          1.0, 0.0, 0.0,
575                          1.0, 1.0, 0.0,
576                          0.0, 1.0, 0.0,
577                          0.0, 0.0, 1.0,
578                          1.0, 0.0, 1.0,
579                          1.0, 1.0, 1.0,
580                          0.0, 1.0, 1.0,
581                          2.0, 0.0, 0.0,
582                          2.0, 1.0, 0.0,
583                          2.0,-1.0, 1.0,
584                          3.0, 2.0, 1.0 };
585 
586      const size_t conn[] = { 0, 1, 2, 3, 4, 5, 6, 7,
587                              1, 8, 9, 2, 5, 10, 11, 6 };
588 
589      hexPatch.fill( 12, coords, 2, HEXAHEDRON, conn, 0, err );
590    }
591 
592    // Create patch containing one ideal element, optionally higher-order.
593    // For 2D elements, will attach appropriate planar domain.
create_ideal_element_patch(PatchData & pd,EntityTopology type,size_t num_nodes,MsqError & err)594    inline void create_ideal_element_patch( PatchData& pd,
595                                            EntityTopology type,
596                                            size_t num_nodes,
597                                            MsqError& err )
598    {
599       static PlanarDomain zplane(PlanarDomain::XY);
600       static Settings settings;
601       settings.set_slaved_ho_node_mode( Settings::SLAVE_NONE );
602       pd.attach_settings( &settings );
603 
604 
605         // build list of vertex coordinates
606       const Vector3D* corners = unit_edge_element( type );
607       std::vector<Vector3D> coords( corners, corners+TopologyInfo::corners(type) );
608       bool mids[4] = {false};
609       TopologyInfo::higher_order( type, num_nodes, mids[1], mids[2], mids[3], err );
610       MSQ_ERRRTN(err);
611       std::vector<size_t> conn(coords.size());
612       for (unsigned i = 0; i < coords.size(); ++i)
613         conn[i] = i;
614 
615       for (unsigned dim = 1; dim <= TopologyInfo::dimension(type); ++dim) {
616         if (!mids[dim])
617           continue;
618 
619         int num_side;
620         if (dim == TopologyInfo::dimension(type))
621           num_side = 1;
622         else
623           num_side = TopologyInfo::adjacent( type, dim );
624 
625         for (int s = 0; s < num_side; ++s) {
626           unsigned idx = TopologyInfo::higher_order_from_side( type, num_nodes, dim, s, err );
627           MSQ_ERRRTN(err);
628           conn.push_back(idx);
629 
630           unsigned n;
631           const unsigned* side = TopologyInfo::side_vertices( type, dim, s, n, err );
632           MSQ_ERRRTN(err);
633           Vector3D avg = coords[side[0]];
634           for (unsigned v = 1; v < n; ++v)
635             avg += coords[side[v]];
636           avg *= 1.0/n;
637           coords.push_back(avg);
638         }
639       }
640 
641       bool* fixed = new bool[coords.size()];
642       std::fill( fixed, fixed+coords.size(), false );
643       pd.fill( coords.size(), coords[0].to_array(), 1, &type,
644                &num_nodes, &conn[0], fixed, err );
645       delete [] fixed;
646       MSQ_ERRRTN(err);
647 
648       if (TopologyInfo::dimension(type) == 2)
649         pd.set_domain( &zplane );
650    }
651 
652 } // namespace
653 
654 #endif // PatchDataInstances_hpp
655