/[escript]/trunk/finley/src/Mesh_hex20.c
ViewVC logotype

Contents of /trunk/finley/src/Mesh_hex20.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 788 - (show annotations)
Wed Jul 26 05:12:15 2006 UTC (13 years, 4 months ago) by bcumming
File MIME type: text/plain
File size: 47792 byte(s)
small corrections to code in previous commit, and some header files that
should have been included in the last commit.


1 /*
2 ************************************************************
3 * Copyright 2006 by ACcESS MNRF *
4 * *
5 * http://www.access.edu.au *
6 * Primary Business: Queensland, Australia *
7 * Licensed under the Open Software License version 3.0 *
8 * http://www.opensource.org/licenses/osl-3.0.php *
9 * *
10 ************************************************************
11 */
12
13 /**************************************************************/
14
15 /* Finley: generates rectangular meshes */
16
17 /* Generates a numElements[0] x numElements[1] x numElements[2] mesh with second order elements (Hex20) in the brick */
18 /* [0,Length[0]] x [0,Length[1]] x [0,Length[2]]. order is the desired accuracy of the */
19 /* integration scheme. */
20
21
22 /**************************************************************/
23
24 /* Author: gross@access.edu.au */
25 /* Version: $Id$
26
27 /**************************************************************/
28
29 #include "RectangularMesh.h"
30
31 #ifdef PASO_MPI
32 /* get the number of nodes/elements for domain with rank=rank, of size processors
33 where n is the total number of nodes/elements in the global domain */
34 static index_t domain_MODdim( index_t rank, index_t size, index_t n )
35 {
36 rank = size-rank-1;
37
38 if( rank < n%size )
39 return (index_t)floor(n/size)+1;
40 return (index_t)floor(n/size);
41 }
42
43
44 /* Determines the number of nodes/elements etc along an axis which is numElementsGlobal long for domain rank */
45 /* A bit messy, but it only has to be done once... */
46 static void domain_calculateDimension( index_t rank, dim_t size, dim_t numElementsGlobal, bool_t periodic, dim_t *numNodesLocal, dim_t *numDOFLocal, dim_t *numElementsLocal, dim_t *numElementsInternal, dim_t *firstNode, dim_t *nodesExternal, dim_t *DOFExternal, dim_t *numNodesExternal, bool_t *periodicLocal, dim_t *DOFBoundary )
47 {
48 index_t i0;
49 dim_t numNodesGlobal = numElementsGlobal+1;
50
51 (*numNodesLocal) = 2*domain_MODdim( rank, size, numNodesGlobal ) - 1;
52 if( rank<size-1 ) // add on node for right hand boundary
53 (*numNodesLocal) += 1;
54
55 numElementsLocal[0] = domain_MODdim( rank, size, numNodesGlobal )+1;
56 periodicLocal[0] = periodicLocal[1] = FALSE;
57 nodesExternal[0] = nodesExternal[1] = 1;
58 if( periodic )
59 {
60 if( size==1 )
61 {
62 numElementsLocal[0] = numElementsGlobal;
63 nodesExternal[0] = nodesExternal[1] = 0;
64 periodicLocal[0] = periodicLocal[1] = TRUE;
65 }
66 else
67 {
68 if( rank==0 )
69 {
70 periodicLocal[0] = TRUE;
71 numNodesLocal[0]++;
72 }
73 if( rank==(size-1) )
74 {
75 periodicLocal[1] = TRUE;
76 numNodesLocal[0]--;
77 numElementsLocal[0]--;
78 }
79 }
80 }
81 else if( !periodic )
82 {
83 if( rank==0 ){
84 nodesExternal[0]--;
85 numElementsLocal[0]--;
86 }
87 if( rank==(size-1) )
88 {
89 nodesExternal[1]--;
90 numElementsLocal[0]--;
91 }
92 }
93 nodesExternal[0]*=2;
94 numNodesExternal[0] = nodesExternal[0]+nodesExternal[1];
95
96 numElementsInternal[0] = numElementsLocal[0];
97 if( (rank==0) && (rank==size-1) );
98
99 else if( !periodic && ( (rank==0) ^ (rank==size-1) ) )
100 numElementsInternal[0] -= 1;
101 else
102 numElementsInternal[0] -= 2;
103
104 firstNode[0] = 0;
105 for( i0=0; i0<rank; i0++ )
106 firstNode[0] += domain_MODdim( i0, size, numNodesGlobal );
107 firstNode[0] *= 2;
108
109 numDOFLocal[0] = numNodesLocal[0];
110 if( periodicLocal[0] )
111 numDOFLocal[0]--;
112
113 DOFExternal[0] = nodesExternal[0];
114 DOFExternal[1] = nodesExternal[1];
115
116 if( size>1 )
117 {
118 DOFBoundary[0] = periodicLocal[0]*1 + (rank>0)*1;
119 DOFBoundary[1] = periodicLocal[1]*2 + (rank<(size-1))*2;
120 }
121 else
122 {
123 DOFBoundary[0] = DOFBoundary[1] = 0;
124 }
125 }
126 #endif
127 /**************************************************************/
128 #ifdef PASO_MPI
129 Finley_Mesh* Finley_RectangularMesh_Hex20_singleCPU(dim_t* numElements,double* Length,bool_t* periodic,index_t order,bool_t useElementsOnFace, Paso_MPIInfo *mpi_info) {
130 #else
131 Finley_Mesh* Finley_RectangularMesh_Hex20(dim_t* numElements,double* Length,bool_t* periodic,index_t order,bool_t useElementsOnFace) {
132 #endif
133 dim_t N0,N1,N2,NE0,NE1,NE2,i0,i1,i2,k,totalNECount,faceNECount,NDOF0,NDOF1,NDOF2,NFaceElements,NUMNODES,M0,M1,M2;
134 index_t node0;
135 Finley_Mesh* out;
136 char name[50];
137 double time0=Finley_timer();
138
139 NE0=MAX(1,numElements[0]);
140 NE1=MAX(1,numElements[1]);
141 NE2=MAX(1,numElements[2]);
142 N0=2*NE0+1;
143 N1=2*NE1+1;
144 N2=2*NE2+1;
145
146 if (N0<=MIN(N1,N2)) {
147 if (N1 <= N2) {
148 M0=1;
149 M1=N0;
150 M2=N0*N1;
151 } else {
152 M0=1;
153 M2=N0;
154 M1=N0*N2;
155 }
156 } else if (N1<=MIN(N2,N0)) {
157 if (N2 <= N0) {
158 M1=1;
159 M2=N1;
160 M0=N2*N1;
161 } else {
162 M1=1;
163 M0=N1;
164 M2=N1*N0;
165 }
166 } else {
167 if (N0 <= N1) {
168 M2=1;
169 M0=N2;
170 M1=N2*N0;
171 } else {
172 M2=1;
173 M1=N2;
174 M0=N1*N2;
175 }
176 }
177
178 NFaceElements=0;
179 if (!periodic[0]) {
180 NDOF0=N0;
181 NFaceElements+=2*NE1*NE2;
182 } else {
183 NDOF0=N0-1;
184 }
185 if (!periodic[1]) {
186 NDOF1=N1;
187 NFaceElements+=2*NE0*NE2;
188 } else {
189 NDOF1=N1-1;
190 }
191 if (!periodic[2]) {
192 NDOF2=N2;
193 NFaceElements+=2*NE0*NE1;
194 } else {
195 NDOF2=N2-1;
196 }
197
198 /* allocate mesh: */
199
200 sprintf(name,"Rectangular %d x %d x %d mesh",N0,N1,N2);
201 #ifdef PASO_MPI
202 out=Finley_Mesh_alloc(name,3,order,mpi_info);
203
204 if (! Finley_noError()) return NULL;
205
206 out->Elements=Finley_ElementFile_alloc(Hex20,out->order,mpi_info);
207 if (useElementsOnFace) {
208 out->FaceElements=Finley_ElementFile_alloc(Hex20Face,out->order,mpi_info);
209 out->ContactElements=Finley_ElementFile_alloc(Hex20Face_Contact,out->order,mpi_info);
210 } else {
211 out->FaceElements=Finley_ElementFile_alloc(Rec8,out->order,mpi_info);
212 out->ContactElements=Finley_ElementFile_alloc(Rec8_Contact,out->order,mpi_info);
213 }
214 out->Points=Finley_ElementFile_alloc(Point1,out->order,mpi_info);
215 if (! Finley_noError()) {
216 Finley_Mesh_dealloc(out);
217 return NULL;
218 }
219
220
221 /* allocate tables: */
222 Finley_NodeFile_allocTable(out->Nodes,N0*N1*N2);
223 Finley_ElementFile_allocTable(out->Elements,NE0*NE1*NE2);
224 Finley_ElementFile_allocTable(out->FaceElements,NFaceElements);
225 Finley_NodeDistribution_allocTable( out->Nodes->degreeOfFreedomDistribution, NDOF0*NDOF1*NDOF2, 0, 0 );
226 Finley_ElementDistribution_allocTable( out->Elements->elementDistribution, NE0*NE1*NE2, NE0*NE1*NE2);
227 Finley_ElementDistribution_allocTable( out->FaceElements->elementDistribution, NFaceElements, NFaceElements );
228 #else
229 out=Finley_Mesh_alloc(name,3,order);
230
231 if (! Finley_noError()) return NULL;
232
233 out->Elements=Finley_ElementFile_alloc(Hex20,out->order);
234 if (useElementsOnFace) {
235 out->FaceElements=Finley_ElementFile_alloc(Hex20Face,out->order);
236 out->ContactElements=Finley_ElementFile_alloc(Hex20Face_Contact,out->order);
237 } else {
238 out->FaceElements=Finley_ElementFile_alloc(Rec8,out->order);
239 out->ContactElements=Finley_ElementFile_alloc(Rec8_Contact,out->order);
240 }
241 out->Points=Finley_ElementFile_alloc(Point1,out->order);
242 if (! Finley_noError()) {
243 Finley_Mesh_dealloc(out);
244 return NULL;
245 }
246
247
248 /* allocate tables: */
249 Finley_NodeFile_allocTable(out->Nodes,N0*N1*N2);
250 Finley_ElementFile_allocTable(out->Elements,NE0*NE1*NE2);
251 Finley_ElementFile_allocTable(out->FaceElements,NFaceElements);
252 #endif
253 if (! Finley_noError()) {
254 Finley_Mesh_dealloc(out);
255 return NULL;
256 }
257
258 /* create nodes */
259 #pragma omp parallel for private(i0,i1,i2,k)
260 for (i2=0;i2<N2;i2++) {
261 for (i1=0;i1<N1;i1++) {
262 for (i0=0;i0<N0;i0++) {
263 k=M0*i0+M1*i1+M2*i2;
264 out->Nodes->Coordinates[INDEX2(0,k,3)]=DBLE(i0)/DBLE(N0-1)*Length[0];
265 out->Nodes->Coordinates[INDEX2(1,k,3)]=DBLE(i1)/DBLE(N1-1)*Length[1];
266 out->Nodes->Coordinates[INDEX2(2,k,3)]=DBLE(i2)/DBLE(N2-1)*Length[2];
267 out->Nodes->Id[k]=i0+N0*i1+N0*N1*i2;
268 out->Nodes->Tag[k]=0;
269 out->Nodes->degreeOfFreedom[k]=M0*(i0%NDOF0) +M1*(i1%NDOF1) +M2*(i2%NDOF2);
270 #ifdef PASO_MPI
271 out->Nodes->Dom[k]=NODE_INTERNAL;
272 #endif
273 }
274 }
275 }
276
277
278 /* tags for the faces: */
279 if (!periodic[2]) {
280 for (i1=0;i1<N1;i1++) {
281 for (i0=0;i0<N0;i0++) {
282 out->Nodes->Tag[M0*i0+M1*i1+M2*0]+=100;
283 out->Nodes->Tag[M0*i0+M1*i1+M2*(N2-1)]+=200;
284 }
285 }
286 }
287 if (!periodic[1]) {
288 for (i2=0;i2<N2;i2++) {
289 for (i0=0;i0<N0;i0++) {
290 out->Nodes->Tag[M0*i0+M1*0+M2*i2]+=10;
291 out->Nodes->Tag[M0*i0+M1*(N1-1)+M2*i2]+=20;
292 }
293 }
294 }
295 if (!periodic[0]) {
296 for (i2=0;i2<N2;i2++) {
297 for (i1=0;i1<N1;i1++) {
298 out->Nodes->Tag[M0*0+M1*i1+M2*i2]+=1;
299 out->Nodes->Tag[M0*(N0-1)+M1*i1+M2*i2]+=2;
300 }
301 }
302 }
303
304 /* set the elements: */
305
306 #pragma omp parallel for private(i0,i1,i2,k,node0)
307 for (i2=0;i2<NE2;i2++) {
308 for (i1=0;i1<NE1;i1++) {
309 for (i0=0;i0<NE0;i0++) {
310 k=i0+NE0*i1+NE0*NE1*i2;
311 node0=2*i0+2*i1*N0+2*N0*N1*i2;
312
313 out->Elements->Id[k]=k;
314 out->Elements->Tag[k]=0;
315 out->Elements->Color[k]=COLOR_MOD(i0)+3*COLOR_MOD(i1)+9*COLOR_MOD(i2);
316 #ifdef PASO_MPI
317 out->Elements->Dom[k]=ELEMENT_INTERNAL;
318 #endif
319
320 out->Elements->Nodes[INDEX2(0,k,20)]=node0;
321 out->Elements->Nodes[INDEX2(1,k,20)]=node0+2;
322 out->Elements->Nodes[INDEX2(2,k,20)]=node0+2*N0+2;
323 out->Elements->Nodes[INDEX2(3,k,20)]=node0+2*N0;
324 out->Elements->Nodes[INDEX2(4,k,20)]=node0+2*N0*N1;
325 out->Elements->Nodes[INDEX2(5,k,20)]=node0+2*N0*N1+2;
326 out->Elements->Nodes[INDEX2(6,k,20)]=node0+2*N0*N1+2*N0+2;
327 out->Elements->Nodes[INDEX2(7,k,20)]=node0+2*N0*N1+2*N0;
328 out->Elements->Nodes[INDEX2(8,k,20)]=node0+1;
329 out->Elements->Nodes[INDEX2(9,k,20)]=node0+N0+2;
330 out->Elements->Nodes[INDEX2(10,k,20)]=node0+2*N0+1;
331 out->Elements->Nodes[INDEX2(11,k,20)]=node0+N0;
332 out->Elements->Nodes[INDEX2(12,k,20)]=node0+N0*N1;
333 out->Elements->Nodes[INDEX2(13,k,20)]=node0+N0*N1+2;
334 out->Elements->Nodes[INDEX2(14,k,20)]=node0+N0*N1+2*N0+2;
335 out->Elements->Nodes[INDEX2(15,k,20)]=node0+N0*N1+2*N0;
336 out->Elements->Nodes[INDEX2(16,k,20)]=node0+2*N0*N1+1;
337 out->Elements->Nodes[INDEX2(17,k,20)]=node0+2*N0*N1+N0+2;
338 out->Elements->Nodes[INDEX2(18,k,20)]=node0+2*N0*N1+2*N0+1;
339 out->Elements->Nodes[INDEX2(19,k,20)]=node0+2*N0*N1+N0;
340 }
341 }
342 }
343 out->Elements->minColor=0;
344 out->Elements->maxColor=COLOR_MOD(0)+3*COLOR_MOD(0)+9*COLOR_MOD(0);
345
346 /* face elements: */
347
348 if (useElementsOnFace) {
349 NUMNODES=20;
350 } else {
351 NUMNODES=8;
352 }
353 totalNECount=NE0*NE1*NE2;
354 faceNECount=0;
355
356 /* these are the quadrilateral elements on boundary 1 (x3=0): */
357
358 if (!periodic[2]) {
359 /* ** elements on boundary 100 (x3=0): */
360 #pragma omp parallel for private(i0,i1,k,node0)
361 for (i1=0;i1<NE1;i1++) {
362 for (i0=0;i0<NE0;i0++) {
363 k=i0+NE0*i1+faceNECount;
364 node0=2*i0+2*i1*N0;
365
366 out->FaceElements->Id[k]=i0+NE0*i1+totalNECount;
367 out->FaceElements->Tag[k]=100;
368 out->FaceElements->Color[k]=(i0%2)+2*(i1%2);
369 #ifdef PASO_MPI
370 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
371 #endif
372
373 if (useElementsOnFace) {
374 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0;
375 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0;
376 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0+2;
377 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2;
378 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+2*N0*N1;
379 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0*N1+2*N0;
380 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
381 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N0*N1+2;
382 out->FaceElements->Nodes[INDEX2(8,k,NUMNODES)]=node0+N0;
383 out->FaceElements->Nodes[INDEX2(9,k,NUMNODES)]=node0+2*N0+1;
384 out->FaceElements->Nodes[INDEX2(10,k,NUMNODES)]=node0+N0+2;
385 out->FaceElements->Nodes[INDEX2(11,k,NUMNODES)]=node0+1;
386 out->FaceElements->Nodes[INDEX2(12,k,NUMNODES)]=node0+N0*N1;
387 out->FaceElements->Nodes[INDEX2(13,k,NUMNODES)]=node0+N0*N1+2*N0;
388 out->FaceElements->Nodes[INDEX2(14,k,NUMNODES)]=node0+N0*N1+2*N0+2;
389 out->FaceElements->Nodes[INDEX2(15,k,NUMNODES)]=node0+N0*N1+2;
390 out->FaceElements->Nodes[INDEX2(16,k,NUMNODES)]=node0+2*N0*N1+N0;
391 out->FaceElements->Nodes[INDEX2(17,k,NUMNODES)]=node0+2*N0*N1+2*N0+1;
392 out->FaceElements->Nodes[INDEX2(18,k,NUMNODES)]=node0+2*N0*N1+N0+2;
393 out->FaceElements->Nodes[INDEX2(19,k,NUMNODES)]=node0+2*N0*N1+1;
394 } else {
395 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0;
396 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0;
397 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0+2;
398 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2;
399 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+N0;
400 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0+1;
401 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+N0+2;
402 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+1;
403 }
404 }
405 }
406 totalNECount+=NE1*NE0;
407 faceNECount+=NE1*NE0;
408
409 /* ** elements on boundary 200 (x3=1) */
410 #pragma omp parallel for private(i0,i1,k,node0)
411 for (i1=0;i1<NE1;i1++) {
412 for (i0=0;i0<NE0;i0++) {
413 k=i0+NE0*i1+faceNECount;
414 node0=2*i0+2*i1*N0+2*N0*N1*(NE2-1);
415
416 out->FaceElements->Id[k]=i0+NE0*i1+totalNECount;
417 out->FaceElements->Tag[k]=200;
418 out->FaceElements->Color[k]=(i0%2)+2*(i1%2)+4;
419 #ifdef PASO_MPI
420 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
421 #endif
422
423 if (useElementsOnFace) {
424 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0+2*N0*N1;
425 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0*N1+2;
426 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
427 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0*N1+2*N0;
428
429 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0;
430 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2;
431 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0+2;
432 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N0;
433
434 out->FaceElements->Nodes[INDEX2(8,k,NUMNODES)]=node0+2*N0*N1+1;
435 out->FaceElements->Nodes[INDEX2(9,k,NUMNODES)]=node0+2*N0*N1+N0+2;
436 out->FaceElements->Nodes[INDEX2(10,k,NUMNODES)]=node0+2*N0*N1+2*N0+1;
437 out->FaceElements->Nodes[INDEX2(11,k,NUMNODES)]=node0+2*N0*N1+N0;
438
439 out->FaceElements->Nodes[INDEX2(12,k,NUMNODES)]=node0+N0*N1;
440 out->FaceElements->Nodes[INDEX2(13,k,NUMNODES)]=node0+N0*N1+2;
441 out->FaceElements->Nodes[INDEX2(14,k,NUMNODES)]=node0+N0*N1+2*N0+2;
442 out->FaceElements->Nodes[INDEX2(15,k,NUMNODES)]=node0+N0*N1+2*N0;
443
444 out->FaceElements->Nodes[INDEX2(16,k,NUMNODES)]=node0+1;
445 out->FaceElements->Nodes[INDEX2(17,k,NUMNODES)]=node0+N0+2;
446 out->FaceElements->Nodes[INDEX2(18,k,NUMNODES)]=node0+2*N0+1;
447 out->FaceElements->Nodes[INDEX2(19,k,NUMNODES)]=node0+N0;
448
449 } else {
450 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0+2*N0*N1;
451 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0*N1+2;
452 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
453 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0*N1+2*N0;
454 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+2*N0*N1+1;
455 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0*N1+N0+2;
456 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0*N1+2*N0+1;
457 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N0*N1+N0;
458 }
459 }
460 }
461 totalNECount+=NE1*NE0;
462 faceNECount+=NE1*NE0;
463 }
464 if (!periodic[0]) {
465 /* ** elements on boundary 001 (x1=0): */
466
467 #pragma omp parallel for private(i1,i2,k,node0)
468 for (i2=0;i2<NE2;i2++) {
469 for (i1=0;i1<NE1;i1++) {
470 k=i1+NE1*i2+faceNECount;
471 node0=2*i1*N0+2*N0*N1*i2;
472
473 out->FaceElements->Id[k]=i1+NE1*i2+totalNECount;
474 out->FaceElements->Tag[k]=1;
475 out->FaceElements->Color[k]=(i2%2)+2*(i1%2)+8;
476 #ifdef PASO_MPI
477 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
478 #endif
479
480 if (useElementsOnFace) {
481 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0;
482 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0*N1;
483 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0;
484 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0;
485
486 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+2;
487 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0*N1+2;
488 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
489 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N0+2;
490
491 out->FaceElements->Nodes[INDEX2(8,k,NUMNODES)]=node0+N0*N1;
492 out->FaceElements->Nodes[INDEX2(9,k,NUMNODES)]=node0+2*N0*N1+N0;
493 out->FaceElements->Nodes[INDEX2(10,k,NUMNODES)]=node0+N0*N1+2*N0;
494 out->FaceElements->Nodes[INDEX2(11,k,NUMNODES)]=node0+N0;
495
496 out->FaceElements->Nodes[INDEX2(12,k,NUMNODES)]=node0+1;
497 out->FaceElements->Nodes[INDEX2(13,k,NUMNODES)]=node0+2*N0*N1+1;
498 out->FaceElements->Nodes[INDEX2(14,k,NUMNODES)]=node0+2*N0*N1+2*N0+1;
499 out->FaceElements->Nodes[INDEX2(15,k,NUMNODES)]=node0+2*N0+1;
500
501 out->FaceElements->Nodes[INDEX2(16,k,NUMNODES)]=node0+N0*N1+2;
502 out->FaceElements->Nodes[INDEX2(17,k,NUMNODES)]=node0+2*N0*N1+N0+2;
503 out->FaceElements->Nodes[INDEX2(18,k,NUMNODES)]=node0+N0*N1+2*N0+2;
504 out->FaceElements->Nodes[INDEX2(19,k,NUMNODES)]=node0+N0+2;
505
506 } else {
507 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0;
508 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0*N1;
509 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0;
510 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0;
511 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+N0*N1;
512 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0*N1+N0;
513 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+N0*N1+2*N0;
514 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+N0;
515 }
516 }
517 }
518 totalNECount+=NE1*NE2;
519 faceNECount+=NE1*NE2;
520
521 /* ** elements on boundary 002 (x1=1): */
522
523 #pragma omp parallel for private(i1,i2,k,node0)
524 for (i2=0;i2<NE2;i2++) {
525 for (i1=0;i1<NE1;i1++) {
526 k=i1+NE1*i2+faceNECount;
527 node0=2*(NE0-1)+2*i1*N0+2*N0*N1*i2 ;
528
529 out->FaceElements->Id[k]=i1+NE1*i2+totalNECount;
530 out->FaceElements->Tag[k]=2;
531 out->FaceElements->Color[k]=(i2%2)+2*(i1%2)+12;
532 #ifdef PASO_MPI
533 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
534 #endif
535
536 if (useElementsOnFace) {
537 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0+2;
538 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0+2;
539 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
540 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0*N1+2;
541
542 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0;
543 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0;
544 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0*N1+2*N0;
545 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N0*N1;
546
547 out->FaceElements->Nodes[INDEX2(8,k,NUMNODES)]=node0+N0+2;
548 out->FaceElements->Nodes[INDEX2(9,k,NUMNODES)]=node0+N0*N1+2*N0+2;
549 out->FaceElements->Nodes[INDEX2(10,k,NUMNODES)]=node0+2*N0*N1+N0+2;
550 out->FaceElements->Nodes[INDEX2(11,k,NUMNODES)]=node0+N0*N1+2;
551
552 out->FaceElements->Nodes[INDEX2(12,k,NUMNODES)]=node0+1;
553 out->FaceElements->Nodes[INDEX2(13,k,NUMNODES)]=node0+2*N0+1;
554 out->FaceElements->Nodes[INDEX2(14,k,NUMNODES)]=node0+2*N0*N1+2*N0+1;
555 out->FaceElements->Nodes[INDEX2(15,k,NUMNODES)]=node0+2*N0*N1+1;
556
557 out->FaceElements->Nodes[INDEX2(16,k,NUMNODES)]=node0+N0;
558 out->FaceElements->Nodes[INDEX2(17,k,NUMNODES)]=node0+N0*N1+2*N0;
559 out->FaceElements->Nodes[INDEX2(18,k,NUMNODES)]=node0+2*N0*N1+N0;
560 out->FaceElements->Nodes[INDEX2(19,k,NUMNODES)]=node0+N0*N1;
561
562 } else {
563 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0+2;
564 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0+2;
565 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
566 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0*N1+2;
567 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+N0+2;
568 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+N0*N1+2*N0+2;
569 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0*N1+N0+2;
570 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+N0*N1+2;
571 }
572
573 }
574 }
575 totalNECount+=NE1*NE2;
576 faceNECount+=NE1*NE2;
577 }
578 if (!periodic[1]) {
579 /* ** elements on boundary 010 (x2=0): */
580
581 #pragma omp parallel for private(i0,i2,k,node0)
582 for (i2=0;i2<NE2;i2++) {
583 for (i0=0;i0<NE0;i0++) {
584 k=i0+NE0*i2+faceNECount;
585 node0=2*i0+2*N0*N1*i2;
586
587 out->FaceElements->Id[k]=i2+NE2*i0+totalNECount;
588 out->FaceElements->Tag[k]=10;
589 out->FaceElements->Color[k]=(i2%2)+2*(i0%2)+16;
590 #ifdef PASO_MPI
591 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
592 #endif
593
594 if (useElementsOnFace) {
595 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0;
596 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2;
597 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N1*N0+2;
598 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N1*N0;
599
600 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+2*N0;
601 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0+2;
602 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N1*N0+2*N0+2;
603 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N1*N0+2*N0;
604
605 out->FaceElements->Nodes[INDEX2(8,k,NUMNODES)]=node0+1;
606 out->FaceElements->Nodes[INDEX2(9,k,NUMNODES)]=node0+N0*N1+2;
607 out->FaceElements->Nodes[INDEX2(10,k,NUMNODES)]=node0+2*N1*N0+1;
608 out->FaceElements->Nodes[INDEX2(11,k,NUMNODES)]=node0+N1*N0;
609
610 out->FaceElements->Nodes[INDEX2(12,k,NUMNODES)]=node0+N0;
611 out->FaceElements->Nodes[INDEX2(13,k,NUMNODES)]=node0+N0+2;
612 out->FaceElements->Nodes[INDEX2(14,k,NUMNODES)]=node0+2*N1*N0+N0+2;
613 out->FaceElements->Nodes[INDEX2(15,k,NUMNODES)]=node0+2*N1*N0+N0;
614
615 out->FaceElements->Nodes[INDEX2(16,k,NUMNODES)]=node0+2*N0+1;
616 out->FaceElements->Nodes[INDEX2(17,k,NUMNODES)]=node0+N0*N1+2*N0+2;
617 out->FaceElements->Nodes[INDEX2(18,k,NUMNODES)]=node0+2*N1*N0+2*N0+1;
618 out->FaceElements->Nodes[INDEX2(19,k,NUMNODES)]=node0+N1*N0+2*N0;
619
620 } else {
621 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0;
622 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2;
623 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N1*N0+2;
624 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N1*N0;
625 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+1;
626 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+N0*N1+2;
627 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N1*N0+1;
628 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+N1*N0;
629 }
630 }
631 }
632 totalNECount+=NE0*NE2;
633 faceNECount+=NE0*NE2;
634
635 /* ** elements on boundary 020 (x2=1): */
636
637 #pragma omp parallel for private(i0,i2,k,node0)
638 for (i2=0;i2<NE2;i2++) {
639 for (i0=0;i0<NE0;i0++) {
640 k=i0+NE0*i2+faceNECount;
641 node0=2*i0+2*(NE1-1)*N0+2*N0*N1*i2;
642
643 out->FaceElements->Id[k]=i2+NE2*i0+totalNECount;
644 out->FaceElements->Tag[k]=20;
645 out->FaceElements->Color[k]=(i2%2)+2*(i0%2)+20;
646 #ifdef PASO_MPI
647 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
648 #endif
649
650 if (useElementsOnFace) {
651 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0+2*N0;
652 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0*N1+2*N0;
653 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
654 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0+2;
655
656 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0;
657 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N0*N1;
658 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+2*N0*N1+2;
659 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2;
660
661 out->FaceElements->Nodes[INDEX2(8,k,NUMNODES)]=node0+N1*N0+2*N0;
662 out->FaceElements->Nodes[INDEX2(9,k,NUMNODES)]=node0+2*N1*N0+2*N0+1;
663 out->FaceElements->Nodes[INDEX2(10,k,NUMNODES)]=node0+N0*N1+2*N0+2;
664 out->FaceElements->Nodes[INDEX2(11,k,NUMNODES)]=node0+2*N0+1;
665
666 out->FaceElements->Nodes[INDEX2(12,k,NUMNODES)]=node0+N0;
667 out->FaceElements->Nodes[INDEX2(13,k,NUMNODES)]=node0+2*N0*N1+N0;
668 out->FaceElements->Nodes[INDEX2(14,k,NUMNODES)]=node0+2*N0*N1+N0+2;
669 out->FaceElements->Nodes[INDEX2(15,k,NUMNODES)]=node0+N0+2;
670
671 out->FaceElements->Nodes[INDEX2(16,k,NUMNODES)]=node0+N1*N0;
672 out->FaceElements->Nodes[INDEX2(17,k,NUMNODES)]=node0+2*N1*N0+1;
673 out->FaceElements->Nodes[INDEX2(18,k,NUMNODES)]=node0+N0*N1+2;
674 out->FaceElements->Nodes[INDEX2(19,k,NUMNODES)]=node0+1;
675 } else {
676 out->FaceElements->Nodes[INDEX2(0,k,NUMNODES)]=node0+2*N0;
677 out->FaceElements->Nodes[INDEX2(1,k,NUMNODES)]=node0+2*N0*N1+2*N0;
678 out->FaceElements->Nodes[INDEX2(2,k,NUMNODES)]=node0+2*N0*N1+2*N0+2;
679 out->FaceElements->Nodes[INDEX2(3,k,NUMNODES)]=node0+2*N0+2;
680 out->FaceElements->Nodes[INDEX2(4,k,NUMNODES)]=node0+N1*N0+2*N0;
681 out->FaceElements->Nodes[INDEX2(5,k,NUMNODES)]=node0+2*N1*N0+2*N0+1;
682 out->FaceElements->Nodes[INDEX2(6,k,NUMNODES)]=node0+N0*N1+2*N0+2;
683 out->FaceElements->Nodes[INDEX2(7,k,NUMNODES)]=node0+2*N0+1;
684 }
685 }
686 }
687 totalNECount+=NE0*NE2;
688 faceNECount+=NE0*NE2;
689 }
690 out->FaceElements->minColor=0;
691 out->FaceElements->maxColor=24;
692
693 #ifdef PASO_MPI
694 Finley_ElementFile_setDomainFlags( out->Elements );
695 Finley_ElementFile_setDomainFlags( out->FaceElements );
696 Finley_ElementFile_setDomainFlags( out->ContactElements );
697 Finley_ElementFile_setDomainFlags( out->Points );
698
699 /* reorder the degrees of freedom */
700 Finley_Mesh_resolveDegreeOfFreedomOrder( out, TRUE );
701 #endif
702
703 /* condense the nodes: */
704 Finley_Mesh_resolveNodeIds(out);
705
706 /* prepare mesh for further calculatuions:*/
707 Finley_Mesh_prepare(out) ;
708
709 #ifdef Finley_TRACE
710 printf("timing: mesh generation: %.4e sec\n",Finley_timer()-time0);
711 #endif
712
713 if (! Finley_noError()) {
714 Finley_Mesh_dealloc(out);
715 return NULL;
716 }
717 return out;
718 }
719 #ifdef PASO_MPI
720 Finley_Mesh* Finley_RectangularMesh_Hex20(dim_t* numElements,double* Length,bool_t* periodic,index_t order,bool_t useElementsOnFace) {
721 dim_t N0,N0t,N1,N2,NE0,NE1,NE2,i0,i1,i2,k,totalNECount,faceNECount,NDOF0,NDOF0t,NDOF1,NDOF2,NFaceElements,NUMNODES,M0,M1,M2;
722 dim_t kk,iI, NE0_local, numNodesLocal, numDOFLocal, numElementsLocal, numElementsInternal, nodesExternal[2], DOFExternal[2], numNodesExternal, DOFBoundary[2];
723 bool_t dom_left, dom_right, dom_internal;
724 index_t firstNode=0, DOFcount=0, node0, node1, node2, idCount;
725 index_t targetDomain=-1, firstNodeConstruct, j;
726 bool_t periodicLocal[2], domLeft=FALSE, domRight=FALSE, domInternal=FALSE, boundaryLeft=FALSE, boundaryRight=FALSE;
727 index_t *indexBackward=NULL, *indexForward=NULL,*facePerm=NULL, *forwardDOF=NULL, *backwardDOF=NULL;
728 Finley_Mesh* out;
729 char name[50];
730 double time0=Finley_timer();
731 Paso_MPIInfo *mpi_info = NULL;
732
733 NE0=MAX(1,numElements[0]);
734 NE1=MAX(1,numElements[1]);
735 NE2=MAX(1,numElements[2]);
736 N0=2*NE0+1;
737 N1=2*NE1+1;
738 N2=2*NE2+1;
739
740 index_t face0[] = {0,4,7,3,1,5,6,2,12,19,15,11,8,16,18,10,13,17,14,9};
741 index_t face1[] = {1,2,6,5,0,3,7,4,9,14,17,13,8,10,18,16,11,15,19,12};
742 index_t face2[] = {0,1,5,4,3,2,6,7,8,13,16,12,11,9,17,19,14,18,15,10};
743 index_t face3[] = {3,7,6,2,0,4,5,1,15,18,14,10,11,19,17,9,12,16,13,8};
744 index_t face4[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,19,18,17,16};
745 index_t face5[] = {4,5,6,7,0,1,2,3,16,17,18,19,12,13,14,15,8,9,10,11};
746
747 index_t face0R[] = {0,4,7,3,12,19,15,11};
748 index_t face1R[] = {1,2,6,5,9,14,17,13};
749 index_t face2R[] = {0,1,5,4,8,13,16,12};
750 index_t face3R[] = {3,7,6,2,15,18,14,10};
751 index_t face4R[] = {0,3,2,1,11,10,9,8};
752 index_t face5R[] = {4,5,6,7,16,17,18,19};
753
754 /* get MPI information */
755 mpi_info = Paso_MPIInfo_alloc( MPI_COMM_WORLD );
756 if (! Finley_noError())
757 return NULL;
758
759 /* use the serial version to generate the mesh for the 1-CPU case */
760 if( mpi_info->size==1 )
761 {
762 out = Finley_RectangularMesh_Hex20_singleCPU( numElements, Length, periodic, order, useElementsOnFace, mpi_info);
763 return out;
764 }
765
766 if( mpi_info->rank==0 )
767 domLeft = TRUE;
768 if( mpi_info->rank==mpi_info->size-1 )
769 domRight = TRUE;
770 if( mpi_info->rank>0 && mpi_info->rank<mpi_info->size-1 )
771 domInternal = TRUE;
772
773 /* dimensions of the local subdomain */
774 domain_calculateDimension( mpi_info->rank, mpi_info->size, NE0, periodic[0], &numNodesLocal, &numDOFLocal, &numElementsLocal, &numElementsInternal, &firstNode, nodesExternal, DOFExternal, &numNodesExternal, periodicLocal, DOFBoundary );
775
776 NFaceElements=0;
777 if (!periodic[0]) {
778 NDOF0=N0;
779 NFaceElements+=(domRight+domLeft)*NE1*NE2;
780 } else {
781 NDOF0=N0-1;
782 }
783 if (!periodic[1]) {
784 NDOF1=N1;
785 NFaceElements+=2*numElementsLocal*NE2;
786 } else {
787 NDOF1=N1-1;
788 }
789 if (!periodic[2]) {
790 NDOF2=N2;
791 NFaceElements+=2*numElementsLocal*NE1;
792 } else {
793 NDOF2=N2-1;
794 }
795
796 boundaryLeft = !domLeft || periodicLocal[0];
797 boundaryRight = !domRight || periodicLocal[1];
798 N0t = numNodesLocal + boundaryRight + boundaryLeft*2;
799 NDOF0t = numDOFLocal + boundaryRight + boundaryLeft*2;
800 firstNodeConstruct = firstNode - 2*boundaryLeft;
801 firstNodeConstruct = firstNodeConstruct<0 ? N0+firstNodeConstruct-1 : firstNodeConstruct;
802
803 /* allocate mesh: */
804
805 sprintf(name,"Rectangular %d x %d x %d mesh",N0,N1,N2);
806 out=Finley_Mesh_alloc(name,3,order,mpi_info);
807
808 if (! Finley_noError()) return NULL;
809
810 out->Elements=Finley_ElementFile_alloc(Hex20,out->order,mpi_info);
811 if (useElementsOnFace) {
812 out->FaceElements=Finley_ElementFile_alloc(Hex20Face,out->order,mpi_info);
813 out->ContactElements=Finley_ElementFile_alloc(Hex20Face_Contact,out->order,mpi_info);
814 } else {
815 out->FaceElements=Finley_ElementFile_alloc(Rec8,out->order,mpi_info);
816 out->ContactElements=Finley_ElementFile_alloc(Rec8_Contact,out->order,mpi_info);
817 }
818 out->Points=Finley_ElementFile_alloc(Point1,out->order,mpi_info);
819 if (! Finley_noError()) {
820 Finley_Mesh_dealloc(out);
821 return NULL;
822 }
823
824 /* allocate tables: */
825 Finley_NodeFile_allocTable(out->Nodes,N0t*N1*N2);
826 Finley_ElementFile_allocTable(out->Elements,numElementsLocal*NE1*NE2);
827 Finley_ElementFile_allocTable(out->FaceElements,NFaceElements);
828
829 Finley_NodeDistribution_allocTable( out->Nodes->degreeOfFreedomDistribution, numDOFLocal*NDOF1*NDOF2, NDOF1*NDOF2*3, 0 );
830 Finley_ElementDistribution_allocTable( out->Elements->elementDistribution, numElementsLocal*NE1*NE2, NE1*NE2*(numElementsLocal-boundaryRight*(!periodic[1])) );
831 Finley_ElementDistribution_allocTable( out->FaceElements->elementDistribution, NFaceElements, NFaceElements-2*boundaryRight*(NE2*(!periodic[1])+NE1*(!periodic[2])) );
832 if (! Finley_noError()) {
833 Finley_Mesh_dealloc(out);
834 return NULL;
835 }
836
837 k=0;
838 #pragma omp parallel for private(i0,i1,i2,k)
839 for (i2=0;i2<N2;i2++) {
840 for (i1=0;i1<N1;i1++) {
841 for (i0=0;i0<N0t;i0++,k++) {
842 out->Nodes->Coordinates[INDEX2(0,k,3)]=DBLE((i0+firstNodeConstruct) % N0)/DBLE(N0-1)*Length[0];
843 out->Nodes->Coordinates[INDEX2(1,k,3)]=DBLE(i1)/DBLE(N1-1)*Length[1];
844 out->Nodes->Coordinates[INDEX2(2,k,3)]=DBLE(i2)/DBLE(N2-1)*Length[2];
845 out->Nodes->Id[k]=k;
846 out->Nodes->Tag[k]=0;
847 out->Nodes->degreeOfFreedom[k]=i0 + (i1%NDOF1)*N0t + (i2%NDOF2)*N0t*N1;
848 out->Nodes->Dom[k]=NODE_INTERNAL;
849 }
850 }
851 }
852
853 /* mark the nodes that reference external and boundary DOF as such */
854 if( boundaryLeft ){
855 for( i1=0; i1<N1; i1++ )
856 for( i2=0; i2<N2; i2++ ) {
857 out->Nodes->Dom[N1*N0t*i2+N0t*i1] = NODE_EXTERNAL;
858 out->Nodes->Dom[N1*N0t*i2+N0t*i1+1] = NODE_EXTERNAL;
859 out->Nodes->Dom[N1*N0t*i2+N0t*i1+2] = NODE_BOUNDARY;
860 }
861 }
862 if( boundaryRight ){
863 for( i1=0; i1<N1; i1++ )
864 for( i2=0; i2<N2; i2++ ) {
865 out->Nodes->Dom[N1*N0t*i2+N0t*(i1+1)-1] = NODE_EXTERNAL;
866 out->Nodes->Dom[N1*N0t*i2+N0t*(i1+1)-2] = NODE_BOUNDARY;
867 out->Nodes->Dom[N1*N0t*i2+N0t*(i1+1)-3] = NODE_BOUNDARY;
868 }
869 }
870 if( periodicLocal[0] ){
871 for( i1=0; i1<N1; i1++ )
872 for( i2=0; i2<N2; i2++ ) {
873 out->Nodes->degreeOfFreedom[N1*N0t*i2+i1*N0t+3] = out->Nodes->degreeOfFreedom[i1*N0t+2];
874 out->Nodes->Dom[N1*N0t*i2+N0t*i1+3] = NODE_BOUNDARY;
875 }
876 }
877
878 /* tag Nodes that are referenced by face elements */
879 if (!periodic[2]) {
880 for (i1=0;i1<N1;i1++) {
881 for (i0=0;i0<N0t;i0++) {
882 out->Nodes->Tag[i0 + N0t*i1]+=100;
883 out->Nodes->Tag[i0 + N0t*i1 + N0t*N1*(N2-1)]+=200;
884 }
885 }
886 }
887 if (!periodic[1]) {
888 for (i2=0;i2<N2;i2++) {
889 for (i0=0;i0<N0t;i0++) {
890 out->Nodes->Tag[i0 + i2*N1*N0t]+=10;
891 out->Nodes->Tag[i0 + (i2+1)*N1*N0t-N0t]+=20;
892 }
893 }
894 }
895 if (!periodic[0] && !domInternal ) {
896 for (i2=0;i2<N2;i2++) {
897 for (i1=0;i1<N1;i1++) {
898 if( domLeft )
899 out->Nodes->Tag[i1*N0t + i2*N0t*N1]+=1;
900 if( domRight )
901 out->Nodes->Tag[(i1+1)*N0t-1 + i2*N0t*N1]+=2;
902 }
903 }
904 }
905
906 /* form the boudary communication information */
907 forwardDOF = MEMALLOC(NDOF1*NDOF2*2,index_t);
908 backwardDOF = MEMALLOC(NDOF1*NDOF2*2,index_t);
909 if( !(mpi_info->size==2 && periodicLocal[0])){
910 if( boundaryLeft ) {
911 targetDomain = mpi_info->rank-1 < 0 ? mpi_info->size-1 : mpi_info->rank-1;
912 for( iI=0, i2=0; i2<NDOF2; i2++ ){
913 for( i1=0; i1<NDOF1; i1++, iI+=2 ){
914 forwardDOF[i1+i2*NDOF1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+i1*N0t+2];
915 backwardDOF[iI] = out->Nodes->degreeOfFreedom[i2*N0t*N1+i1*N0t];
916 backwardDOF[iI+1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+i1*N0t+1];
917 }
918 }
919 Finley_NodeDistribution_addForward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2, forwardDOF );
920 Finley_NodeDistribution_addBackward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2*2, backwardDOF );
921 }
922 if( boundaryRight ) {
923 targetDomain = mpi_info->rank+1 > mpi_info->size-1 ? 0 : mpi_info->rank+1;
924 for( iI=0,i2=0; i2<NDOF2; i2++ ){
925 for( i1=0; i1<NDOF1; i1++, iI+=2 ){
926 forwardDOF[iI] = out->Nodes->degreeOfFreedom[i2*N0t*N1+(i1+1)*N0t-3];
927 forwardDOF[iI+1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+(i1+1)*N0t-2];
928 backwardDOF[i1+i2*NDOF1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+(i1+1)*N0t-1];
929 }
930 }
931 Finley_NodeDistribution_addForward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2*2, forwardDOF );
932 Finley_NodeDistribution_addBackward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2, backwardDOF );
933 }
934 } else{
935 /* periodic boundary conditions with 2 domains, need to change the order in which domain 0 passes boundary data */
936 targetDomain = 1;
937
938 for( iI=0,i2=0; i2<NDOF2; i2++ ){
939 for( i1=0; i1<NDOF1; i1++, iI+=2 ){
940 forwardDOF[iI] = out->Nodes->degreeOfFreedom[i2*N0t*N1+(i1+1)*N0t-3];
941 forwardDOF[iI+1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+(i1+1)*N0t-2];
942 backwardDOF[i1+i2*NDOF1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+(i1+1)*N0t-1];
943 }
944 }
945 Finley_NodeDistribution_addForward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2*2, forwardDOF );
946 Finley_NodeDistribution_addBackward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2, backwardDOF );
947
948 for( iI=0, i2=0; i2<NDOF2; i2++ ){
949 for( i1=0; i1<NDOF1; i1++, iI+=2 ){
950 forwardDOF[i1+i2*NDOF1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+i1*N0t+2];
951 backwardDOF[iI] = out->Nodes->degreeOfFreedom[i2*N0t*N1+i1*N0t];
952 backwardDOF[iI+1] = out->Nodes->degreeOfFreedom[i2*N0t*N1+i1*N0t+1];
953 }
954 }
955 Finley_NodeDistribution_addForward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2, forwardDOF );
956 Finley_NodeDistribution_addBackward( out->Nodes->degreeOfFreedomDistribution, targetDomain, NDOF1*NDOF2*2, backwardDOF );
957 }
958 MEMFREE( forwardDOF );
959 MEMFREE( backwardDOF );
960 /* set the elements: */
961
962 k=0;
963 #pragma omp parallel for private(i0,i1,i2,k,node0)
964 for (i2=0;i2<NE2;i2++) {
965 for (i1=0;i1<NE1;i1++) {
966 for (i0=0;i0<numElementsLocal;i0++,k++) {
967 node0 = (periodicLocal[0] && !i0) ? 2*(i1*N0t + i2*N1*N0t) : 2*(i1*N0t + i2*N1*N0t + i0) + periodicLocal[0];
968
969 out->Elements->Id[k]=((firstNodeConstruct/2+i0)%NE0)*NE1*NE2 + NE1*i2 + i1;
970 out->Elements->Tag[k]=0;
971 out->Elements->Color[k]=COLOR_MOD(i0)+3*COLOR_MOD(i1)+9*COLOR_MOD(i2);
972 out->Elements->Dom[k]=ELEMENT_INTERNAL;
973
974 out->Elements->Nodes[INDEX2(0,k,20)]=node0;
975 out->Elements->Nodes[INDEX2(1,k,20)]=node0+2;
976 out->Elements->Nodes[INDEX2(2,k,20)]=node0+2*N0t+2;
977 out->Elements->Nodes[INDEX2(3,k,20)]=node0+2*N0t;
978 out->Elements->Nodes[INDEX2(4,k,20)]=node0+2*N0t*N1;
979 out->Elements->Nodes[INDEX2(5,k,20)]=node0+2*N0t*N1+2;
980 out->Elements->Nodes[INDEX2(6,k,20)]=node0+2*N0t*N1+2*N0t+2;
981 out->Elements->Nodes[INDEX2(7,k,20)]=node0+2*N0t*N1+2*N0t;
982 out->Elements->Nodes[INDEX2(8,k,20)]=node0+1;
983 out->Elements->Nodes[INDEX2(9,k,20)]=node0+N0t+2;
984 out->Elements->Nodes[INDEX2(10,k,20)]=node0+2*N0t+1;
985 out->Elements->Nodes[INDEX2(11,k,20)]=node0+N0t;
986 out->Elements->Nodes[INDEX2(12,k,20)]=node0+N0t*N1;
987 out->Elements->Nodes[INDEX2(13,k,20)]=node0+N0t*N1+2;
988 out->Elements->Nodes[INDEX2(14,k,20)]=node0+N0t*N1+2*N0t+2;
989 out->Elements->Nodes[INDEX2(15,k,20)]=node0+N0t*N1+2*N0t;
990 out->Elements->Nodes[INDEX2(16,k,20)]=node0+2*N0t*N1+1;
991 out->Elements->Nodes[INDEX2(17,k,20)]=node0+2*N0t*N1+N0t+2;
992 out->Elements->Nodes[INDEX2(18,k,20)]=node0+2*N0t*N1+2*N0t+1;
993 out->Elements->Nodes[INDEX2(19,k,20)]=node0+2*N0t*N1+N0t;
994 }
995 }
996 }
997 out->Elements->minColor=0;
998 out->Elements->maxColor=COLOR_MOD(0)+3*COLOR_MOD(0)+9*COLOR_MOD(0);
999
1000 if( boundaryLeft )
1001 for( i2=0; i2<NE2; i2++ )
1002 for( i1=0; i1<NE1; i1++ )
1003 out->Elements->Dom[i2*NE1*numElementsLocal+i1*numElementsLocal]=ELEMENT_BOUNDARY;
1004 if( boundaryRight )
1005 for( i2=0; i2<NE2; i2++ )
1006 for( i1=0; i1<NE1; i1++ )
1007 out->Elements->Dom[i2*NE1*numElementsLocal+(i1+1)*numElementsLocal-1]=ELEMENT_BOUNDARY;
1008
1009 out->Elements->numElements = numElementsLocal*NE1*NE2;
1010 Finley_ElementFile_setDomainFlags( out->Elements );
1011
1012 /* face elements: */
1013
1014 if (useElementsOnFace) {
1015 NUMNODES=20;
1016 } else {
1017 NUMNODES=8;
1018 }
1019 totalNECount=out->Elements->numElements;
1020 faceNECount=0;
1021 idCount = totalNECount;
1022
1023 /* these are the quadrilateral elements on boundary 1 (x3=0): */
1024 numElementsInternal = numElementsLocal-nodesExternal[0]-nodesExternal[1];
1025 if (!periodic[0] && !domInternal) {
1026 /* ** elements on boundary 001 (x1=0): */
1027 if( domLeft ){
1028 #pragma omp parallel for private(i1,i2,k)
1029 for (i2=0;i2<NE2;i2++) {
1030 for (i1=0;i1<NE1;i1++) {
1031 k=i1+NE1*i2+faceNECount;
1032 kk=i1*numElementsLocal + i2*numElementsLocal*NE1;
1033 facePerm =!useElementsOnFace ? face0R : face0;
1034
1035 out->FaceElements->Id[k]=idCount++;
1036 out->FaceElements->Tag[k]=1;
1037 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
1038 out->FaceElements->Color[k]=(i2%2)+2*(i1%2)+8;
1039
1040 for( j=0; j<NUMNODES; j++ )
1041 out->FaceElements->Nodes[INDEX2(j,k,NUMNODES)]=out->Elements->Nodes[INDEX2(facePerm[j],kk,20)];
1042 }
1043 }
1044 totalNECount+=NE1*NE2;
1045 faceNECount+=NE1*NE2;
1046 }
1047 /* ** elements on boundary 002 (x1=1): */
1048 if( domRight ) {
1049 #pragma omp parallel for private(i1,i2,k)
1050 for (i2=0;i2<NE2;i2++) {
1051 for (i1=0;i1<NE1;i1++) {
1052 k=i1+NE1*i2+faceNECount;
1053 kk=(i1+1)*numElementsLocal + i2*numElementsLocal*NE1 - 1;
1054 facePerm =!useElementsOnFace ? face1R : face1;
1055
1056 out->FaceElements->Id[k]=idCount++;
1057 out->FaceElements->Tag[k]=2;
1058 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
1059 out->FaceElements->Color[k]=(i2%2)+2*(i1%2)+12;
1060
1061 for( j=0; j<NUMNODES; j++ )
1062 out->FaceElements->Nodes[INDEX2(j,k,NUMNODES)]=out->Elements->Nodes[INDEX2(facePerm[j],kk,20)];
1063 }
1064 }
1065 totalNECount+=NE1*NE2;
1066 faceNECount+=NE1*NE2;
1067 }
1068 }
1069 if (!periodic[1]) {
1070 /* ** elements on boundary 010 (x2=0): */
1071
1072 #pragma omp parallel for private(i0,i2,k)
1073 for (i2=0;i2<NE2;i2++) {
1074 for (i0=0;i0<numElementsLocal;i0++) {
1075 k=i0+numElementsLocal*i2+faceNECount;
1076 kk=i0+numElementsLocal*NE1*i2;
1077 facePerm =!useElementsOnFace ? face2R : face2;
1078
1079 out->FaceElements->Id[k]=idCount++;
1080 out->FaceElements->Tag[k]=10;
1081 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
1082 out->FaceElements->Color[k]=(i0%2)+2*(i2%2)+16;
1083
1084 for( j=0; j<NUMNODES; j++ )
1085 out->FaceElements->Nodes[INDEX2(j,k,NUMNODES)]=out->Elements->Nodes[INDEX2(facePerm[j],kk,20)];
1086 }
1087 }
1088 if( boundaryLeft ){
1089 for( i2=0; i2<NE2; i2++ )
1090 out->FaceElements->Dom[faceNECount+i2*numElementsLocal]=ELEMENT_BOUNDARY;
1091 if( periodicLocal[0] )
1092 for( i2=0; i2<NE2; i2++ )
1093 out->FaceElements->Dom[faceNECount+i2*numElementsLocal+1]=ELEMENT_BOUNDARY;
1094 }
1095 if( boundaryRight )
1096 for( i2=0; i2<NE2; i2++ )
1097 out->FaceElements->Dom[faceNECount+(i2+1)*numElementsLocal-1]=ELEMENT_BOUNDARY;
1098 totalNECount+=numElementsLocal*NE2;
1099 faceNECount+=numElementsLocal*NE2;
1100
1101 /* ** elements on boundary 020 (x2=1): */
1102
1103 #pragma omp parallel for private(i0,i2,k)
1104 for (i2=0;i2<NE2;i2++) {
1105 for (i0=0;i0<numElementsLocal;i0++) {
1106 k=i0+numElementsLocal*i2+faceNECount;
1107 kk=i0+numElementsLocal*NE1*(i2+1)-numElementsLocal;
1108 facePerm =!useElementsOnFace ? face3R : face3;
1109
1110 out->FaceElements->Tag[k]=20;
1111 out->FaceElements->Id[k]=idCount++;
1112 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
1113 out->FaceElements->Color[k]=(i0%2)+2*(i2%2)+20;
1114
1115 for( j=0; j<NUMNODES; j++ )
1116 out->FaceElements->Nodes[INDEX2(j,k,NUMNODES)]=out->Elements->Nodes[INDEX2(facePerm[j],kk,20)];
1117 }
1118 }
1119 if( boundaryLeft ){
1120 for( i2=0; i2<NE2; i2++ )
1121 out->FaceElements->Dom[faceNECount+i2*numElementsLocal]=ELEMENT_BOUNDARY;
1122 if( periodicLocal[0] )
1123 for( i2=0; i2<NE2; i2++ )
1124 out->FaceElements->Dom[faceNECount+i2*numElementsLocal+1]=ELEMENT_BOUNDARY;
1125 }
1126 if( boundaryRight )
1127 for( i2=0; i2<NE2; i2++ )
1128 out->FaceElements->Dom[faceNECount+(i2+1)*numElementsLocal-1]=ELEMENT_BOUNDARY;
1129 totalNECount+=numElementsLocal*NE2;
1130 faceNECount+=numElementsLocal*NE2;
1131 }
1132 if (!periodic[2]) {
1133 /* elements on boundary 100 (x3=0): */
1134
1135 #pragma omp parallel for private(i0,i1,k)
1136 for (i1=0;i1<NE1;i1++) {
1137 for (i0=0; i0<numElementsLocal; i0++) {
1138 k=i0+numElementsLocal*i1+faceNECount;
1139 kk=i0 + i1*numElementsLocal;
1140 facePerm =!useElementsOnFace ? face4R : face4;
1141
1142 out->FaceElements->Id[k]=idCount++;
1143 out->FaceElements->Tag[k]=100;
1144 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
1145 out->FaceElements->Color[k]=(i0%2)+2*(i1%2);
1146
1147 for( j=0; j<NUMNODES; j++ )
1148 out->FaceElements->Nodes[INDEX2(j,k,NUMNODES)]=out->Elements->Nodes[INDEX2(facePerm[j],kk,20)];
1149 }
1150 }
1151 if( boundaryLeft ){
1152 for( i1=0; i1<NE1; i1++ )
1153 out->FaceElements->Dom[faceNECount+i1*numElementsLocal]=ELEMENT_BOUNDARY;
1154 if( periodicLocal[0] )
1155 for( i1=0; i1<NE1; i1++ )
1156 out->FaceElements->Dom[faceNECount+i1*numElementsLocal+1]=ELEMENT_BOUNDARY;
1157 }
1158 if( boundaryRight )
1159 for( i1=0; i1<NE1; i1++ )
1160 out->FaceElements->Dom[faceNECount+(i1+1)*numElementsLocal-1]=ELEMENT_BOUNDARY;
1161 totalNECount+=NE1*numElementsLocal;
1162 faceNECount+=NE1*numElementsLocal;
1163
1164 /* ** elements on boundary 200 (x3=1) */
1165
1166 #pragma omp parallel for private(i0,i1,k)
1167 for (i1=0;i1<NE1;i1++) {
1168 for (i0=0;i0<numElementsLocal;i0++) {
1169 k=i0+numElementsLocal*i1+faceNECount;
1170 kk=i0+i1*numElementsLocal+numElementsLocal*NE1*(NE2-1);
1171 facePerm = !useElementsOnFace ? face5R : face5;
1172
1173 out->FaceElements->Id[k]=idCount++;
1174 out->FaceElements->Tag[k]=200;
1175 out->FaceElements->Dom[k]=ELEMENT_INTERNAL;
1176 out->FaceElements->Color[k]=(i0%2)+2*(i1%2)+4;
1177
1178 for( j=0; j<NUMNODES; j++ )
1179 out->FaceElements->Nodes[INDEX2(j,k,NUMNODES)]=out->Elements->Nodes[INDEX2(facePerm[j],kk,20)];
1180 }
1181 }
1182 if( boundaryLeft ){
1183 for( i1=0; i1<NE1; i1++ )
1184 out->FaceElements->Dom[faceNECount+i1*numElementsLocal]=ELEMENT_BOUNDARY;
1185 if( periodicLocal[0] )
1186 for( i1=0; i1<NE1; i1++ )
1187 out->FaceElements->Dom[faceNECount+i1*numElementsLocal+1]=ELEMENT_BOUNDARY;
1188 }
1189 if( boundaryRight )
1190 for( i1=0; i1<NE1; i1++ )
1191 out->FaceElements->Dom[faceNECount+(i1+1)*numElementsLocal-1]=ELEMENT_BOUNDARY;
1192 totalNECount+=NE1*numElementsLocal;
1193 faceNECount+=NE1*numElementsLocal;
1194 }
1195 out->FaceElements->elementDistribution->numInternal = faceNECount;
1196
1197 out->FaceElements->minColor=0;
1198 out->FaceElements->maxColor=23;
1199 out->FaceElements->numElements=faceNECount;
1200 Finley_ElementFile_setDomainFlags( out->FaceElements );
1201
1202 /* setup distribution info for other elements */
1203 Finley_ElementFile_setDomainFlags( out->ContactElements );
1204 Finley_ElementFile_setDomainFlags( out->Points );
1205
1206 /* reorder the degrees of freedom */
1207 Finley_Mesh_resolveDegreeOfFreedomOrder( out, TRUE );
1208
1209 /* condense the nodes: */
1210 Finley_Mesh_resolveNodeIds(out);
1211 if( !Finley_MPI_noError(mpi_info) )
1212 {
1213 Paso_MPIInfo_dealloc( mpi_info );
1214 Finley_Mesh_dealloc(out);
1215 return NULL;
1216 }
1217
1218 /* prepare mesh for further calculatuions:*/
1219 Finley_Mesh_prepare(out);
1220 if( !Finley_MPI_noError(mpi_info) )
1221 {
1222 Paso_MPIInfo_dealloc( mpi_info );
1223 Finley_Mesh_dealloc(out);
1224 return NULL;
1225 }
1226
1227 /* free up memory */
1228 Paso_MPIInfo_dealloc( mpi_info );
1229
1230 //print_mesh_statistics( out, FALSE );
1231
1232 #ifdef Finley_TRACE
1233 printf("timing: mesh generation: %.4e sec\n",Finley_timer()-time0);
1234 #endif
1235
1236 return out;
1237 }
1238 #endif
1239

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26