@@ -71,22 +71,39 @@ problemData problemOptions[] = {
71
71
// Auxiliary function to determine if nodes belong to cube faces (panels)
72
72
// -----------------------------------------------------------------------------
73
73
74
- PetscErrorCode FindPanelEdgeNodes (DM dm , PetscInt ncomp , PetscInt * nedgenodes ,
75
- EdgeNode * edgenodes ) {
74
+ PetscErrorCode FindPanelEdgeNodes (DM dm , PhysicsContext phys_ctx ,
75
+ PetscInt ncomp , Mat * T ) {
76
76
77
- PetscInt ierr ;
78
- PetscInt cstart , cend , nstart , nend , nnodes , depth , edgenode = 0 ;
77
+ PetscInt ierr , rankid ;
78
+ MPI_Comm comm ;
79
+ PetscInt cstart , cend , nstart , nend , lnodes , gdofs , depth , edgenodecnt = 0 ;
79
80
PetscSection section ;
81
+ EdgeNode edgenodes ;
82
+
80
83
PetscFunctionBeginUser ;
81
84
// Get Nelem
82
- ierr = DMGetSection (dm , & section ); CHKERRQ (ierr );
85
+ ierr = DMGetLocalSection (dm , & section ); CHKERRQ (ierr );
83
86
ierr = DMPlexGetHeightStratum (dm , 0 , & cstart , & cend ); CHKERRQ (ierr );
84
87
ierr = DMPlexGetDepth (dm , & depth ); CHKERRQ (ierr );
85
88
ierr = DMPlexGetHeightStratum (dm , depth , & nstart , & nend ); CHKERRQ (ierr );
86
- nnodes = nend - nstart ;
87
- unsigned int bitmap [nnodes ];
89
+ lnodes = nend - nstart ;
90
+
91
+ PetscSF sf ;
92
+ Vec bitmapVec ;
93
+ ierr = DMGetSectionSF (dm , & sf ); CHKERRQ (ierr );
94
+ ierr = DMCreateGlobalVector (dm , & bitmapVec ); CHKERRQ (ierr );
95
+ ierr = VecGetSize (bitmapVec , & gdofs ); CHKERRQ (ierr );
96
+ ierr = VecDestroy (& bitmapVec );
97
+
98
+ // Arrays for local and global bitmaps
99
+ unsigned int bitmaploc [lnodes * ncomp ];
100
+ unsigned int bitmap [gdofs ];
88
101
ierr = PetscMemzero (bitmap , sizeof (bitmap )); CHKERRQ (ierr );
89
102
103
+ // Broadcast bitmap values to all ranks
104
+ ierr = PetscSFBcastBegin (sf , MPI_UNSIGNED , bitmap , bitmaploc ); CHKERRQ (ierr );
105
+ ierr = PetscSFBcastEnd (sf , MPI_UNSIGNED , bitmap , bitmaploc ); CHKERRQ (ierr );
106
+
90
107
// Get indices
91
108
for (PetscInt c = cstart ; c < cend ; c ++ ) { // Traverse elements
92
109
PetscInt numindices , * indices , n , panel ;
@@ -96,49 +113,220 @@ PetscErrorCode FindPanelEdgeNodes(DM dm, PetscInt ncomp, PetscInt *nedgenodes,
96
113
& numindices , & indices , NULL , NULL );
97
114
CHKERRQ (ierr );
98
115
for (n = 0 ; n < numindices ; n += ncomp ) { // Traverse nodes per element
99
- PetscInt bitmapidx = indices [n ] / ncomp ;
100
- bitmap [bitmapidx ] |= (1 << panel );
116
+ PetscInt bitmapidx = indices [n ];
117
+ bitmaploc [bitmapidx ] |= (1 << panel );
101
118
}
102
119
ierr = DMPlexRestoreClosureIndices (dm , section , section , c , PETSC_TRUE ,
103
120
& numindices , & indices , NULL , NULL );
104
121
CHKERRQ (ierr );
105
122
}
106
- // Read the 1's in the resulting bitmap and extract edge nodes only
107
- ierr = PetscMalloc1 (nnodes + 24 , edgenodes ); CHKERRQ (ierr );
108
- for (PetscInt i = 0 ; i < nnodes ; i ++ ) {
109
- PetscInt ones = 0 , panels [3 ];
110
- for (PetscInt p = 0 ; p < 6 ; p ++ ) {
111
- if (bitmap [i ] & 1 )
112
- panels [ones ++ ] = p ;
113
- bitmap [i ] >>= 1 ;
114
- }
115
- if (ones == 2 ) {
116
- (* edgenodes )[edgenode ].idx = i ;
117
- (* edgenodes )[edgenode ].panelA = panels [0 ];
118
- (* edgenodes )[edgenode ].panelB = panels [1 ];
119
- edgenode ++ ;
123
+
124
+ // Reduce on all ranks
125
+ ierr = PetscSFReduceBegin (sf , MPI_UNSIGNED , bitmaploc , bitmap , MPI_BOR );
126
+ CHKERRQ (ierr );
127
+ ierr = PetscSFReduceEnd (sf , MPI_UNSIGNED , bitmaploc , bitmap , MPI_BOR );
128
+ CHKERRQ (ierr );
129
+
130
+ // Rank 0 reads the 1's in the resulting bitmap and extracts edge nodes only
131
+ PetscObjectGetComm ((PetscObject )dm , & comm ); CHKERRQ (ierr );
132
+ MPI_Comm_rank (comm , & rankid );
133
+ if (rankid == 0 ) {
134
+ ierr = PetscMalloc1 (gdofs + 24 * ncomp , & edgenodes ); CHKERRQ (ierr );
135
+ for (PetscInt i = 0 ; i < gdofs ; i += ncomp ) {
136
+ PetscInt ones = 0 , panels [3 ];
137
+ for (PetscInt p = 0 ; p < 6 ; p ++ ) {
138
+ if (bitmap [i ] & 1 )
139
+ panels [ones ++ ] = p ;
140
+ bitmap [i ] >>= 1 ;
141
+ }
142
+ if (ones == 2 ) {
143
+ edgenodes [edgenodecnt ].idx = i ;
144
+ edgenodes [edgenodecnt ].panelA = panels [0 ];
145
+ edgenodes [edgenodecnt ].panelB = panels [1 ];
146
+ edgenodecnt ++ ;
147
+ }
148
+ else if (ones == 3 ) {
149
+ edgenodes [edgenodecnt ].idx = i ;
150
+ edgenodes [edgenodecnt ].panelA = panels [0 ];
151
+ edgenodes [edgenodecnt ].panelB = panels [1 ];
152
+ edgenodecnt ++ ;
153
+ edgenodes [edgenodecnt ].idx = i ;
154
+ edgenodes [edgenodecnt ].panelA = panels [0 ];
155
+ edgenodes [edgenodecnt ].panelB = panels [2 ];
156
+ edgenodecnt ++ ;
157
+ edgenodes [edgenodecnt ].idx = i ;
158
+ edgenodes [edgenodecnt ].panelA = panels [1 ];
159
+ edgenodes [edgenodecnt ].panelB = panels [2 ];
160
+ edgenodecnt ++ ;
161
+ }
120
162
}
121
- else if (ones == 3 ) {
122
- (* edgenodes )[edgenode ].idx = i ;
123
- (* edgenodes )[edgenode ].panelA = panels [0 ];
124
- (* edgenodes )[edgenode ].panelB = panels [1 ];
125
- edgenode ++ ;
126
- (* edgenodes )[edgenode ].idx = i ;
127
- (* edgenodes )[edgenode ].panelA = panels [0 ];
128
- (* edgenodes )[edgenode ].panelB = panels [2 ];
129
- edgenode ++ ;
130
- (* edgenodes )[edgenode ].idx = i ;
131
- (* edgenodes )[edgenode ].panelA = panels [1 ];
132
- (* edgenodes )[edgenode ].panelB = panels [2 ];
133
- edgenode ++ ;
163
+ ierr = SetupPanelCoordTransformations (dm , phys_ctx , ncomp , edgenodes ,
164
+ edgenodecnt , T ); CHKERRQ (ierr );
165
+ // Free edgenodes structure array
166
+ ierr = PetscFree (edgenodes ); CHKERRQ (ierr );
167
+ }
168
+
169
+ PetscFunctionReturn (0 );
170
+ }
171
+
172
+ // -----------------------------------------------------------------------------
173
+ // Auxiliary function that sets up all corrdinate transformations between panels
174
+ // -----------------------------------------------------------------------------
175
+ PetscErrorCode SetupPanelCoordTransformations (DM dm , PhysicsContext phys_ctx ,
176
+ PetscInt ncomp ,
177
+ EdgeNode edgenodes ,
178
+ PetscInt nedgenodes , Mat * T ) {
179
+ PetscInt ierr ;
180
+ MPI_Comm comm ;
181
+ Vec X ;
182
+ PetscInt gdofs ;
183
+ const PetscScalar * xarray ;
184
+
185
+ PetscFunctionBeginUser ;
186
+ ierr = PetscObjectGetComm ((PetscObject )dm , & comm ); CHKERRQ (ierr );
187
+
188
+ ierr = DMGetCoordinates (dm , & X ); CHKERRQ (ierr );
189
+ ierr = VecGetSize (X , & gdofs ); CHKERRQ (ierr );
190
+
191
+ // Preallocate sparse matrix
192
+ ierr = MatCreateBAIJ (comm , 2 , PETSC_DECIDE , PETSC_DECIDE , 4 * gdofs /ncomp ,
193
+ 4 * gdofs /ncomp , 2 , NULL , 0 , NULL , T ); CHKERRQ (ierr );
194
+ for (PetscInt i = 0 ; i < 4 * gdofs /ncomp ; i ++ ) {
195
+ ierr = MatSetValue (* T , i , i , 1. , INSERT_VALUES ); CHKERRQ (ierr );
196
+ }
197
+
198
+ ierr = VecGetArrayRead (X , & xarray ); CHKERRQ (ierr );
199
+ PetscScalar R = phys_ctx -> R ;
200
+ // Nodes loop
201
+ for (PetscInt i = 0 ; i < gdofs ; i += ncomp ) {
202
+ // Read global Cartesian coordinates
203
+ PetscScalar x [3 ] = {xarray [i * ncomp + 0 ],
204
+ xarray [i * ncomp + 1 ],
205
+ xarray [i * ncomp + 2 ]
206
+ };
207
+ // Normalize quadrature point coordinates to sphere
208
+ PetscScalar rad = sqrt (x [0 ]* x [0 ] + x [1 ]* x [1 ] + x [2 ]* x [2 ]);
209
+ x [0 ] *= R / rad ;
210
+ x [1 ] *= R / rad ;
211
+ x [2 ] *= R / rad ;
212
+ // Compute latitude and longitude
213
+ const PetscScalar theta = asin (x [2 ] / R ); // latitude
214
+ const PetscScalar lambda = atan2 (x [1 ], x [0 ]); // longitude
215
+
216
+ // For P_1 (east), P_3 (front), P_4 (west), P_5 (back):
217
+ PetscScalar T00 = cos (theta )* cos (lambda ) * cos (lambda );
218
+ PetscScalar T01 = cos (theta )* cos (lambda ) * 0. ;
219
+ PetscScalar T10 = cos (theta )* cos (lambda ) * - sin (theta )* sin (lambda );
220
+ PetscScalar T11 = cos (theta )* cos (lambda ) * cos (theta );
221
+ const PetscScalar T_lateral [2 ][2 ] = {{T00 ,
222
+ T01 },
223
+ {T10 ,
224
+ T11 }
225
+ };
226
+ PetscScalar Tinv00 = 1. /(cos (theta )* cos (lambda )) * (1. /cos (lambda ));
227
+ PetscScalar Tinv01 = 1. /(cos (theta )* cos (lambda )) * 0. ;
228
+ PetscScalar Tinv10 = 1. /(cos (theta )* cos (lambda )) * tan (theta )* tan (lambda );
229
+ PetscScalar Tinv11 = 1. /(cos (theta )* cos (lambda )) * (1. /cos (theta ));
230
+ const PetscScalar T_lateralinv [2 ][2 ] = {{Tinv00 ,
231
+ Tinv01 },
232
+ {Tinv10 ,
233
+ Tinv11 }
234
+ };
235
+ // For P2 (north):
236
+ T00 = sin (theta ) * cos (lambda );
237
+ T01 = sin (theta ) * sin (lambda );
238
+ T10 = sin (theta ) * - sin (theta )* sin (lambda );
239
+ T11 = sin (theta ) * sin (theta )* cos (lambda );
240
+ const PetscScalar T_top [2 ][2 ] = {{T00 ,
241
+ T01 },
242
+ {T10 ,
243
+ T11 }
244
+ };
245
+ Tinv00 = 1. /(sin (theta )* sin (theta )) * sin (theta )* cos (lambda );
246
+ Tinv01 = 1. /(sin (theta )* sin (theta )) * (- sin (lambda ));
247
+ Tinv10 = 1. /(sin (theta )* sin (theta )) * sin (theta )* sin (lambda );
248
+ Tinv11 = 1. /(sin (theta )* sin (theta )) * cos (lambda );
249
+ const PetscScalar T_topinv [2 ][2 ] = {{Tinv00 ,
250
+ Tinv01 },
251
+ {Tinv10 ,
252
+ Tinv11 }
253
+ };
254
+
255
+ // For P0 (south):
256
+ T00 = sin (theta ) * (- cos (theta ));
257
+ T01 = sin (theta ) * sin (lambda );
258
+ T10 = sin (theta ) * sin (theta )* sin (lambda );
259
+ T11 = sin (theta ) * sin (theta )* cos (lambda );
260
+ const PetscScalar T_bottom [2 ][2 ] = {{T00 ,
261
+ T01 },
262
+ {T10 ,
263
+ T11 }
264
+ };
265
+ Tinv00 = 1. /(sin (theta )* sin (theta )) * (- sin (theta )* cos (lambda ));
266
+ Tinv01 = 1. /(sin (theta )* sin (theta )) * sin (lambda );
267
+ Tinv10 = 1. /(sin (theta )* sin (theta )) * sin (theta )* sin (lambda );
268
+ Tinv11 = 1. /(sin (theta )* sin (theta )) * cos (lambda );
269
+ const PetscScalar T_bottominv [2 ][2 ] = {{Tinv00 ,
270
+ Tinv01 },
271
+ {Tinv10 ,
272
+ Tinv11 }
273
+ };
274
+
275
+ const PetscScalar (* transforms [6 ])[2 ][2 ] = {& T_bottom ,
276
+ & T_lateral ,
277
+ & T_top ,
278
+ & T_lateral ,
279
+ & T_lateral ,
280
+ & T_lateral
281
+ };
282
+
283
+ const PetscScalar (* inv_transforms [6 ])[2 ][2 ] = {& T_bottominv ,
284
+ & T_lateralinv ,
285
+ & T_topinv ,
286
+ & T_lateralinv ,
287
+ & T_lateralinv ,
288
+ & T_lateralinv
289
+ };
290
+
291
+ for (PetscInt e = 0 ; e < nedgenodes ; e ++ ) {
292
+ if (edgenodes [e ].idx == i ) {
293
+ const PetscScalar (* matrixA )[2 ][2 ] = inv_transforms [edgenodes [e ].panelA ];
294
+ const PetscScalar (* matrixB )[2 ][2 ] = transforms [edgenodes [e ].panelB ];
295
+
296
+ // inv_transform * transform (A^{-1}*B)
297
+ // This product represents the mapping from coordinate system A
298
+ // to spherical coordinates and then to coordinate system B. Vice versa
299
+ // for transform * inv_transform (B^{-1}*A)
300
+ PetscScalar matrixAB [2 ][2 ], matrixBA [2 ][2 ];
301
+ for (int j = 0 ; j < 2 ; j ++ ) {
302
+ for (int k = 0 ; k < 2 ; k ++ ) {
303
+ matrixAB [j ][k ] = matrixBA [j ][k ] = 0 ;
304
+ for (int l = 0 ; l < 2 ; l ++ ) {
305
+ matrixAB [j ][k ] += (* matrixA )[j ][l ] * (* matrixB )[l ][k ];
306
+ matrixBA [j ][k ] += (* matrixB )[j ][l ] * (* matrixA )[l ][k ];
307
+ }
308
+ }
309
+ }
310
+ PetscInt idxAB [2 ] = {4 * i /ncomp + 0 , 4 * i /ncomp + 1 };
311
+ PetscInt idxBA [2 ] = {4 * i /ncomp + 2 , 4 * i /ncomp + 3 };
312
+ ierr = MatSetValues (* T , 2 , idxAB , 2 , idxAB , (PetscScalar * )matrixAB ,
313
+ INSERT_VALUES ); CHKERRQ (ierr );
314
+ ierr = MatSetValues (* T , 2 , idxBA , 2 , idxBA , (PetscScalar * )matrixBA ,
315
+ INSERT_VALUES ); CHKERRQ (ierr );
316
+ }
134
317
}
135
318
}
136
- ierr = PetscRealloc (edgenode , edgenodes ); CHKERRQ (ierr );
137
- * nedgenodes = edgenode ;
319
+ // Assemble matrix for all node transformations
320
+ ierr = MatAssemblyBegin (* T , MAT_FINAL_ASSEMBLY ); CHKERRQ (ierr );
321
+ ierr = MatAssemblyEnd (* T , MAT_FINAL_ASSEMBLY ); CHKERRQ (ierr );
322
+
323
+ // Restore array read
324
+ ierr = VecRestoreArrayRead (X , & xarray ); CHKERRQ (ierr );
138
325
139
326
PetscFunctionReturn (0 );
140
327
}
141
328
329
+
142
330
// -----------------------------------------------------------------------------
143
331
// Auxiliary function to create PETSc FE space for a given degree
144
332
// -----------------------------------------------------------------------------
0 commit comments