1 /*============================================================================
2  * Functions handling periodicity.
3  *============================================================================*/
4 
5 /*
6   This file is part of Code_Saturne, a general-purpose CFD tool.
7 
8   Copyright (C) 1998-2021 EDF S.A.
9 
10   This program is free software; you can redistribute it and/or modify it under
11   the terms of the GNU General Public License as published by the Free Software
12   Foundation; either version 2 of the License, or (at your option) any later
13   version.
14 
15   This program is distributed in the hope that it will be useful, but WITHOUT
16   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18   details.
19 
20   You should have received a copy of the GNU General Public License along with
21   this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22   Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24 
25 /*----------------------------------------------------------------------------*/
26 
27 #include "cs_defs.h"
28 
29 /*----------------------------------------------------------------------------
30  * Standard C library headers
31  *----------------------------------------------------------------------------*/
32 
33 #include <assert.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <math.h>
37 #include <stdarg.h>
38 #include <string.h>
39 
40 /*----------------------------------------------------------------------------
41  *  Local headers
42  *----------------------------------------------------------------------------*/
43 
44 #include "bft_mem.h"
45 #include "bft_printf.h"
46 
47 #include "fvm_periodicity.h"
48 
49 #include "cs_base.h"
50 #include "cs_halo.h"
51 #include "cs_interface.h"
52 #include "cs_mesh.h"
53 #include "cs_prototypes.h"
54 #include "cs_timer.h"
55 
56 /*----------------------------------------------------------------------------
57  *  Header for the current file
58  *----------------------------------------------------------------------------*/
59 
60 #include "cs_halo_perio.h"
61 
62 /*----------------------------------------------------------------------------*/
63 
64 BEGIN_C_DECLS
65 
66 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
67 
68 /*=============================================================================
69  * Local Macro definitions
70  *============================================================================*/
71 
72 /*=============================================================================
73  * Local Structure definitions
74  *============================================================================*/
75 
76 /* Structure used for building mesh structure */
77 /* ------------------------------------------ */
78 
79 typedef struct {
80 
81   /* Periodic features */
82 
83   cs_lnum_t  *per_face_idx;    /* Index on periodicity for per_face_lst */
84 
85   cs_lnum_t  *per_face_lst;    /* Periodic faces list. For each couple,
86                                   we have the local face number on local rank
87                                   and the local face number on distant rank */
88 
89   cs_lnum_t  *per_rank_lst;    /* Remote ranks list. For each couple,
90                                   we have the distant rank number. Exists
91                                   only in case of parallelism. */
92 
93 } _perio_mesh_builder_t ;
94 
95 /*============================================================================
96  * Static global variables
97  *============================================================================*/
98 
99 /* Table giving the Reynolds stress component for [i][j] */
100 
101 /* Warning: old fashion to store Rij */
102 static const int _rij[3][3] = {{0, 3, 4},
103                                {3, 1, 5},
104                                {4, 5, 2}};
105 
106 static const int _symt[3][3] = {{0, 3, 5},
107                                 {3, 1, 4},
108                                 {5, 4, 2}};
109 
110 /*============================================================================
111  * Private function definitions
112  *============================================================================*/
113 
114 /*----------------------------------------------------------------------------
115  * Compute a matrix/vector product to apply a transformation to a given
116  * vector.
117  *
118  * parameters:
119  *   matrix[3][4] --> matrix of the transformation in homogeneous coord.
120  *                    last line = [0; 0; 0; 1] (Not used here)
121  *   in_cell_id   --> cell_id of the parent cell.
122  *   out_cell_id  --> cell_id of the generated cell.
123  *   xyz          <-> array of coordinates
124  *----------------------------------------------------------------------------*/
125 
126 static void
_apply_vector_transfo(cs_real_t matrix[3][4],cs_lnum_t in_cell_id,cs_lnum_t out_cell_id,cs_real_t * xyz)127 _apply_vector_transfo(cs_real_t    matrix[3][4],
128                       cs_lnum_t    in_cell_id,
129                       cs_lnum_t    out_cell_id,
130                       cs_real_t   *xyz)
131 {
132   cs_lnum_t  i, j;
133 
134   cs_real_t  xyz_a[3 + 1];
135   cs_real_t  xyz_b[3];
136 
137   /* Define the cell center in homogeneous coordinates before
138      transformation */
139 
140   for (j = 0; j < 3; j++)
141     xyz_a[j] = xyz[in_cell_id*3 + j];
142   xyz_a[3] = 1;
143 
144   /* Initialize output */
145 
146   for (i = 0; i < 3; i++)
147     xyz_b[i] = 0.;
148 
149   for (i = 0; i < 3; i++)
150     for (j = 0; j < 4; j++)
151       xyz_b[i] += matrix[i][j]*xyz_a[j];
152 
153   /* Store updated cell center */
154 
155   for (j = 0; j < 3; j++)
156     xyz[out_cell_id*3 + j] = xyz_b[j];
157 
158 }
159 
160 /*----------------------------------------------------------------------------
161  * Compute a matrix/vector product to apply a transformation to a given
162  * interleaved vector.
163  *
164  * parameters:
165  *   matrix[3][4] --> matrix of the transformation in homogeneous coord.
166  *                    last line = [0; 0; 0; 1] (Not used here)
167  *   xyz          <-> array of coordinates
168  *----------------------------------------------------------------------------*/
169 
170 static void
_apply_vector_rotation(cs_real_t matrix[3][4],cs_real_t * xyz)171 _apply_vector_rotation(cs_real_t    matrix[3][4],
172                        cs_real_t   *xyz)
173 {
174   cs_lnum_t  i;
175 
176   cs_real_t  t[3];
177   for (i = 0; i < 3; i++)
178     t[i] = xyz[i];
179 
180   /* Initialize output */
181 
182   for (i = 0; i < 3; i++)
183     xyz[i] = matrix[i][0]*t[0] + matrix[i][1]*t[1] + matrix[i][2]*t[2];
184 
185 }
186 
187 /*----------------------------------------------------------------------------
188  * Compute a matrix * tensor * Tmatrix product to apply a rotation to a
189  * given tensor
190  *
191  * parameters:
192  *   matrix[3][4]        --> transformation matrix in homogeneous coords.
193  *                           last line = [0; 0; 0; 1] (Not used here)
194  *   in11, in12, in13    --> incoming first line of the tensor
195  *   in21, in22, in23    --> incoming second line of the tensor
196  *   in31, in32, in33    --> incoming third line of the tensor
197  *   out11, out12, out13 <-- pointer to the first line of the output
198  *   out21, out22, out23 <-- pointer to the second line of the output
199  *   out31, out32, out33 <-- pointer to the third line of the output
200  *----------------------------------------------------------------------------*/
201 
202 static void
_apply_tensor_rotation_ni(cs_real_t matrix[3][4],cs_real_t in11,cs_real_t in12,cs_real_t in13,cs_real_t in21,cs_real_t in22,cs_real_t in23,cs_real_t in31,cs_real_t in32,cs_real_t in33,cs_real_t * out11,cs_real_t * out12,cs_real_t * out13,cs_real_t * out21,cs_real_t * out22,cs_real_t * out23,cs_real_t * out31,cs_real_t * out32,cs_real_t * out33)203 _apply_tensor_rotation_ni(cs_real_t   matrix[3][4],
204                           cs_real_t   in11,
205                           cs_real_t   in12,
206                           cs_real_t   in13,
207                           cs_real_t   in21,
208                           cs_real_t   in22,
209                           cs_real_t   in23,
210                           cs_real_t   in31,
211                           cs_real_t   in32,
212                           cs_real_t   in33,
213                           cs_real_t   *out11,
214                           cs_real_t   *out12,
215                           cs_real_t   *out13,
216                           cs_real_t   *out21,
217                           cs_real_t   *out22,
218                           cs_real_t   *out23,
219                           cs_real_t   *out31,
220                           cs_real_t   *out32,
221                           cs_real_t   *out33)
222 {
223   cs_lnum_t  i, j, k;
224   cs_real_t  tensorA[3][3], tensorB[3][3];
225 
226   tensorA[0][0] = matrix[0][0]*in11 + matrix[0][1]*in12 + matrix[0][2]*in13;
227   tensorA[0][1] = matrix[1][0]*in11 + matrix[1][1]*in12 + matrix[1][2]*in13;
228   tensorA[0][2] = matrix[2][0]*in11 + matrix[2][1]*in12 + matrix[2][2]*in13;
229 
230   tensorA[1][0] = matrix[0][0]*in21 + matrix[0][1]*in22 + matrix[0][2]*in23;
231   tensorA[1][1] = matrix[1][0]*in21 + matrix[1][1]*in22 + matrix[1][2]*in23;
232   tensorA[1][2] = matrix[2][0]*in21 + matrix[2][1]*in22 + matrix[2][2]*in23;
233 
234   tensorA[2][0] = matrix[0][0]*in31 + matrix[0][1]*in32 + matrix[0][2]*in33;
235   tensorA[2][1] = matrix[1][0]*in31 + matrix[1][1]*in32 + matrix[1][2]*in33;
236   tensorA[2][2] = matrix[2][0]*in31 + matrix[2][1]*in32 + matrix[2][2]*in33;
237 
238   for (i = 0; i < 3; i++) {
239     for (j = 0; j < 3; j++) {
240       tensorB[i][j] = 0.;
241       for (k = 0; k < 3; k++)
242         tensorB[i][j] += matrix[i][k] * tensorA[k][j];
243     }
244   }
245 
246   *out11 = tensorB[0][0];
247   *out22 = tensorB[1][1];
248   *out33 = tensorB[2][2];
249 
250   if (out12 != NULL) {
251     *out12 = tensorB[0][1];
252     *out13 = tensorB[0][2];
253     *out21 = tensorB[1][0];
254     *out23 = tensorB[1][2];
255     *out31 = tensorB[2][0];
256     *out32 = tensorB[2][1];
257   }
258 
259 }
260 
261 /*----------------------------------------------------------------------------
262  * Compute a matrix * tensor * Tmatrix product to apply a rotation to a
263  * given interleaved tensor
264  *
265  * parameters:
266  *   matrix[3][4]        --> transformation matrix in homogeneous coords.
267  *                           last line = [0; 0; 0; 1] (Not used here)
268  *   tensor              <-> incoming 3x3 tensor
269  *----------------------------------------------------------------------------*/
270 
271 static void
_apply_tensor_rotation(cs_real_t matrix[3][4],cs_real_t * tensor)272 _apply_tensor_rotation(cs_real_t   matrix[3][4],
273                        cs_real_t   *tensor)
274 {
275   cs_lnum_t  i, j, k, l;
276 
277   cs_real_t  t[3][3];
278 
279   for (k = 0; k < 3; k++) {
280     for (j = 0; j < 3; j++) {
281       t[k][j] = 0.;
282       for (l = 0; l < 3; l++)
283         t[k][j] += matrix[j][l] * tensor[k*3+l];
284     }
285   }
286 
287   for (i = 0; i < 3; i++) {
288     for (j = 0; j < 3; j++) {
289       tensor[i*3+j] = 0.;
290       for (k = 0; k < 3; k++)
291         tensor[i*3+j] += matrix[i][k] * t[k][j];
292     }
293   }
294 
295 }
296 
297 /*----------------------------------------------------------------------------
298  * Compute a matrix * tensor * Tmatrix product to apply a rotation to a
299  * given symmetric interleaved tensor
300  *
301  * parameters:
302  *   matrix[3][4]        --> transformation matrix in homogeneous coords.
303  *                           last line = [0; 0; 0; 1] (Not used here)
304  *   tensor              <-> incoming (6) symmetric tensor
305  *----------------------------------------------------------------------------*/
306 
307 static void
_apply_sym_tensor_rotation(cs_real_t matrix[3][4],cs_real_t * tensor)308 _apply_sym_tensor_rotation(cs_real_t   matrix[3][4],
309                            cs_real_t   *tensor)
310 {
311   cs_lnum_t  i, j, k, l;
312 
313   cs_real_t  t[3][3];
314   cs_real_t  t0[3][3];
315 
316   t0[0][0] = tensor[0];
317   t0[1][1] = tensor[1];
318   t0[2][2] = tensor[2];
319   t0[0][1] = tensor[3];
320   t0[1][0] = tensor[3];
321   t0[1][2] = tensor[4];
322   t0[2][1] = tensor[4];
323   t0[0][2] = tensor[5];
324   t0[2][0] = tensor[5];
325 
326   for (k = 0; k < 3; k++) {
327     for (j = 0; j < 3; j++) {
328       t[k][j] = 0.;
329       for (l = 0; l < 3; l++)
330         t[k][j] += matrix[j][l] * t0[k][l];
331     }
332   }
333 
334   for (i = 0; i < 3; i++) {
335     for (j = 0; j < 3; j++) {
336       t0[i][j] = 0.;
337       for (k = 0; k < 3; k++)
338         t0[i][j] += matrix[i][k] * t[k][j];
339     }
340   }
341 
342   tensor[0] = t0[0][0];
343   tensor[1] = t0[1][1];
344   tensor[2] = t0[2][2];
345   tensor[3] = t0[0][1];
346   tensor[3] = t0[1][0];
347   tensor[4] = t0[2][1];
348   tensor[5] = t0[2][0];
349 
350 }
351 
352 /*----------------------------------------------------------------------------
353  * Compute the rotation of a third-order symmetric interleaved tensor
354  * (18 components)
355  * TENSOR_ijk = M_ip M_jq M_kr TENSOR_pqr
356  *
357  * WARNING: old fashion to store Rij (11, 22, 33, 12, 13, 23)
358  *
359  * parameters:
360  *   matrix[3][4]        --> transformation matrix in homogeneous coords.
361  *                           last line = [0; 0; 0; 1] (Not used here)
362  *   tensor              <-> incoming 3x3x3 tensor
363  *                           (in fact 3x6 due to symmetry)
364  *----------------------------------------------------------------------------*/
365 
366 static void
_apply_tensor3sym_rotation_old(cs_real_t matrix[3][4],cs_real_t * tensor)367 _apply_tensor3sym_rotation_old(cs_real_t   matrix[3][4],
368                                cs_real_t   *tensor)
369 {
370   cs_lnum_t  i, j, k, p, q, r;
371 
372   cs_real_t  t1[3][3][3], t2[3][3][3];
373 
374   for (p = 0; p < 3; p++) {
375     for (q = 0; q < 3; q++) {
376       for (k = 0; k < 3; k++) {
377         t1[p][q][k] = 0.;
378         for (r = 0; r < 3; r++)
379           t1[p][q][k] += matrix[k][r] * tensor[3*_rij[p][q] + r];
380       }
381     }
382   }
383 
384   for (i = 0; i < 3; i++) {
385     for (j = 0; j < 3; j++) {
386       for (k = 0; k < 3; k++) {
387         t2[i][j][k] = 0.;
388         for (p = 0; p < 3; p++) {
389           for (q = 0; q < 3; q++)
390             t2[i][j][k] += matrix[i][p] * matrix[j][q] * t1[p][q][k];
391         }
392       }
393     }
394   }
395 
396   /* Output */
397 
398   for (i = 0; i < 3; i++) {
399     for (j = 0; j < 3; j++) {
400       for (k = 0; k < 3; k++)
401         tensor[3*_rij[i][j] + k] = t2[i][j][k];
402     }
403   }
404 
405 }
406 
407 /*----------------------------------------------------------------------------
408  * Compute the rotation of a third-order symmetric interleaved tensor
409  * (18 components)
410  * TENSOR_ijk = M_ip M_jq M_kr TENSOR_pqr
411  *
412  * Warning: Rij stored as (11, 22, 33, 12, 23, 13)
413  *
414  * parameters:
415  *   matrix[3][4]        --> transformation matrix in homogeneous coords.
416  *                           last line = [0; 0; 0; 1] (Not used here)
417  *   tensor              <-> incoming 3x3x3 tensor
418  *                           (in fact 3x6 due to symmetry)
419  *----------------------------------------------------------------------------*/
420 
421 static void
_apply_tensor3sym_rotation(cs_real_t matrix[3][4],cs_real_t * tensor)422 _apply_tensor3sym_rotation(cs_real_t   matrix[3][4],
423                            cs_real_t   *tensor)
424 {
425   cs_lnum_t  i, j, k, p, q, r;
426 
427   cs_real_t  t1[3][3][3], t2[3][3][3];
428 
429   for (p = 0; p < 3; p++) {
430     for (q = 0; q < 3; q++) {
431       for (k = 0; k < 3; k++) {
432         t1[p][q][k] = 0.;
433         for (r = 0; r < 3; r++)
434           t1[p][q][k] += matrix[k][r] * tensor[3*_symt[p][q] + r];
435       }
436     }
437   }
438 
439   for (i = 0; i < 3; i++) {
440     for (j = 0; j < 3; j++) {
441       for (k = 0; k < 3; k++) {
442         t2[i][j][k] = 0.;
443         for (p = 0; p < 3; p++) {
444           for (q = 0; q < 3; q++)
445             t2[i][j][k] += matrix[i][p] * matrix[j][q] * t1[p][q][k];
446         }
447       }
448     }
449   }
450 
451   /* Output */
452 
453   for (i = 0; i < 3; i++) {
454     for (j = 0; j < 3; j++) {
455       for (k = 0; k < 3; k++)
456         tensor[3*_symt[i][j] + k] = t2[i][j][k];
457     }
458   }
459 
460 }
461 
462 /*----------------------------------------------------------------------------
463  * Test if a halo seems compatible with the main mesh's periodic
464  * transformations.
465  *
466  * If a halo is not compatible, abort with an error message.
467  *
468  * parameters:
469  *   halo --> pointer to halo structure
470  *----------------------------------------------------------------------------*/
471 
472 static void
_test_halo_compatibility(const cs_halo_t * halo)473 _test_halo_compatibility(const cs_halo_t  *halo)
474 {
475   assert(halo != NULL);
476 
477   if (cs_glob_mesh->n_transforms != halo->n_transforms)
478     bft_error(__FILE__, __LINE__, 0,
479               _("The %d periodic transformations of the halo do not comply\n"
480                 "with the main mesh transformations (numbering %d).\n"),
481               halo->n_transforms, (int)(cs_glob_mesh->n_transforms));
482 }
483 
484 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
485 
486 /*============================================================================
487  * Public function definitions
488  *============================================================================*/
489 
490 /*----------------------------------------------------------------------------
491  * Apply transformation on coordinates.
492  *
493  * parameters:
494  *   halo      <-> halo associated with coordinates to synchronize
495  *   sync_mode <-- kind of halo treatment (standard or extended)
496  *   coords    <-- coordinates on which transformation have to be done.
497  *----------------------------------------------------------------------------*/
498 
499 void
cs_halo_perio_sync_coords(const cs_halo_t * halo,cs_halo_type_t sync_mode,cs_real_t * coords)500 cs_halo_perio_sync_coords(const cs_halo_t  *halo,
501                           cs_halo_type_t    sync_mode,
502                           cs_real_t        *coords)
503 {
504   int  rank_id, t_id;
505   cs_lnum_t  i, shift, start_std, end_std, start_ext, end_ext;
506 
507   cs_real_t  matrix[3][4];
508 
509   const fvm_periodicity_t  *periodicity = cs_glob_mesh->periodicity;
510   const int  n_transforms = halo->n_transforms;
511   const cs_lnum_t  n_elts = halo->n_local_elts;
512 
513   if (sync_mode == CS_HALO_N_TYPES)
514     return;
515 
516   assert(halo != NULL);
517 
518   _test_halo_compatibility(halo);
519 
520   /* Compute the new cell centers through periodicity */
521 
522   for (t_id = 0; t_id < n_transforms; t_id++) {
523 
524     shift = 4 * halo->n_c_domains * t_id;
525 
526     fvm_periodicity_get_matrix(periodicity, t_id, matrix);
527 
528     for (rank_id = 0; rank_id < halo->n_c_domains; rank_id++) {
529 
530       /* apply transformation for standard halo */
531 
532       start_std = halo->perio_lst[shift + 4*rank_id];
533       end_std = start_std + halo->perio_lst[shift + 4*rank_id + 1];
534 
535       for (i = start_std; i < end_std; i++)
536         _apply_vector_transfo(matrix, n_elts+i, n_elts+i, coords);
537 
538       /* apply transformation for extended halo */
539 
540       if (sync_mode == CS_HALO_EXTENDED) {
541 
542         start_ext = halo->perio_lst[shift + 4*rank_id + 2];
543         end_ext = start_ext + halo->perio_lst[shift + 4*rank_id + 3];
544 
545         for (i = start_ext; i < end_ext; i++)
546           _apply_vector_transfo(matrix, n_elts+i, n_elts+i, coords);
547 
548       } /* End if extended halo */
549 
550     } /* End of loop on ranks */
551 
552   } /* End of loop on transformation */
553 }
554 
555 /*----------------------------------------------------------------------------
556  * Synchronize values for a real vector (interleaved) between periodic cells.
557  *
558  * parameters:
559  *   halo      <-> halo associated with variable to synchronize
560  *   sync_mode <-- kind of halo treatment (standard or extended)
561  *   var       <-> vector to update
562  *   incvar    <-- specifies the increment for the elements of var
563  *----------------------------------------------------------------------------*/
564 
565 void
cs_halo_perio_sync_var_vect(const cs_halo_t * halo,cs_halo_type_t sync_mode,cs_real_t var[],int incvar)566 cs_halo_perio_sync_var_vect(const cs_halo_t  *halo,
567                             cs_halo_type_t    sync_mode,
568                             cs_real_t         var[],
569                             int               incvar)
570 {
571   int  rank_id, t_id;
572   cs_lnum_t  i, shift, start_std, end_std, start_ext, end_ext;
573 
574   cs_real_t matrix[3][4];
575 
576   fvm_periodicity_type_t  perio_type = FVM_PERIODICITY_NULL;
577 
578   const int  n_transforms = halo->n_transforms;
579   const cs_lnum_t  n_elts   = halo->n_local_elts;
580   const fvm_periodicity_t  *periodicity = cs_glob_mesh->periodicity;
581   const int  have_rotation = cs_glob_mesh->have_rotation_perio;
582 
583   if (sync_mode == CS_HALO_N_TYPES || have_rotation == 0)
584     return;
585 
586   assert(halo != NULL);
587   assert(incvar == 3);
588 
589   _test_halo_compatibility(halo);
590 
591   for (t_id = 0; t_id < n_transforms; t_id++) {
592 
593     shift = 4 * halo->n_c_domains * t_id;
594 
595     perio_type = fvm_periodicity_get_type(periodicity, t_id);
596 
597     if (perio_type >= FVM_PERIODICITY_ROTATION) {
598 
599       fvm_periodicity_get_matrix(periodicity, t_id, matrix);
600 
601       for (rank_id = 0; rank_id < halo->n_c_domains; rank_id++) {
602 
603         start_std = n_elts + halo->perio_lst[shift + 4*rank_id];
604         end_std = start_std + halo->perio_lst[shift + 4*rank_id + 1];
605 
606         for (i = start_std; i < end_std; i++)
607           _apply_vector_rotation(matrix, var + i*incvar);
608 
609         if (sync_mode == CS_HALO_EXTENDED) {
610 
611           start_ext = n_elts + halo->perio_lst[shift + 4*rank_id + 2];
612           end_ext = start_ext + halo->perio_lst[shift + 4*rank_id + 3];
613 
614           for (i = start_ext; i < end_ext; i++)
615             _apply_vector_rotation(matrix, var + i*incvar);
616 
617         }
618 
619       } /* End of loop on ranks */
620 
621     } /* End of the treatment of rotation */
622 
623   } /* End of loop on transformations */
624 }
625 
626 /*----------------------------------------------------------------------------
627  * Synchronize values for a real tensor (interleaved) between periodic cells.
628  *
629  * parameters:
630  *   halo      <-> halo associated with variable to synchronize
631  *   sync_mode <-- kind of halo treatment (standard or extended)
632  *   var       <-> tensor to update
633  *----------------------------------------------------------------------------*/
634 
635 void
cs_halo_perio_sync_var_tens(const cs_halo_t * halo,cs_halo_type_t sync_mode,cs_real_t var[])636 cs_halo_perio_sync_var_tens(const cs_halo_t  *halo,
637                             cs_halo_type_t    sync_mode,
638                             cs_real_t         var[])
639 {
640   int  rank_id, t_id;
641   cs_lnum_t  i, shift, start_std, end_std, start_ext, end_ext;
642 
643   cs_real_t  matrix[3][4];
644 
645   fvm_periodicity_type_t  perio_type = FVM_PERIODICITY_NULL;
646 
647   const int  n_transforms = halo->n_transforms;
648   const cs_lnum_t  n_elts   = halo->n_local_elts;
649   const fvm_periodicity_t *periodicity = cs_glob_mesh->periodicity;
650   const int  have_rotation = cs_glob_mesh->have_rotation_perio;
651 
652   if (sync_mode == CS_HALO_N_TYPES || have_rotation == 0)
653     return;
654 
655   assert(halo != NULL);
656 
657   _test_halo_compatibility(halo);
658 
659   for (t_id = 0; t_id < n_transforms; t_id++) {
660 
661     shift = 4 * halo->n_c_domains * t_id;
662 
663     perio_type = fvm_periodicity_get_type(periodicity, t_id);
664 
665     if (perio_type >= FVM_PERIODICITY_ROTATION) {
666 
667       fvm_periodicity_get_matrix(periodicity, t_id, matrix);
668 
669       for (rank_id = 0; rank_id < halo->n_c_domains; rank_id++) {
670 
671         start_std = halo->perio_lst[shift + 4*rank_id];
672         end_std = start_std + halo->perio_lst[shift + 4*rank_id + 1];
673 
674         for (i = start_std; i < end_std; i++)
675           _apply_tensor_rotation(matrix, var + 9*(n_elts+i));
676 
677         if (sync_mode == CS_HALO_EXTENDED) {
678 
679           start_ext = halo->perio_lst[shift + 4*rank_id + 2];
680           end_ext = start_ext + halo->perio_lst[shift + 4*rank_id + 3];
681 
682           for (i = start_ext; i < end_ext; i++)
683             _apply_tensor_rotation(matrix, var + 9*(n_elts+i));
684 
685         } /* End of the treatment of rotation */
686 
687       } /* End if halo is extended */
688 
689     } /* End of loop on ranks */
690 
691   } /* End of loop on transformations for the local rank */
692 }
693 
694 /*----------------------------------------------------------------------------
695  * Synchronize values for a real tensor (symmetric interleaved) between
696  * periodic cells.
697  *
698  * parameters:
699  *   halo      <-> halo associated with variable to synchronize
700  *   sync_mode <-- kind of halo treatment (standard or extended)
701  *   var       <-> symmetric tensor to update (6 values)
702  *----------------------------------------------------------------------------*/
703 
704 void
cs_halo_perio_sync_var_sym_tens(const cs_halo_t * halo,cs_halo_type_t sync_mode,cs_real_t var[])705 cs_halo_perio_sync_var_sym_tens(const cs_halo_t  *halo,
706                                 cs_halo_type_t    sync_mode,
707                                 cs_real_t         var[])
708 {
709   int  rank_id, t_id;
710   cs_lnum_t  i, shift, start_std, end_std, start_ext, end_ext;
711 
712   cs_real_t  matrix[3][4];
713 
714   fvm_periodicity_type_t  perio_type = FVM_PERIODICITY_NULL;
715 
716   const int  n_transforms = halo->n_transforms;
717   const cs_lnum_t  n_elts   = halo->n_local_elts;
718   const fvm_periodicity_t *periodicity = cs_glob_mesh->periodicity;
719   const int  have_rotation = cs_glob_mesh->have_rotation_perio;
720 
721   if (sync_mode == CS_HALO_N_TYPES || have_rotation == 0)
722     return;
723 
724   assert(halo != NULL);
725 
726   _test_halo_compatibility(halo);
727 
728   for (t_id = 0; t_id < n_transforms; t_id++) {
729 
730     shift = 4 * halo->n_c_domains * t_id;
731 
732     perio_type = fvm_periodicity_get_type(periodicity, t_id);
733 
734     if (perio_type >= FVM_PERIODICITY_ROTATION) {
735 
736       fvm_periodicity_get_matrix(periodicity, t_id, matrix);
737 
738       for (rank_id = 0; rank_id < halo->n_c_domains; rank_id++) {
739 
740         start_std = halo->perio_lst[shift + 4*rank_id];
741         end_std = start_std + halo->perio_lst[shift + 4*rank_id + 1];
742 
743         for (i = start_std; i < end_std; i++)
744           _apply_sym_tensor_rotation(matrix, var + 6*(n_elts+i));
745 
746         if (sync_mode == CS_HALO_EXTENDED) {
747 
748           start_ext = halo->perio_lst[shift + 4*rank_id + 2];
749           end_ext = start_ext + halo->perio_lst[shift + 4*rank_id + 3];
750 
751           for (i = start_ext; i < end_ext; i++)
752             _apply_sym_tensor_rotation(matrix, var + 6*(n_elts+i));
753 
754         } /* End of the treatment of rotation */
755 
756       } /* End if halo is extended */
757 
758     } /* End of loop on ranks */
759 
760   } /* End of loop on transformations for the local rank */
761 }
762 
763 /*----------------------------------------------------------------------------
764  * Synchronize values for a real gradient of a tensor (symmetric interleaved)
765  * between periodic cells.
766  *
767  * parameters:
768  *   halo      <-> halo associated with variable to synchronize
769  *   sync_mode <-- kind of halo treatment (standard or extended)
770  *   var       <-> symmetric tensor to update (6 values)
771  *----------------------------------------------------------------------------*/
772 
773 void
cs_halo_perio_sync_var_sym_tens_grad(const cs_halo_t * halo,cs_halo_type_t sync_mode,cs_real_t var[])774 cs_halo_perio_sync_var_sym_tens_grad(const cs_halo_t  *halo,
775                                      cs_halo_type_t    sync_mode,
776                                      cs_real_t         var[])
777 {
778   int  rank_id, t_id;
779   cs_lnum_t  i, shift, start_std, end_std, start_ext, end_ext;
780 
781   cs_real_t  matrix[3][4];
782 
783   fvm_periodicity_type_t  perio_type = FVM_PERIODICITY_NULL;
784 
785   const int  n_transforms = halo->n_transforms;
786   const cs_lnum_t  n_elts   = halo->n_local_elts;
787   const fvm_periodicity_t *periodicity = cs_glob_mesh->periodicity;
788   const int  have_rotation = cs_glob_mesh->have_rotation_perio;
789 
790   if (sync_mode == CS_HALO_N_TYPES || have_rotation == 0)
791     return;
792 
793   assert(halo != NULL);
794 
795   _test_halo_compatibility(halo);
796 
797   for (t_id = 0; t_id < n_transforms; t_id++) {
798 
799     shift = 4 * halo->n_c_domains * t_id;
800 
801     perio_type = fvm_periodicity_get_type(periodicity, t_id);
802 
803     if (perio_type >= FVM_PERIODICITY_ROTATION) {
804 
805       fvm_periodicity_get_matrix(periodicity, t_id, matrix);
806 
807       for (rank_id = 0; rank_id < halo->n_c_domains; rank_id++) {
808 
809         start_std =n_elts +  halo->perio_lst[shift + 4*rank_id];
810         end_std = start_std + halo->perio_lst[shift + 4*rank_id + 1];
811 
812         for (i = start_std; i < end_std; i++)
813           _apply_tensor3sym_rotation(matrix, var + 18*i);
814 
815         if (sync_mode == CS_HALO_EXTENDED) {
816 
817           start_ext = n_elts + halo->perio_lst[shift + 4*rank_id + 2];
818           end_ext = start_ext + halo->perio_lst[shift + 4*rank_id + 3];
819 
820           for (i = start_ext; i < end_ext; i++)
821             _apply_tensor3sym_rotation(matrix, var + 18*i);
822 
823         } /* End of the treatment of rotation */
824 
825       } /* End if halo is extended */
826 
827     } /* End of loop on ranks */
828 
829   } /* End of loop on transformations for the local rank */
830 }
831 
832 /*----------------------------------------------------------------------------*/
833 
834 END_C_DECLS
835