1 /*============================================================================
2 * Convection-diffusion operators.
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 #include "cs_defs.h"
27
28 /*----------------------------------------------------------------------------
29 * Standard C library headers
30 *----------------------------------------------------------------------------*/
31
32 #include <assert.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <math.h>
38 #include <float.h>
39
40 #if defined(HAVE_MPI)
41 #include <mpi.h>
42 #endif
43
44 /*----------------------------------------------------------------------------
45 * Local headers
46 *----------------------------------------------------------------------------*/
47
48 #include "bft_error.h"
49 #include "bft_mem.h"
50 #include "bft_printf.h"
51
52 #include "cs_blas.h"
53 #include "cs_bad_cells_regularisation.h"
54 #include "cs_boundary_conditions.h"
55 #include "cs_halo.h"
56 #include "cs_halo_perio.h"
57 #include "cs_log.h"
58 #include "cs_internal_coupling.h"
59 #include "cs_math.h"
60 #include "cs_mesh.h"
61 #include "cs_field.h"
62 #include "cs_field_operator.h"
63 #include "cs_field_pointer.h"
64 #include "cs_gradient.h"
65 #include "cs_ext_neighborhood.h"
66 #include "cs_mesh_quantities.h"
67 #include "cs_parall.h"
68 #include "cs_parameters.h"
69 #include "cs_porous_model.h"
70 #include "cs_prototypes.h"
71 #include "cs_timer.h"
72 #include "cs_velocity_pressure.h"
73
74 /*----------------------------------------------------------------------------
75 * Header for the current file
76 *----------------------------------------------------------------------------*/
77
78 #include "cs_convection_diffusion.h"
79
80 /*----------------------------------------------------------------------------*/
81
82 BEGIN_C_DECLS
83
84 /*=============================================================================
85 * Additional Doxygen documentation
86 *============================================================================*/
87
88 /*! \file cs_convection_diffusion.c
89 *
90 * \brief Convection-diffusion operators.
91 *
92 * Please refer to the
93 * <a href="../../theory.pdf#conv-diff"><b>convection-diffusion</b></a> section
94 * of the theory guide for more informations.
95 */
96 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
97
98 /*=============================================================================
99 * Local Macro Definitions
100 *============================================================================*/
101
102 /*=============================================================================
103 * Local type definitions
104 *============================================================================*/
105
106 /*============================================================================
107 * Private function definitions
108 *============================================================================*/
109
110 /*----------------------------------------------------------------------------
111 * Return the equivalent heat transfer coefficient. If both terms are
112 * below a given tolerance, 0. is returned.
113 *
114 * parameters:
115 * h1 <-- first exchange coefficient
116 * h2 <-- second exchange coefficient
117 *
118 * return:
119 * value of equivalent exchange coefficient
120 *----------------------------------------------------------------------------*/
121
122 static inline cs_real_t
_calc_heq(cs_real_t h1,cs_real_t h2)123 _calc_heq(cs_real_t h1,
124 cs_real_t h2)
125 {
126 const cs_real_t h_eps = 1.e-12;
127
128 cs_real_t heq = 0.;
129 if (h1 + h2 > h_eps)
130 heq = h1 * h2 / (h1 + h2);
131
132 return heq;
133 }
134
135 /*----------------------------------------------------------------------------
136 * Return the denominator to build the beta blending coefficient of the
137 * beta limiter (ensuring preservation of a given min/max pair of values).
138 *
139 * parameters:
140 * f_id <-- field id (or -1)
141 * inc <-- 0 if an increment, 1 otherwise
142 * denom_inf --> computed denominator for the inferior bound
143 * denom_sup --> computed denominator for the superior bound
144 *
145 * return:
146 * pointer to local values array, or NULL;
147 *----------------------------------------------------------------------------*/
148
149 static void
_beta_limiter_denom(const int f_id,const int inc,cs_real_t * restrict denom_inf,cs_real_t * restrict denom_sup)150 _beta_limiter_denom(const int f_id,
151 const int inc,
152 cs_real_t *restrict denom_inf,
153 cs_real_t *restrict denom_sup)
154 {
155 const cs_mesh_t *m = cs_glob_mesh;
156 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
157
158 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
159 const int n_i_groups = m->i_face_numbering->n_groups;
160 const int n_i_threads = m->i_face_numbering->n_threads;
161 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
162
163 const cs_lnum_2_t *restrict i_face_cells
164 = (const cs_lnum_2_t *restrict)m->i_face_cells;
165 const cs_real_t *restrict weight = fvq->weight;
166 const cs_real_3_t *restrict cell_cen
167 = (const cs_real_3_t *restrict)fvq->cell_cen;
168 const cs_real_3_t *restrict i_face_normal
169 = (const cs_real_3_t *restrict)fvq->i_face_normal;
170 const cs_real_3_t *restrict i_face_cog
171 = (const cs_real_3_t *restrict)fvq->i_face_cog;
172 const cs_real_3_t *restrict diipf
173 = (const cs_real_3_t *restrict)fvq->diipf;
174 const cs_real_3_t *restrict djjpf
175 = (const cs_real_3_t *restrict)fvq->djjpf;
176
177 /* Get option from the field */
178 cs_field_t *f = cs_field_by_id(f_id);
179
180 const cs_real_t *restrict pvar = f->val;
181 const cs_real_t *restrict pvara = f->val_pre;
182
183 const cs_real_t *restrict coefap = f->bc_coeffs->a;
184 const cs_real_t *restrict coefbp = f->bc_coeffs->b;
185
186 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
187 cs_var_cal_opt_t var_cal_opt;
188
189 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
190
191 const int ischcp = var_cal_opt.ischcv;
192 const int ircflp = var_cal_opt.ircflu;
193 const int imrgra = var_cal_opt.imrgra;
194 const cs_real_t thetap = var_cal_opt.thetav;
195 const cs_real_t blencp = var_cal_opt.blencv;
196
197 const int kimasf = cs_field_key_id("inner_mass_flux_id");
198 const int kbmasf = cs_field_key_id("boundary_mass_flux_id");
199 const cs_real_t *restrict i_massflux =
200 cs_field_by_id(cs_field_get_key_int(f, kimasf))->val;
201 const cs_real_t *restrict b_massflux =
202 cs_field_by_id(cs_field_get_key_int(f, kbmasf))->val;
203
204 /* select halo type according to field gradient method */
205
206 cs_halo_type_t halo_type = CS_HALO_STANDARD;
207 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
208
209 cs_gradient_type_by_imrgra(imrgra,
210 &gradient_type,
211 &halo_type);
212
213 /* for NVD / TVD schemes (including VoF schemes) */
214
215 const int key_lim_choice = cs_field_key_id("limiter_choice");
216 int limiter_choice = -1;
217
218 cs_real_t *local_min = NULL;
219 cs_real_t *local_max = NULL;
220 cs_real_t *courant = NULL;
221
222 if (ischcp == 4) {
223 /* get limiter choice */
224 limiter_choice = cs_field_get_key_int(f, key_lim_choice);
225
226 /* local extrema computation */
227 BFT_MALLOC(local_max, n_cells_ext, cs_real_t);
228 BFT_MALLOC(local_min, n_cells_ext, cs_real_t);
229 cs_field_local_extrema_scalar(f_id,
230 halo_type,
231 local_max,
232 local_min);
233
234 /* cell Courant number computation */
235 if (limiter_choice >= CS_NVD_VOF_HRIC) {
236 BFT_MALLOC(courant, n_cells_ext, cs_real_t);
237 cs_cell_courant_number(f_id, courant);
238 }
239 }
240
241 cs_real_t *df_limiter = NULL;
242 int df_limiter_id =
243 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
244 if (df_limiter_id > -1)
245 df_limiter = cs_field_by_id(df_limiter_id)->val;
246
247 /* step 1: gradient computation */
248 cs_real_3_t *grdpa; /* for the implicit part */
249 cs_real_3_t *grdpaa; /* for the explicit part */
250
251 BFT_MALLOC(grdpa, n_cells_ext, cs_real_3_t);
252 BFT_MALLOC(grdpaa, n_cells_ext, cs_real_3_t);
253
254 # pragma omp parallel for
255 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
256 grdpa[cell_id][0] = 0.;
257 grdpa[cell_id][1] = 0.;
258 grdpa[cell_id][2] = 0.;
259
260 grdpaa[cell_id][0] = 0.;
261 grdpaa[cell_id][1] = 0.;
262 grdpaa[cell_id][2] = 0.;
263 }
264
265 /* legacy SOLU Scheme or centered scheme */
266 if (ischcp == 0 || ischcp == 1 || ischcp == 3) {
267
268 cs_field_gradient_scalar(f,
269 false, /* use_previous_t */
270 inc,
271 true, /* _recompute_cocg */
272 grdpa);
273
274 cs_field_gradient_scalar(f,
275 true, /* use_previous_t */
276 inc,
277 true, /* _recompute_cocg */
278 grdpaa);
279
280 }
281 /* pure SOLU scheme (upwind gradient reconstruction) */
282 else if (ischcp == 2) {
283
284 cs_upwind_gradient(f_id,
285 inc,
286 halo_type,
287 coefap,
288 coefbp,
289 i_massflux,
290 b_massflux,
291 pvar,
292 grdpa);
293
294 cs_upwind_gradient(f_id,
295 inc,
296 halo_type,
297 coefap,
298 coefbp,
299 i_massflux,
300 b_massflux,
301 pvara,
302 grdpaa);
303
304 }
305
306 /* Step 2: Building of denominator */
307
308 # pragma omp parallel for
309 for (cs_lnum_t ii = 0; ii < n_cells_ext; ii++) {
310 denom_inf[ii] = 0.;
311 denom_sup[ii] = 0.;
312 }
313
314 /* ---> Contribution from interior faces */
315
316 for (int g_id = 0; g_id < n_i_groups; g_id++) {
317 # pragma omp parallel for
318 for (int t_id = 0; t_id < n_i_threads; t_id++) {
319 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
320 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
321 face_id++) {
322
323 cs_lnum_t ii = i_face_cells[face_id][0];
324 cs_lnum_t jj = i_face_cells[face_id][1];
325
326 cs_real_t pi = pvar[ii];
327 cs_real_t pj = pvar[jj];
328 cs_real_t pia = pvara[ii];
329 cs_real_t pja = pvara[jj];
330 cs_real_t pif, pjf, pip, pjp;
331 cs_real_t pifa, pjfa, pipa, pjpa;
332
333 cs_real_t hybrid_coef_ii, hybrid_coef_jj;
334 if (ischcp == 3) {
335 hybrid_coef_ii = CS_F_(hybrid_blend)->val[ii];
336 hybrid_coef_jj = CS_F_(hybrid_blend)->val[jj];
337 } else {
338 hybrid_coef_ii = 0.;
339 hybrid_coef_jj = 0.;
340 }
341
342 cs_real_t bldfrp = (cs_real_t) ircflp;
343 /* Local limitation of the reconstruction */
344 if (df_limiter != NULL && ircflp > 0)
345 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
346
347 if (ischcp == 4) {
348 /* NVD/TVD family of high accuracy schemes */
349
350 cs_lnum_t ic, id;
351
352 /* Determine central and downwind sides w.r.t. current face */
353 cs_central_downwind_cells(ii,
354 jj,
355 i_massflux[face_id],
356 &ic, /* central cell id */
357 &id); /* downwind cell id */
358
359 cs_real_t courant_c = -1.;
360 if (courant != NULL)
361 courant_c = courant[ic];
362
363 cs_i_cd_unsteady_nvd(limiter_choice,
364 blencp,
365 cell_cen[ic],
366 cell_cen[id],
367 i_face_normal[face_id],
368 i_face_cog[face_id],
369 grdpa[ic],
370 pvar[ic],
371 pvar[id],
372 local_max[ic],
373 local_min[ic],
374 courant_c,
375 &pif,
376 &pjf);
377
378 cs_i_cd_unsteady_nvd(limiter_choice,
379 blencp,
380 cell_cen[ic],
381 cell_cen[id],
382 i_face_normal[face_id],
383 i_face_cog[face_id],
384 grdpaa[ic],
385 pvara[ic],
386 pvara[id],
387 local_max[ic],
388 local_min[ic],
389 courant_c,
390 &pifa,
391 &pjfa);
392 } else {
393 /* Value at time n */
394 cs_i_cd_unsteady(bldfrp,
395 ischcp,
396 blencp,
397 weight[face_id],
398 cell_cen[ii],
399 cell_cen[jj],
400 i_face_cog[face_id],
401 hybrid_coef_ii,
402 hybrid_coef_jj,
403 diipf[face_id],
404 djjpf[face_id],
405 grdpa[ii], /* Std gradient when needed */
406 grdpa[jj], /* Std gradient when needed */
407 grdpa[ii], /* Upwind gradient when needed */
408 grdpa[jj], /* Upwind gradient when needed */
409 pi,
410 pj,
411 &pif,
412 &pjf,
413 &pip,
414 &pjp);
415
416 /* Value at time n-1 */
417 cs_i_cd_unsteady(bldfrp,
418 ischcp,
419 blencp,
420 weight[face_id],
421 cell_cen[ii],
422 cell_cen[jj],
423 i_face_cog[face_id],
424 hybrid_coef_ii, /* FIXME use previous values
425 of blending function */
426 hybrid_coef_jj, /* FIXME use previous values
427 of blending function */
428 diipf[face_id],
429 djjpf[face_id],
430 grdpaa[ii], /* Std gradient when needed */
431 grdpaa[jj], /* Std gradient when needed */
432 grdpaa[ii], /* Upwind gradient when needed */
433 grdpaa[jj], /* Upwind gradient when needed */
434 pia,
435 pja,
436 &pifa,
437 &pjfa,
438 &pipa,
439 &pjpa);
440 }
441
442 cs_real_t flui = 0.5*(i_massflux[face_id] +fabs(i_massflux[face_id]));
443 cs_real_t fluj = 0.5*(i_massflux[face_id] -fabs(i_massflux[face_id]));
444
445 cs_real_t flux = thetap * ( (pif - pi )*flui
446 + (pjf - pj )*fluj)
447 + (1.-thetap) * ( (pifa - pia)*flui
448 + (pjfa - pja)*fluj);
449
450 /* blending to prevent INFERIOR bound violation
451 We need to take the positive part*/
452 cs_real_t partii = 0.5*(flux + CS_ABS(flux));
453 cs_real_t partjj = 0.5*(flux - CS_ABS(flux));
454
455 denom_inf[ii] = denom_inf[ii] + partii;
456 denom_inf[jj] = denom_inf[jj] - partjj;
457
458 /* blending to prevent SUPERIOR bound violation
459 We need to take the negative part
460 Note: the swap between ii and jj is due to the fact
461 that an upwind value on (Y-bound) is equivalent to a
462 downwind value on (bound-Y) */
463 denom_sup[ii] = denom_sup[ii] - partjj;
464 denom_sup[jj] = denom_sup[jj] + partii;
465 }
466 }
467 }
468
469 //Free Gradient arrays
470 BFT_FREE(local_min);
471 BFT_FREE(local_max);
472 BFT_FREE(courant);
473 BFT_FREE(grdpa);
474 BFT_FREE(grdpaa);
475
476 }
477
478 /*----------------------------------------------------------------------------
479 * Return the diagonal part of the numerator to build the Min/max limiter.
480 *
481 * parameters:
482 * f_id <-- field id (or -1)
483 * rovsdt <-- rho * volume / dt
484 * num_inf --> computed numerator for the inferior bound
485 * num_sup --> computed numerator for the superior bound
486 *
487 *----------------------------------------------------------------------------*/
488
489 static void
_beta_limiter_num(const int f_id,const int inc,const cs_real_t rovsdt[],cs_real_t * num_inf,cs_real_t * num_sup)490 _beta_limiter_num(const int f_id,
491 const int inc,
492 const cs_real_t rovsdt[],
493 cs_real_t *num_inf,
494 cs_real_t *num_sup)
495 {
496 const cs_mesh_t *m = cs_glob_mesh;
497
498 const cs_lnum_t n_cells = m->n_cells;
499 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
500 const int n_i_groups = m->i_face_numbering->n_groups;
501 const int n_i_threads = m->i_face_numbering->n_threads;
502 const int n_b_groups = m->b_face_numbering->n_groups;
503 const int n_b_threads = m->b_face_numbering->n_threads;
504 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
505 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
506
507 const cs_lnum_2_t *restrict i_face_cells
508 = (const cs_lnum_2_t *restrict)m->i_face_cells;
509 const cs_lnum_t *restrict b_face_cells
510 = (const cs_lnum_t *restrict)m->b_face_cells;
511
512 /* Get option from the field */
513 cs_field_t *f = cs_field_by_id(f_id);
514
515 const cs_real_t *restrict pvara = f->val_pre;
516
517 const cs_real_t *restrict coefap = f->bc_coeffs->a;
518 const cs_real_t *restrict coefbp = f->bc_coeffs->b;
519
520 int key_scamax_id = cs_field_key_id("max_scalar");
521 int key_scamin_id = cs_field_key_id("min_scalar");
522
523 cs_real_t scalar_max = cs_field_get_key_double(f, key_scamax_id);
524 cs_real_t scalar_min = cs_field_get_key_double(f, key_scamin_id);
525
526 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
527 cs_var_cal_opt_t var_cal_opt;
528
529 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
530
531 const cs_real_t thetex = 1.-var_cal_opt.thetav;
532
533 const int kimasf = cs_field_key_id("inner_mass_flux_id");
534 const int kbmasf = cs_field_key_id("boundary_mass_flux_id");
535 const cs_real_t *restrict i_massflux =
536 cs_field_by_id( cs_field_get_key_int(f, kimasf) )->val;
537 const cs_real_t *restrict b_massflux =
538 cs_field_by_id( cs_field_get_key_int(f, kbmasf) )->val;
539
540 for (cs_lnum_t ii = n_cells; ii < n_cells_ext; ii++) {
541 num_inf[ii] = 0.;
542 num_sup[ii] = 0.;
543 }
544
545 # pragma omp parallel for
546 for (cs_lnum_t ii = 0; ii < n_cells; ii++) {
547 num_inf[ii] = rovsdt[ii] * (pvara[ii] -scalar_min);
548 num_sup[ii] = rovsdt[ii] * (scalar_max-pvara[ii]);
549 }
550
551 /* ---> Contribution from interior faces */
552
553 for (int g_id = 0; g_id < n_i_groups; g_id++) {
554 # pragma omp parallel for
555 for (int t_id = 0; t_id < n_i_threads; t_id++) {
556 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
557 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
558 face_id++) {
559
560 cs_lnum_t ii = i_face_cells[face_id][0];
561 cs_lnum_t jj = i_face_cells[face_id][1];
562
563 cs_real_t flui = 0.5*(i_massflux[face_id] + fabs(i_massflux[face_id]));
564 cs_real_t fluj = 0.5*(i_massflux[face_id] - fabs(i_massflux[face_id]));
565
566 cs_real_t pi = pvara[ii]-scalar_min;
567 cs_real_t pj = pvara[jj]-scalar_min;
568
569 num_inf[ii] -= thetex *(pi * flui + pj * fluj);
570 num_inf[jj] += thetex *(pj * fluj + pi * flui);
571
572 pi = scalar_max-pvara[ii];
573 pj = scalar_max-pvara[jj];
574
575 num_sup[ii] -= thetex *(pi * flui + pj * fluj);
576 num_sup[jj] += thetex *(pj * fluj + pi * flui);
577 }
578 }
579 }
580
581 /* ---> Contribution from boundary faces */
582
583 for (int g_id = 0; g_id < n_b_groups; g_id++) {
584 # pragma omp parallel for
585 for (int t_id = 0; t_id < n_b_threads; t_id++) {
586 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
587 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
588 face_id++) {
589
590 cs_lnum_t ii = b_face_cells[face_id];
591
592 cs_real_t flui = 0.5*(b_massflux[face_id]+fabs(b_massflux[face_id]));
593 cs_real_t fluf = 0.5*(b_massflux[face_id]-fabs(b_massflux[face_id]));
594 cs_real_t pfabor = inc*coefap[face_id]+coefbp[face_id]*pvara[ii];
595
596 num_inf[ii] -= thetex *( (pvara[ii]-scalar_min) * flui
597 + (pfabor -scalar_min) * fluf);
598 num_sup[ii] -= thetex *( (scalar_max-pvara[ii]) * flui
599 + (scalar_max-pfabor ) * fluf);
600 }
601 }
602 }
603 }
604
605 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
606
607 /*============================================================================
608 * Public function definitions for Fortran API
609 *============================================================================*/
610
611 /*----------------------------------------------------------------------------
612 * Wrapper to cs_face_diffusion_potential
613 *----------------------------------------------------------------------------*/
614
CS_PROCF(itrmas,ITRMAS)615 void CS_PROCF (itrmas, ITRMAS)
616 (
617 const int *const f_id,
618 const int *const init,
619 const int *const inc,
620 const int *const imrgra,
621 const int *const iccocg,
622 const int *const nswrgp,
623 const int *const imligp,
624 const int *const iphydp,
625 const int *const iwgrp,
626 const int *const iwarnp,
627 const cs_real_t *const epsrgp,
628 const cs_real_t *const climgp,
629 const cs_real_t *const extrap,
630 cs_real_3_t frcxt[],
631 cs_real_t pvar[],
632 const cs_real_t coefap[],
633 const cs_real_t coefbp[],
634 const cs_real_t cofafp[],
635 const cs_real_t cofbfp[],
636 const cs_real_t i_visc[],
637 const cs_real_t b_visc[],
638 cs_real_t visel[],
639 cs_real_t i_massflux[],
640 cs_real_t b_massflux[]
641 )
642 {
643 CS_UNUSED(extrap);
644
645 const cs_mesh_t *m = cs_glob_mesh;
646 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
647
648 cs_face_diffusion_potential(*f_id,
649 m,
650 fvq,
651 *init,
652 *inc,
653 *imrgra,
654 *iccocg,
655 *nswrgp,
656 *imligp,
657 *iphydp,
658 *iwgrp,
659 *iwarnp,
660 *epsrgp,
661 *climgp,
662 frcxt,
663 pvar,
664 coefap,
665 coefbp,
666 cofafp,
667 cofbfp,
668 i_visc,
669 b_visc,
670 visel,
671 i_massflux,
672 b_massflux);
673 }
674
675 /*----------------------------------------------------------------------------
676 * Wrapper to cs_face_anisotropic_diffusion_potential
677 *----------------------------------------------------------------------------*/
678
CS_PROCF(itrmav,ITRMAV)679 void CS_PROCF (itrmav, ITRMAV)
680 (
681 const int *const f_id,
682 const int *const init,
683 const int *const inc,
684 const int *const imrgra,
685 const int *const iccocg,
686 const int *const nswrgp,
687 const int *const imligp,
688 const int *const ircflp,
689 const int *const iphydp,
690 const int *const iwgrp,
691 const int *const iwarnp,
692 const cs_real_t *const epsrgp,
693 const cs_real_t *const climgp,
694 const cs_real_t *const extrap,
695 cs_real_3_t frcxt[],
696 cs_real_t pvar[],
697 const cs_real_t coefap[],
698 const cs_real_t coefbp[],
699 const cs_real_t cofafp[],
700 const cs_real_t cofbfp[],
701 const cs_real_t i_visc[],
702 const cs_real_t b_visc[],
703 cs_real_6_t viscel[],
704 const cs_real_2_t weighf[],
705 const cs_real_t weighb[],
706 cs_real_t i_massflux[],
707 cs_real_t b_massflux[]
708 )
709 {
710 CS_UNUSED(extrap);
711
712 const cs_mesh_t *m = cs_glob_mesh;
713 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
714
715 cs_face_anisotropic_diffusion_potential(*f_id,
716 m,
717 fvq,
718 *init,
719 *inc,
720 *imrgra,
721 *iccocg,
722 *nswrgp,
723 *imligp,
724 *ircflp,
725 *iphydp,
726 *iwgrp,
727 *iwarnp,
728 *epsrgp,
729 *climgp,
730 frcxt,
731 pvar,
732 coefap,
733 coefbp,
734 cofafp,
735 cofbfp,
736 i_visc,
737 b_visc,
738 viscel,
739 weighf,
740 weighb,
741 i_massflux,
742 b_massflux);
743 }
744
745 /*----------------------------------------------------------------------------
746 * Wrapper to cs_diffusion_potential
747 *----------------------------------------------------------------------------*/
748
CS_PROCF(itrgrp,ITRGRP)749 void CS_PROCF (itrgrp, ITRGRP)
750 (
751 const int *const f_id,
752 const int *const init,
753 const int *const inc,
754 const int *const imrgra,
755 const int *const iccocg,
756 const int *const nswrgp,
757 const int *const imligp,
758 const int *const iphydp,
759 const int *const iwgrp,
760 const int *const iwarnp,
761 const cs_real_t *const epsrgp,
762 const cs_real_t *const climgp,
763 const cs_real_t *const extrap,
764 cs_real_3_t frcxt[],
765 cs_real_t pvar[],
766 const cs_real_t coefap[],
767 const cs_real_t coefbp[],
768 const cs_real_t cofafp[],
769 const cs_real_t cofbfp[],
770 const cs_real_t i_visc[],
771 const cs_real_t b_visc[],
772 cs_real_t visel[],
773 cs_real_t diverg[]
774 )
775 {
776 CS_UNUSED(extrap);
777
778 const cs_mesh_t *m = cs_glob_mesh;
779 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
780
781 cs_diffusion_potential(*f_id,
782 m,
783 fvq,
784 *init,
785 *inc,
786 *imrgra,
787 *iccocg,
788 *nswrgp,
789 *imligp,
790 *iphydp,
791 *iwgrp,
792 *iwarnp,
793 *epsrgp,
794 *climgp,
795 frcxt,
796 pvar,
797 coefap,
798 coefbp,
799 cofafp,
800 cofbfp,
801 i_visc,
802 b_visc,
803 visel,
804 diverg);
805 }
806
807 /*----------------------------------------------------------------------------
808 * Wrapper to cs_anisotropic_diffusion_potential
809 *----------------------------------------------------------------------------*/
810
CS_PROCF(itrgrv,ITRGRV)811 void CS_PROCF (itrgrv, ITRGRV)
812 (
813 const int *const f_id,
814 const int *const init,
815 const int *const inc,
816 const int *const imrgra,
817 const int *const iccocg,
818 const int *const nswrgp,
819 const int *const imligp,
820 const int *const ircflp,
821 const int *const iphydp,
822 const int *const iwgrp,
823 const int *const iwarnp,
824 const cs_real_t *const epsrgp,
825 const cs_real_t *const climgp,
826 const cs_real_t *const extrap,
827 cs_real_3_t frcxt[],
828 cs_real_t pvar[],
829 const cs_real_t coefap[],
830 const cs_real_t coefbp[],
831 const cs_real_t cofafp[],
832 const cs_real_t cofbfp[],
833 const cs_real_t i_visc[],
834 const cs_real_t b_visc[],
835 cs_real_6_t viscel[],
836 const cs_real_2_t weighf[],
837 const cs_real_t weighb[],
838 cs_real_t diverg[]
839 )
840 {
841 CS_UNUSED(extrap);
842
843 const cs_mesh_t *m = cs_glob_mesh;
844 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
845
846 cs_anisotropic_diffusion_potential(*f_id,
847 m,
848 fvq,
849 *init,
850 *inc,
851 *imrgra,
852 *iccocg,
853 *nswrgp,
854 *imligp,
855 *ircflp,
856 *iphydp,
857 *iwgrp,
858 *iwarnp,
859 *epsrgp,
860 *climgp,
861 frcxt,
862 pvar,
863 coefap,
864 coefbp,
865 cofafp,
866 cofbfp,
867 i_visc,
868 b_visc,
869 viscel,
870 weighf,
871 weighb,
872 diverg);
873 }
874
875 /*============================================================================
876 * Public function definitions
877 *============================================================================*/
878
879 /*----------------------------------------------------------------------------*/
880 /*!
881 * \brief Compute the upwind gradient used in the slope tests.
882 *
883 * This function assumes the input gradient and pvar values have already
884 * been synchronized.
885 *
886 * \param[in] f_id field id
887 * \param[in] inc Not an increment flag
888 * \param[in] halo_type halo type
889 * \param[in] grad standard gradient
890 * \param[out] grdpa upwind gradient
891 * \param[in] pvar values
892 * \param[in] coefap boundary condition array for the variable
893 * (explicit part)
894 * \param[in] coefbp boundary condition array for the variable
895 * (implicit part)
896 * \param[in] i_massflux mass flux at interior faces
897 */
898 /*----------------------------------------------------------------------------*/
899
900 void
cs_slope_test_gradient(int f_id,int inc,cs_halo_type_t halo_type,const cs_real_3_t * grad,cs_real_3_t * grdpa,const cs_real_t * pvar,const cs_real_t * coefap,const cs_real_t * coefbp,const cs_real_t * i_massflux)901 cs_slope_test_gradient(int f_id,
902 int inc,
903 cs_halo_type_t halo_type,
904 const cs_real_3_t *grad,
905 cs_real_3_t *grdpa,
906 const cs_real_t *pvar,
907 const cs_real_t *coefap,
908 const cs_real_t *coefbp,
909 const cs_real_t *i_massflux)
910 {
911 CS_UNUSED(f_id);
912
913 const cs_mesh_t *m = cs_glob_mesh;
914 const cs_halo_t *halo = m->halo;
915 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
916
917 const cs_lnum_t n_cells = m->n_cells;
918
919 const cs_lnum_2_t *restrict i_face_cells
920 = (const cs_lnum_2_t *restrict)m->i_face_cells;
921 const cs_lnum_t *restrict b_face_cells
922 = (const cs_lnum_t *restrict)m->b_face_cells;
923 const cs_real_t *restrict cell_vol = fvq->cell_vol;
924 const cs_real_3_t *restrict cell_cen
925 = (const cs_real_3_t *restrict)fvq->cell_cen;
926 const cs_real_3_t *restrict i_face_normal
927 = (const cs_real_3_t *restrict)fvq->i_face_normal;
928 const cs_real_3_t *restrict b_face_normal
929 = (const cs_real_3_t *restrict)fvq->b_face_normal;
930 const cs_real_3_t *restrict i_face_cog
931 = (const cs_real_3_t *restrict)fvq->i_face_cog;
932 const cs_real_3_t *restrict diipb
933 = (const cs_real_3_t *restrict)fvq->diipb;
934
935 const int n_i_groups = m->i_face_numbering->n_groups;
936 const int n_i_threads = m->i_face_numbering->n_threads;
937 const int n_b_groups = m->b_face_numbering->n_groups;
938 const int n_b_threads = m->b_face_numbering->n_threads;
939 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
940 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
941
942 for (int g_id = 0; g_id < n_i_groups; g_id++) {
943 # pragma omp parallel for
944 for (int t_id = 0; t_id < n_i_threads; t_id++) {
945 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
946 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
947 face_id++) {
948
949 cs_lnum_t ii = i_face_cells[face_id][0];
950 cs_lnum_t jj = i_face_cells[face_id][1];
951
952 cs_real_t difx = i_face_cog[face_id][0] - cell_cen[ii][0];
953 cs_real_t dify = i_face_cog[face_id][1] - cell_cen[ii][1];
954 cs_real_t difz = i_face_cog[face_id][2] - cell_cen[ii][2];
955 cs_real_t djfx = i_face_cog[face_id][0] - cell_cen[jj][0];
956 cs_real_t djfy = i_face_cog[face_id][1] - cell_cen[jj][1];
957 cs_real_t djfz = i_face_cog[face_id][2] - cell_cen[jj][2];
958
959 cs_real_t pif = pvar[ii]
960 + difx*grad[ii][0]+dify*grad[ii][1]+difz*grad[ii][2];
961 cs_real_t pjf = pvar[jj]
962 + djfx*grad[jj][0]+djfy*grad[jj][1]+djfz*grad[jj][2];
963
964 cs_real_t pfac = pjf;
965 if (i_massflux[face_id] > 0.) pfac = pif;
966
967 cs_real_t pfac1 = pfac*i_face_normal[face_id][0];
968 cs_real_t pfac2 = pfac*i_face_normal[face_id][1];
969 cs_real_t pfac3 = pfac*i_face_normal[face_id][2];
970
971 grdpa[ii][0] = grdpa[ii][0] + pfac1;
972 grdpa[ii][1] = grdpa[ii][1] + pfac2;
973 grdpa[ii][2] = grdpa[ii][2] + pfac3;
974
975 grdpa[jj][0] = grdpa[jj][0] - pfac1;
976 grdpa[jj][1] = grdpa[jj][1] - pfac2;
977 grdpa[jj][2] = grdpa[jj][2] - pfac3;
978
979 }
980 }
981 }
982
983 for (int g_id = 0; g_id < n_b_groups; g_id++) {
984 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
985 for (int t_id = 0; t_id < n_b_threads; t_id++) {
986 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
987 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
988 face_id++) {
989
990 cs_lnum_t ii = b_face_cells[face_id];
991
992 cs_real_t pfac = inc*coefap[face_id] + coefbp[face_id]
993 * (pvar[ii] + cs_math_3_dot_product(grad[ii], diipb[face_id]));
994 grdpa[ii][0] = grdpa[ii][0] + pfac*b_face_normal[face_id][0];
995 grdpa[ii][1] = grdpa[ii][1] + pfac*b_face_normal[face_id][1];
996 grdpa[ii][2] = grdpa[ii][2] + pfac*b_face_normal[face_id][2];
997
998 }
999 }
1000 }
1001
1002 # pragma omp parallel for
1003 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
1004
1005 cs_real_t unsvol = 1./cell_vol[cell_id];
1006
1007 grdpa[cell_id][0] = grdpa[cell_id][0]*unsvol;
1008 grdpa[cell_id][1] = grdpa[cell_id][1]*unsvol;
1009 grdpa[cell_id][2] = grdpa[cell_id][2]*unsvol;
1010
1011 }
1012
1013 /* Synchronization for parallelism or periodicity */
1014
1015 if (halo != NULL) {
1016 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)grdpa, 3);
1017 if (cs_glob_mesh->n_init_perio > 0)
1018 cs_halo_perio_sync_var_vect(halo, CS_HALO_STANDARD, (cs_real_t *)grdpa, 3);
1019 }
1020
1021 }
1022
1023 /*----------------------------------------------------------------------------*/
1024 /*!
1025 * \brief Compute the upwind gradient used in the pure SOLU schemes
1026 * (observed in the litterature).
1027 *
1028 * \param[in] f_id field index
1029 * \param[in] inc Not an increment flag
1030 * \param[in] halo_type halo type
1031 * \param[in] coefap boundary condition array for the variable
1032 * (explicit part)
1033 * \param[in] coefbp boundary condition array for the variable
1034 * (implicit part)
1035 * \param[in] i_massflux mass flux at interior faces
1036 * \param[in] b_massflux mass flux at boundary faces
1037 * \param[in] pvar values
1038 * \param[out] grdpa upwind gradient
1039 */
1040 /*----------------------------------------------------------------------------*/
1041
1042 void
cs_upwind_gradient(const int f_id,const int inc,const cs_halo_type_t halo_type,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t i_massflux[],const cs_real_t b_massflux[],const cs_real_t * restrict pvar,cs_real_3_t * restrict grdpa)1043 cs_upwind_gradient(const int f_id,
1044 const int inc,
1045 const cs_halo_type_t halo_type,
1046 const cs_real_t coefap[],
1047 const cs_real_t coefbp[],
1048 const cs_real_t i_massflux[],
1049 const cs_real_t b_massflux[],
1050 const cs_real_t *restrict pvar,
1051 cs_real_3_t *restrict grdpa)
1052 {
1053 CS_UNUSED(f_id);
1054
1055 const cs_mesh_t *m = cs_glob_mesh;
1056 const cs_halo_t *halo = m->halo;
1057 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
1058
1059 const cs_lnum_t n_cells = m->n_cells;
1060
1061 const cs_lnum_2_t *restrict i_face_cells
1062 = (const cs_lnum_2_t *restrict)m->i_face_cells;
1063 const cs_lnum_t *restrict b_face_cells
1064 = (const cs_lnum_t *restrict)m->b_face_cells;
1065 const cs_real_t *restrict cell_vol = fvq->cell_vol;
1066 const cs_real_3_t *restrict i_face_normal
1067 = (const cs_real_3_t *restrict)fvq->i_face_normal;
1068 const cs_real_3_t *restrict b_face_normal
1069 = (const cs_real_3_t *restrict)fvq->b_face_normal;
1070
1071 const int n_i_groups = m->i_face_numbering->n_groups;
1072 const int n_i_threads = m->i_face_numbering->n_threads;
1073 const int n_b_groups = m->b_face_numbering->n_groups;
1074 const int n_b_threads = m->b_face_numbering->n_threads;
1075 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
1076 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
1077
1078 for (int g_id = 0; g_id < n_i_groups; g_id++) {
1079 # pragma omp parallel for
1080 for (int t_id = 0; t_id < n_i_threads; t_id++) {
1081 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
1082 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
1083 face_id++) {
1084
1085 cs_lnum_t ii = i_face_cells[face_id][0];
1086 cs_lnum_t jj = i_face_cells[face_id][1];
1087
1088 cs_real_t pif = pvar[ii];
1089 cs_real_t pjf = pvar[jj];
1090
1091 cs_real_t pfac = pjf;
1092 if (i_massflux[face_id] > 0.) pfac = pif;
1093
1094 cs_real_t pfac1 = pfac*i_face_normal[face_id][0];
1095 cs_real_t pfac2 = pfac*i_face_normal[face_id][1];
1096 cs_real_t pfac3 = pfac*i_face_normal[face_id][2];
1097
1098 grdpa[ii][0] = grdpa[ii][0] + pfac1;
1099 grdpa[ii][1] = grdpa[ii][1] + pfac2;
1100 grdpa[ii][2] = grdpa[ii][2] + pfac3;
1101
1102 grdpa[jj][0] = grdpa[jj][0] - pfac1;
1103 grdpa[jj][1] = grdpa[jj][1] - pfac2;
1104 grdpa[jj][2] = grdpa[jj][2] - pfac3;
1105
1106 }
1107 }
1108 }
1109
1110 for (int g_id = 0; g_id < n_b_groups; g_id++) {
1111 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
1112 for (int t_id = 0; t_id < n_b_threads; t_id++) {
1113 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
1114 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
1115 face_id++) {
1116
1117 cs_lnum_t ii = b_face_cells[face_id];
1118
1119 cs_real_t pfac = pvar[ii];
1120
1121 if (b_massflux[face_id] < 0)
1122 pfac = inc*coefap[face_id] + coefbp[face_id] * pvar[ii];
1123
1124 grdpa[ii][0] = grdpa[ii][0] + pfac*b_face_normal[face_id][0];
1125 grdpa[ii][1] = grdpa[ii][1] + pfac*b_face_normal[face_id][1];
1126 grdpa[ii][2] = grdpa[ii][2] + pfac*b_face_normal[face_id][2];
1127
1128 }
1129 }
1130 }
1131
1132 # pragma omp parallel for
1133 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
1134
1135 cs_real_t unsvol = 1./cell_vol[cell_id];
1136
1137 grdpa[cell_id][0] = grdpa[cell_id][0]*unsvol;
1138 grdpa[cell_id][1] = grdpa[cell_id][1]*unsvol;
1139 grdpa[cell_id][2] = grdpa[cell_id][2]*unsvol;
1140
1141 }
1142
1143 /* Synchronization for parallelism or periodicity */
1144
1145 if (halo != NULL) {
1146 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)grdpa, 3);
1147 if (cs_glob_mesh->n_init_perio > 0)
1148 cs_halo_perio_sync_var_vect(halo, halo_type, (cs_real_t *)grdpa, 3);
1149 }
1150 }
1151
1152 /*----------------------------------------------------------------------------*/
1153 /*!
1154 * \brief Compute the upwind gradient used in the slope tests.
1155 *
1156 * This function assumes the input gradient and pvar values have already
1157 * been synchronized.
1158 *
1159 * \param[in] inc Not an increment flag
1160 * \param[in] halo_type halo type
1161 * \param[in] grad standard gradient
1162 * \param[out] grdpa upwind gradient
1163 * \param[in] pvar values
1164 * \param[in] coefa boundary condition array for the variable
1165 (Explicit part)
1166 * \param[in] coefb boundary condition array for the variable
1167 (Implicit part)
1168 * \param[in] i_massflux mass flux at interior faces
1169 */
1170 /*----------------------------------------------------------------------------*/
1171
1172 void
cs_slope_test_gradient_vector(const int inc,const cs_halo_type_t halo_type,const cs_real_33_t * grad,cs_real_33_t * grdpa,const cs_real_3_t * pvar,const cs_real_3_t * coefa,const cs_real_33_t * coefb,const cs_real_t * i_massflux)1173 cs_slope_test_gradient_vector(const int inc,
1174 const cs_halo_type_t halo_type,
1175 const cs_real_33_t *grad,
1176 cs_real_33_t *grdpa,
1177 const cs_real_3_t *pvar,
1178 const cs_real_3_t *coefa,
1179 const cs_real_33_t *coefb,
1180 const cs_real_t *i_massflux)
1181 {
1182 const cs_mesh_t *m = cs_glob_mesh;
1183 const cs_halo_t *halo = m->halo;
1184 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
1185
1186 const cs_lnum_t n_cells = m->n_cells;
1187
1188 const cs_lnum_2_t *restrict i_face_cells
1189 = (const cs_lnum_2_t *restrict)m->i_face_cells;
1190 const cs_lnum_t *restrict b_face_cells
1191 = (const cs_lnum_t *restrict)m->b_face_cells;
1192 const cs_real_t *restrict cell_vol = fvq->cell_vol;
1193 const cs_real_3_t *restrict cell_cen
1194 = (const cs_real_3_t *restrict)fvq->cell_cen;
1195 const cs_real_3_t *restrict i_f_face_normal
1196 = (const cs_real_3_t *restrict)fvq->i_f_face_normal;
1197 const cs_real_3_t *restrict b_f_face_normal
1198 = (const cs_real_3_t *restrict)fvq->b_f_face_normal;
1199 const cs_real_3_t *restrict i_face_cog
1200 = (const cs_real_3_t *restrict)fvq->i_face_cog;
1201 const cs_real_3_t *restrict diipb
1202 = (const cs_real_3_t *restrict)fvq->diipb;
1203
1204 const int n_i_groups = m->i_face_numbering->n_groups;
1205 const int n_i_threads = m->i_face_numbering->n_threads;
1206 const int n_b_groups = m->b_face_numbering->n_groups;
1207 const int n_b_threads = m->b_face_numbering->n_threads;
1208 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
1209 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
1210
1211 for (int g_id = 0; g_id < n_i_groups; g_id++) {
1212 # pragma omp parallel for
1213 for (int t_id = 0; t_id < n_i_threads; t_id++) {
1214 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
1215 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
1216 face_id++) {
1217
1218 cs_real_t difv[3], djfv[3];
1219
1220 cs_lnum_t ii = i_face_cells[face_id][0];
1221 cs_lnum_t jj = i_face_cells[face_id][1];
1222
1223 for (int jsou = 0; jsou < 3; jsou++) {
1224 difv[jsou] = i_face_cog[face_id][jsou] - cell_cen[ii][jsou];
1225 djfv[jsou] = i_face_cog[face_id][jsou] - cell_cen[jj][jsou];
1226 }
1227
1228 /* x-y-z component, p = u, v, w */
1229
1230 for (int isou = 0; isou < 3; isou++) {
1231 cs_real_t pif = pvar[ii][isou];
1232 cs_real_t pjf = pvar[jj][isou];
1233 for (int jsou = 0; jsou < 3; jsou++) {
1234 pif = pif + grad[ii][isou][jsou]*difv[jsou];
1235 pjf = pjf + grad[jj][isou][jsou]*djfv[jsou];
1236 }
1237
1238 cs_real_t pfac = pjf;
1239 if (i_massflux[face_id] > 0.) pfac = pif;
1240
1241 /* U gradient */
1242
1243 cs_real_t vfac[3];
1244
1245 for (int jsou = 0; jsou < 3; jsou++) {
1246 vfac[jsou] = pfac*i_f_face_normal[face_id][jsou];
1247
1248 grdpa[ii][isou][jsou] = grdpa[ii][isou][jsou] + vfac[jsou];
1249 grdpa[jj][isou][jsou] = grdpa[jj][isou][jsou] - vfac[jsou];
1250 }
1251 }
1252
1253 }
1254 }
1255 }
1256
1257 for (int g_id = 0; g_id < n_b_groups; g_id++) {
1258 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
1259 for (int t_id = 0; t_id < n_b_threads; t_id++) {
1260 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
1261 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
1262 face_id++) {
1263
1264 cs_real_t diipbv[3];
1265 cs_lnum_t ii = b_face_cells[face_id];
1266
1267 for (int jsou = 0; jsou < 3; jsou++)
1268 diipbv[jsou] = diipb[face_id][jsou];
1269
1270 /* x-y-z components, p = u, v, w */
1271
1272 for (int isou = 0; isou < 3; isou++) {
1273 cs_real_t pfac = inc*coefa[face_id][isou];
1274 /*coefu is a matrix */
1275 for (int jsou = 0; jsou < 3; jsou++)
1276 pfac += coefb[face_id][jsou][isou]*( pvar[ii][jsou]
1277 + grad[ii][jsou][0]*diipbv[0]
1278 + grad[ii][jsou][1]*diipbv[1]
1279 + grad[ii][jsou][2]*diipbv[2]);
1280
1281 for (int jsou = 0; jsou < 3; jsou++)
1282 grdpa[ii][isou][jsou] += pfac*b_f_face_normal[face_id][jsou];
1283 }
1284
1285 }
1286 }
1287 }
1288
1289 # pragma omp parallel for
1290 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
1291 cs_real_t unsvol = 1./cell_vol[cell_id];
1292 for (int isou = 0; isou < 3; isou++) {
1293 for (int jsou = 0; jsou < 3; jsou++)
1294 grdpa[cell_id][isou][jsou] = grdpa[cell_id][isou][jsou]*unsvol;
1295 }
1296 }
1297
1298 /* Handle parallelism and periodicity */
1299
1300 if (halo != NULL) {
1301 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)grdpa, 9);
1302 if (m->n_init_perio > 0)
1303 cs_halo_perio_sync_var_sym_tens(halo, halo_type, (cs_real_t *)grdpa);
1304 }
1305 }
1306
1307 /*----------------------------------------------------------------------------*/
1308 /*!
1309 * \brief Compute the upwind gradient used in the slope tests.
1310 *
1311 * This function assumes the input gradient and pvar values have already
1312 * been synchronized.
1313 *
1314 * \param[in] inc Not an increment flag
1315 * \param[in] halo_type halo type
1316 * \param[in] grad standard gradient
1317 * \param[out] grdpa upwind gradient
1318 * \param[in] pvar values
1319 * \param[in] coefa boundary condition array for the variable
1320 (Explicit part)
1321 * \param[in] coefb boundary condition array for the variable
1322 (Implicit part)
1323 * \param[in] i_massflux mass flux at interior faces
1324 */
1325 /*----------------------------------------------------------------------------*/
1326
1327 void
cs_slope_test_gradient_tensor(const int inc,const cs_halo_type_t halo_type,const cs_real_63_t * grad,cs_real_63_t * grdpa,const cs_real_6_t * pvar,const cs_real_6_t * coefa,const cs_real_66_t * coefb,const cs_real_t * i_massflux)1328 cs_slope_test_gradient_tensor(const int inc,
1329 const cs_halo_type_t halo_type,
1330 const cs_real_63_t *grad,
1331 cs_real_63_t *grdpa,
1332 const cs_real_6_t *pvar,
1333 const cs_real_6_t *coefa,
1334 const cs_real_66_t *coefb,
1335 const cs_real_t *i_massflux)
1336 {
1337 const cs_mesh_t *m = cs_glob_mesh;
1338 const cs_halo_t *halo = m->halo;
1339 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
1340
1341 const cs_lnum_t n_cells = m->n_cells;
1342
1343 const cs_lnum_2_t *restrict i_face_cells
1344 = (const cs_lnum_2_t *restrict)m->i_face_cells;
1345 const cs_lnum_t *restrict b_face_cells
1346 = (const cs_lnum_t *restrict)m->b_face_cells;
1347 const cs_real_t *restrict cell_vol = fvq->cell_vol;
1348 const cs_real_3_t *restrict cell_cen
1349 = (const cs_real_3_t *restrict)fvq->cell_cen;
1350 const cs_real_3_t *restrict i_f_face_normal
1351 = (const cs_real_3_t *restrict)fvq->i_f_face_normal;
1352 const cs_real_3_t *restrict b_f_face_normal
1353 = (const cs_real_3_t *restrict)fvq->b_f_face_normal;
1354 const cs_real_3_t *restrict i_face_cog
1355 = (const cs_real_3_t *restrict)fvq->i_face_cog;
1356 const cs_real_3_t *restrict diipb
1357 = (const cs_real_3_t *restrict)fvq->diipb;
1358
1359 const int n_i_groups = m->i_face_numbering->n_groups;
1360 const int n_i_threads = m->i_face_numbering->n_threads;
1361 const int n_b_groups = m->b_face_numbering->n_groups;
1362 const int n_b_threads = m->b_face_numbering->n_threads;
1363 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
1364 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
1365
1366 for (int g_id = 0; g_id < n_i_groups; g_id++) {
1367 # pragma omp parallel for
1368 for (int t_id = 0; t_id < n_i_threads; t_id++) {
1369 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
1370 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
1371 face_id++) {
1372
1373 cs_real_t difv[3], djfv[3];
1374
1375 cs_lnum_t ii = i_face_cells[face_id][0];
1376 cs_lnum_t jj = i_face_cells[face_id][1];
1377
1378 for (int jsou = 0; jsou < 3; jsou++) {
1379 difv[jsou] = i_face_cog[face_id][jsou] - cell_cen[ii][jsou];
1380 djfv[jsou] = i_face_cog[face_id][jsou] - cell_cen[jj][jsou];
1381 }
1382
1383 /* x-y-z component, p = u, v, w */
1384
1385 for (int isou = 0; isou < 6; isou++) {
1386 cs_real_t pif = pvar[ii][isou];
1387 cs_real_t pjf = pvar[jj][isou];
1388 for (int jsou = 0; jsou < 3; jsou++) {
1389 pif = pif + grad[ii][isou][jsou]*difv[jsou];
1390 pjf = pjf + grad[jj][isou][jsou]*djfv[jsou];
1391 }
1392
1393 cs_real_t pfac = pjf;
1394 if (i_massflux[face_id] > 0.) pfac = pif;
1395
1396 /* U gradient */
1397
1398 cs_real_t vfac[3];
1399
1400 for (int jsou = 0; jsou < 3; jsou++) {
1401 vfac[jsou] = pfac*i_f_face_normal[face_id][jsou];
1402
1403 grdpa[ii][isou][jsou] = grdpa[ii][isou][jsou] + vfac[jsou];
1404 grdpa[jj][isou][jsou] = grdpa[jj][isou][jsou] - vfac[jsou];
1405 }
1406 }
1407
1408 }
1409 }
1410 }
1411
1412 for (int g_id = 0; g_id < n_b_groups; g_id++) {
1413 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
1414 for (int t_id = 0; t_id < n_b_threads; t_id++) {
1415 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
1416 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
1417 face_id++) {
1418
1419 cs_real_t diipbv[3];
1420 cs_lnum_t ii = b_face_cells[face_id];
1421
1422 for (int jsou = 0; jsou < 3; jsou++)
1423 diipbv[jsou] = diipb[face_id][jsou];
1424
1425 /* x-y-z components, p = u, v, w */
1426
1427 for (int isou = 0; isou < 6; isou++) {
1428 cs_real_t pfac = inc*coefa[face_id][isou];
1429 /*coefu is a matrix */
1430 for (int jsou = 0; jsou < 6; jsou++)
1431 pfac += coefb[face_id][jsou][isou]*( pvar[ii][jsou]
1432 + grad[ii][jsou][0]*diipbv[0]
1433 + grad[ii][jsou][1]*diipbv[1]
1434 + grad[ii][jsou][2]*diipbv[2]);
1435
1436 for (int jsou = 0; jsou < 3; jsou++)
1437 grdpa[ii][isou][jsou] += pfac*b_f_face_normal[face_id][jsou];
1438 }
1439
1440 }
1441 }
1442 }
1443
1444 # pragma omp parallel for
1445 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
1446 cs_real_t unsvol = 1./cell_vol[cell_id];
1447 for (int isou = 0; isou < 6; isou++) {
1448 for (int jsou = 0; jsou < 3; jsou++)
1449 grdpa[cell_id][isou][jsou] = grdpa[cell_id][isou][jsou]*unsvol;
1450 }
1451 }
1452
1453 /* Handle parallelism and periodicity */
1454
1455 if (halo != NULL) {
1456 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)grdpa, 18);
1457 if (m->n_init_perio > 0)
1458 cs_halo_perio_sync_var_sym_tens(halo, halo_type, (cs_real_t *)grdpa);
1459 }
1460 }
1461
1462 /*----------------------------------------------------------------------------*/
1463 /*!
1464 * \brief Compute the beta blending coefficient of the
1465 * beta limiter (ensuring preservation of a given min/max pair of values).
1466 *
1467 * \param[in] f_id field id
1468 * \param[in] inc "not an increment" flag
1469 * \param[in] rovsdt rho * volume / dt
1470 */
1471 /*----------------------------------------------------------------------------*/
1472
1473 void
cs_beta_limiter_building(int f_id,int inc,const cs_real_t rovsdt[])1474 cs_beta_limiter_building(int f_id,
1475 int inc,
1476 const cs_real_t rovsdt[])
1477 {
1478 const cs_mesh_t *m = cs_glob_mesh;
1479 const cs_halo_t *halo = m->halo;
1480 const cs_lnum_t n_cells = m->n_cells;
1481 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
1482
1483 /* Get options from the field */
1484
1485 cs_field_t *f = cs_field_by_id(f_id);
1486 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
1487 cs_var_cal_opt_t var_cal_opt;
1488
1489 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
1490
1491 if (var_cal_opt.isstpc != 2)
1492 return;
1493
1494 cs_real_t* cpro_beta = cs_field_by_id(
1495 cs_field_get_key_int(f, cs_field_key_id("convection_limiter_id")))->val;
1496
1497 cs_real_t* denom_inf;
1498 cs_real_t* num_inf;
1499 cs_real_t* denom_sup;
1500 cs_real_t* num_sup;
1501
1502 BFT_MALLOC(denom_inf, n_cells_ext, cs_real_t);
1503 BFT_MALLOC(denom_sup, n_cells_ext, cs_real_t);
1504 BFT_MALLOC(num_inf, n_cells_ext, cs_real_t);
1505 BFT_MALLOC(num_sup, n_cells_ext, cs_real_t);
1506
1507 /* computation of the denominator for the inferior and superior bound */
1508
1509 _beta_limiter_denom(f_id,
1510 inc,
1511 denom_inf,
1512 denom_sup);
1513
1514 /* computation of the numerator for the inferior and superior bound */
1515
1516 _beta_limiter_num(f_id,
1517 inc,
1518 rovsdt,
1519 num_inf,
1520 num_sup);
1521
1522 # pragma omp parallel for
1523 for (cs_lnum_t ii = 0; ii < n_cells; ii++) {
1524
1525 /* Treatment of the inferior bound */
1526 cs_real_t beta_inf;
1527 if (denom_inf[ii] <= num_inf[ii]) {
1528 beta_inf = 1.;
1529 }
1530 else if (denom_inf[ii] <= CS_ABS(num_inf[ii])) {
1531 beta_inf = -1.;
1532 }
1533 else {
1534 beta_inf = num_inf[ii]/denom_inf[ii]; //FIXME division by 0
1535 beta_inf = CS_MIN(beta_inf, 1.);
1536 }
1537
1538 /* Treatment of the superior bound */
1539 cs_real_t beta_sup;
1540 if (denom_sup[ii] <= num_sup[ii]) {
1541 beta_sup = 1.;
1542 }
1543 else if (denom_sup[ii] <= CS_ABS(num_sup[ii])) {
1544 beta_sup = -1.;
1545 }
1546 else {
1547 beta_sup = num_sup[ii]/denom_sup[ii]; //FIXME division by 0
1548 beta_sup = CS_MIN(beta_sup, 1.);
1549 }
1550
1551 cpro_beta[ii] = CS_MIN(beta_inf, beta_sup);
1552 }
1553
1554 /* Synchronize variable */
1555 if (halo != NULL)
1556 cs_halo_sync_var(halo, CS_HALO_STANDARD, cpro_beta);
1557
1558 BFT_FREE(denom_inf);
1559 BFT_FREE(num_inf);
1560 BFT_FREE(denom_sup);
1561 BFT_FREE(num_sup);
1562 }
1563
1564 /*----------------------------------------------------------------------------*/
1565 /*!
1566 * <a name="cs_convection_diffusion_scalar"></a>
1567 *
1568 * \brief Add the explicit part of the convection/diffusion terms of a
1569 * standard transport equation of a scalar field \f$ \varia \f$.
1570 *
1571 * More precisely, the right hand side \f$ Rhs \f$ is updated as
1572 * follows:
1573 * \f[
1574 * Rhs = Rhs - \sum_{\fij \in \Facei{\celli}} \left(
1575 * \dot{m}_\ij \left( \varia_\fij - \varia_\celli \right)
1576 * - \mu_\fij \gradv_\fij \varia \cdot \vect{S}_\ij \right)
1577 * \f]
1578 *
1579 * Warning:
1580 * - \f$ Rhs \f$ has already been initialized before calling bilsc2!
1581 * - mind the sign minus
1582 *
1583 * Please refer to the
1584 * <a href="../../theory.pdf#bilsc2"><b>bilsc2</b></a> section of the
1585 * theory guide for more informations.
1586 *
1587 * \param[in] idtvar indicator of the temporal scheme
1588 * \param[in] f_id field id (or -1)
1589 * \param[in] var_cal_opt variable calculation options
1590 * \param[in] icvflb global indicator of boundary convection flux
1591 * - 0 upwind scheme at all boundary faces
1592 * - 1 imposed flux at some boundary faces
1593 * \param[in] inc indicator
1594 * - 0 when solving an increment
1595 * - 1 otherwise
1596 * \param[in] iccocg indicator
1597 * - 1 re-compute cocg matrix
1598 * (for iterative gradients)
1599 * - 0 otherwise
1600 * \param[in] imasac take mass accumulation into account?
1601 * \param[in] pvar solved variable (current time step)
1602 * \param[in] pvara solved variable (previous time step)
1603 * \param[in] icvfli boundary face indicator array of convection flux
1604 * - 0 upwind scheme
1605 * - 1 imposed flux
1606 * \param[in] coefap boundary condition array for the variable
1607 * (explicit part)
1608 * \param[in] coefbp boundary condition array for the variable
1609 * (implicit part)
1610 * \param[in] cofafp boundary condition array for the diffusion
1611 * of the variable (explicit part)
1612 * \param[in] cofbfp boundary condition array for the diffusion
1613 * of the variable (implicit part)
1614 * \param[in] i_massflux mass flux at interior faces
1615 * \param[in] b_massflux mass flux at boundary faces
1616 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
1617 * at interior faces for the r.h.s.
1618 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
1619 * at border faces for the r.h.s.
1620 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
1621 */
1622 /*----------------------------------------------------------------------------*/
1623
1624 void
cs_convection_diffusion_scalar(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int icvflb,int inc,int iccocg,int imasac,cs_real_t * restrict pvar,const cs_real_t * restrict pvara,const int icvfli[],const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_massflux[],const cs_real_t b_massflux[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_t * restrict rhs)1625 cs_convection_diffusion_scalar(int idtvar,
1626 int f_id,
1627 const cs_var_cal_opt_t var_cal_opt,
1628 int icvflb,
1629 int inc,
1630 int iccocg,
1631 int imasac,
1632 cs_real_t *restrict pvar,
1633 const cs_real_t *restrict pvara,
1634 const int icvfli[],
1635 const cs_real_t coefap[],
1636 const cs_real_t coefbp[],
1637 const cs_real_t cofafp[],
1638 const cs_real_t cofbfp[],
1639 const cs_real_t i_massflux[],
1640 const cs_real_t b_massflux[],
1641 const cs_real_t i_visc[],
1642 const cs_real_t b_visc[],
1643 cs_real_t *restrict rhs)
1644 {
1645 const int iconvp = var_cal_opt.iconv;
1646 const int idiffp = var_cal_opt.idiff;
1647 const int nswrgp = var_cal_opt.nswrgr;
1648 const int imrgra = var_cal_opt.imrgra;
1649 const int imligp = var_cal_opt.imligr;
1650 const int ircflp = var_cal_opt.ircflu;
1651 const int ischcp = var_cal_opt.ischcv;
1652 const int isstpp = var_cal_opt.isstpc;
1653 const int iwarnp = var_cal_opt.verbosity;
1654 const int icoupl = var_cal_opt.icoupl;
1655 int limiter_choice = -1;
1656 const double blencp = var_cal_opt.blencv;
1657 const double blend_st = var_cal_opt.blend_st;
1658 const double epsrgp = var_cal_opt.epsrgr;
1659 const double climgp = var_cal_opt.climgr;
1660 const double relaxp = var_cal_opt.relaxv;
1661 const double thetap = var_cal_opt.thetav;
1662
1663 const cs_mesh_t *m = cs_glob_mesh;
1664 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
1665
1666 const cs_lnum_t n_cells = m->n_cells;
1667 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
1668 const int n_i_groups = m->i_face_numbering->n_groups;
1669 const int n_i_threads = m->i_face_numbering->n_threads;
1670 const int n_b_groups = m->b_face_numbering->n_groups;
1671 const int n_b_threads = m->b_face_numbering->n_threads;
1672 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
1673 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
1674
1675 const cs_lnum_2_t *restrict i_face_cells
1676 = (const cs_lnum_2_t *restrict)m->i_face_cells;
1677 const cs_lnum_t *restrict b_face_cells
1678 = (const cs_lnum_t *restrict)m->b_face_cells;
1679 const cs_real_t *restrict weight = fvq->weight;
1680 const cs_real_t *restrict i_dist = fvq->i_dist;
1681 const cs_real_t *restrict i_face_surf = fvq->i_face_surf;
1682 const cs_real_t *restrict cell_vol = fvq->cell_vol;
1683 const cs_real_3_t *restrict cell_cen
1684 = (const cs_real_3_t *restrict)fvq->cell_cen;
1685 const cs_real_3_t *restrict i_face_normal
1686 = (const cs_real_3_t *restrict)fvq->i_face_normal;
1687 const cs_real_3_t *restrict i_face_cog
1688 = (const cs_real_3_t *restrict)fvq->i_face_cog;
1689 const cs_real_3_t *restrict diipf
1690 = (const cs_real_3_t *restrict)fvq->diipf;
1691 const cs_real_3_t *restrict djjpf
1692 = (const cs_real_3_t *restrict)fvq->djjpf;
1693 const cs_real_3_t *restrict diipb
1694 = (const cs_real_3_t *restrict)fvq->diipb;
1695
1696 const int *bc_type = cs_glob_bc_type;
1697
1698 /* Local variables */
1699
1700 char var_name[64];
1701
1702 int iupwin = 0;
1703 int w_stride = 1;
1704
1705 bool recompute_cocg = (iccocg) ? true : false;
1706
1707 cs_real_t *coface = NULL, *cofbce = NULL;
1708
1709 cs_real_3_t *grad;
1710 cs_real_3_t *gradup = NULL;
1711 cs_real_3_t *gradst = NULL;
1712 cs_field_t *f = NULL;
1713
1714 cs_real_t *local_min = NULL;
1715 cs_real_t *local_max = NULL;
1716 cs_real_t *courant = NULL;
1717
1718 cs_real_t *cv_limiter = NULL;
1719 cs_real_t *df_limiter = NULL;
1720
1721 cs_real_t *gweight = NULL;
1722
1723 const int key_lim_choice = cs_field_key_id("limiter_choice");
1724
1725 cs_real_t *v_slope_test = cs_get_v_slope_test(f_id, var_cal_opt);
1726
1727 /* Internal coupling variables */
1728 cs_real_t *pvar_local = NULL;
1729 cs_real_t *pvar_distant = NULL;
1730 cs_real_t *df_limiter_local = NULL;
1731 int coupling_id = -1;
1732 cs_lnum_t n_local = 0, n_distant = 0;
1733 const cs_lnum_t *faces_local = NULL, *faces_distant = NULL;
1734 cs_internal_coupling_t *cpl = NULL;
1735
1736 /* Initialization */
1737
1738 /* Allocate work arrays */
1739
1740 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
1741
1742 /* Choose gradient type */
1743
1744 cs_halo_type_t halo_type = CS_HALO_STANDARD;
1745 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
1746
1747 cs_gradient_type_by_imrgra(imrgra,
1748 &gradient_type,
1749 &halo_type);
1750
1751 /* Handle cases where only the previous values (already synchronized)
1752 or current values are provided */
1753
1754 if (pvar != NULL)
1755 cs_sync_scalar_halo(m, pvar);
1756 if (pvara == NULL)
1757 pvara = (const cs_real_t *restrict)pvar;
1758
1759 const cs_real_t *restrict _pvar = (pvar != NULL) ? pvar : pvara;
1760
1761 /* Limiters */
1762
1763 if (f_id != -1) {
1764 f = cs_field_by_id(f_id);
1765
1766 /* NVD/TVD limiters */
1767 if (ischcp == 4) {
1768 limiter_choice = cs_field_get_key_int(f, key_lim_choice);
1769 BFT_MALLOC(local_max, n_cells_ext, cs_real_t);
1770 BFT_MALLOC(local_min, n_cells_ext, cs_real_t);
1771 cs_field_local_extrema_scalar(f_id,
1772 halo_type,
1773 local_max,
1774 local_min);
1775 if (limiter_choice >= CS_NVD_VOF_HRIC) {
1776 BFT_MALLOC(courant, n_cells_ext, cs_real_t);
1777 cs_cell_courant_number(f_id, courant);
1778 }
1779 }
1780
1781 int cv_limiter_id =
1782 cs_field_get_key_int(f, cs_field_key_id("convection_limiter_id"));
1783 if (cv_limiter_id > -1)
1784 cv_limiter = cs_field_by_id(cv_limiter_id)->val;
1785
1786 int df_limiter_id =
1787 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
1788 if (df_limiter_id > -1)
1789 df_limiter = cs_field_by_id(df_limiter_id)->val;
1790
1791 snprintf(var_name, 63, "%s", f->name);
1792 }
1793 else if (isstpp > 1) {
1794 bft_error(__FILE__, __LINE__, 0,
1795 _("invalid value of isstpp for a work array"));
1796 } else {
1797 strncpy(var_name, "[scalar convection-diffusion]", 63);
1798 }
1799 var_name[63] = '\0';
1800
1801 if (iwarnp >= 2) {
1802 if (ischcp == 1) {
1803 bft_printf(
1804 _(" %s: Convection in centered blending with %f percent of upwind\n"),
1805 var_name, (1.-blencp)*100.);
1806 } else {
1807 bft_printf(
1808 _(" %s: Convection in 2nd order blending with %f percent of upwind\n"),
1809 var_name, (1.-blencp)*100.);
1810 }
1811 }
1812
1813 iupwin = (blencp > 0.) ? 0 : 1;
1814
1815 if (icoupl > 0) {
1816 assert(f_id != -1);
1817 const int coupling_key_id = cs_field_key_id("coupling_entity");
1818 coupling_id = cs_field_get_key_int(f, coupling_key_id);
1819 cpl = cs_internal_coupling_by_id(coupling_id);
1820 cs_internal_coupling_coupled_faces(cpl,
1821 &n_local,
1822 &faces_local,
1823 &n_distant,
1824 &faces_distant);
1825 }
1826
1827 /* Compute the balance with reconstruction */
1828
1829 /* Compute the gradient of the variable */
1830
1831 /* The gradient (grad) is used in the flux reconstruction and the slope test.
1832 Thus we must compute it:
1833 - when we have diffusion and we reconstruct the fluxes,
1834 - when the convection scheme is the legacy SOLU,
1835 - when we have convection, we are not in pure upwind
1836 and we reconstruct the fluxes,
1837 - when we have convection, we are not in pure upwind
1838 and we have not shunted the slope test,
1839 - when we use NVD / TVD schemes.
1840 */
1841
1842 if ( (idiffp != 0 && ircflp == 1)
1843 || ( iconvp != 0 && iupwin == 0
1844 && (ischcp == 0 || ircflp == 1 || isstpp == 0 || ischcp == 3 || ischcp == 4))) {
1845
1846 if (f_id != -1) {
1847 /* Get the calculation option from the field */
1848 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
1849 if (var_cal_opt.idiff > 0) {
1850 int key_id = cs_field_key_id("gradient_weighting_id");
1851 int diff_id = cs_field_get_key_int(f, key_id);
1852 if (diff_id > -1) {
1853 cs_field_t *weight_f = cs_field_by_id(diff_id);
1854 gweight = weight_f->val;
1855 w_stride = weight_f->dim;
1856 cs_field_synchronize(weight_f, halo_type);
1857 }
1858 }
1859 }
1860 }
1861
1862 cs_gradient_scalar_synced_input(var_name,
1863 gradient_type,
1864 halo_type,
1865 inc,
1866 recompute_cocg,
1867 nswrgp,
1868 0, /* hyd_p_flag */
1869 w_stride,
1870 iwarnp,
1871 imligp,
1872 epsrgp,
1873 climgp,
1874 NULL, /* f_ext exterior force */
1875 coefap,
1876 coefbp,
1877 _pvar,
1878 gweight, /* Weighted gradient */
1879 cpl,
1880 grad);
1881
1882 } else {
1883
1884 # pragma omp parallel for
1885 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
1886 grad[cell_id][0] = 0.;
1887 grad[cell_id][1] = 0.;
1888 grad[cell_id][2] = 0.;
1889 }
1890 }
1891
1892 /* Compute gradients used in convection schemes */
1893
1894 if (iconvp > 0 && iupwin == 0) {
1895
1896 /* Compute cell gradient used in slope test */
1897 if (isstpp == 0) {
1898
1899 BFT_MALLOC(gradst, n_cells_ext, cs_real_3_t);
1900
1901 # pragma omp parallel for
1902 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
1903 gradst[cell_id][0] = 0.;
1904 gradst[cell_id][1] = 0.;
1905 gradst[cell_id][2] = 0.;
1906 }
1907
1908 cs_slope_test_gradient(f_id,
1909 inc,
1910 halo_type,
1911 (const cs_real_3_t *)grad,
1912 gradst,
1913 _pvar,
1914 coefap,
1915 coefbp,
1916 i_massflux);
1917
1918 }
1919
1920 /* Pure SOLU scheme */
1921 if (ischcp == 2) {
1922
1923 BFT_MALLOC(gradup, n_cells_ext, cs_real_3_t);
1924
1925 # pragma omp parallel for
1926 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
1927 gradup[cell_id][0] = 0.;
1928 gradup[cell_id][1] = 0.;
1929 gradup[cell_id][2] = 0.;
1930 }
1931
1932 cs_upwind_gradient(f_id,
1933 inc,
1934 halo_type,
1935 coefap,
1936 coefbp,
1937 i_massflux,
1938 b_massflux,
1939 _pvar,
1940 gradup);
1941
1942 }
1943
1944 }
1945
1946 /* ======================================================================
1947 ---> Contribution from interior faces
1948 ======================================================================*/
1949
1950 cs_gnum_t n_upwind = 0;
1951
1952 if (n_cells_ext>n_cells) {
1953 # pragma omp parallel for if(n_cells_ext - n_cells > CS_THR_MIN)
1954 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
1955 rhs[cell_id] = 0.;
1956 }
1957 }
1958
1959 /* --> Pure upwind flux
1960 =====================*/
1961
1962 if (iupwin == 1) {
1963
1964 /* Steady */
1965 if (idtvar < 0) {
1966
1967 for (int g_id = 0; g_id < n_i_groups; g_id++) {
1968 # pragma omp parallel for reduction(+:n_upwind)
1969 for (int t_id = 0; t_id < n_i_threads; t_id++) {
1970 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
1971 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
1972 face_id++) {
1973
1974 cs_lnum_t ii = i_face_cells[face_id][0];
1975 cs_lnum_t jj = i_face_cells[face_id][1];
1976
1977 /* in parallel, face will be counted by one and only one rank */
1978 if (ii < n_cells) {
1979 n_upwind++;
1980 }
1981
1982 cs_real_2_t fluxij = {0.,0.};
1983
1984 cs_real_t pifri, pjfri, pifrj, pjfrj;
1985 cs_real_t pip, pjp, pipr, pjpr;
1986
1987 cs_real_t bldfrp = (cs_real_t) ircflp;
1988 /* Local limitation of the reconstruction */
1989 if (df_limiter != NULL && ircflp > 0)
1990 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
1991
1992 cs_i_cd_steady_upwind(bldfrp,
1993 relaxp,
1994 diipf[face_id],
1995 djjpf[face_id],
1996 grad[ii],
1997 grad[jj],
1998 _pvar[ii],
1999 _pvar[jj],
2000 pvara[ii],
2001 pvara[jj],
2002 &pifri,
2003 &pifrj,
2004 &pjfri,
2005 &pjfrj,
2006 &pip,
2007 &pjp,
2008 &pipr,
2009 &pjpr);
2010
2011 cs_i_conv_flux(iconvp,
2012 1.,
2013 1,
2014 _pvar[ii],
2015 _pvar[jj],
2016 pifri,
2017 pifrj,
2018 pjfri,
2019 pjfrj,
2020 i_massflux[face_id],
2021 1., /* xcpp */
2022 1., /* xcpp */
2023 fluxij);
2024
2025 cs_i_diff_flux(idiffp,
2026 1.,
2027 pip,
2028 pjp,
2029 pipr,
2030 pjpr,
2031 i_visc[face_id],
2032 fluxij);
2033
2034 rhs[ii] -= fluxij[0];
2035 rhs[jj] += fluxij[1];
2036
2037 }
2038 }
2039 }
2040
2041 /* Unsteady */
2042 } else {
2043
2044 for (int g_id = 0; g_id < n_i_groups; g_id++) {
2045 # pragma omp parallel for reduction(+:n_upwind)
2046 for (int t_id = 0; t_id < n_i_threads; t_id++) {
2047 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
2048 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
2049 face_id++) {
2050
2051 cs_lnum_t ii = i_face_cells[face_id][0];
2052 cs_lnum_t jj = i_face_cells[face_id][1];
2053
2054 /* in parallel, face will be counted by one and only one rank */
2055 if (ii < n_cells) {
2056 n_upwind++;
2057 }
2058
2059 cs_real_2_t fluxij = {0.,0.};
2060
2061 cs_real_t pif, pjf;
2062 cs_real_t pip, pjp;
2063
2064 cs_real_t bldfrp = (cs_real_t) ircflp;
2065 /* Local limitation of the reconstruction */
2066 if (df_limiter != NULL && ircflp > 0)
2067 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
2068
2069 cs_i_cd_unsteady_upwind(bldfrp,
2070 diipf[face_id],
2071 djjpf[face_id],
2072 grad[ii],
2073 grad[jj],
2074 _pvar[ii],
2075 _pvar[jj],
2076 &pif,
2077 &pjf,
2078 &pip,
2079 &pjp);
2080
2081 cs_i_conv_flux(iconvp,
2082 thetap,
2083 imasac,
2084 _pvar[ii],
2085 _pvar[jj],
2086 pif,
2087 pif, /* no relaxation */
2088 pjf,
2089 pjf, /* no relaxation */
2090 i_massflux[face_id],
2091 1., /* xcpp */
2092 1., /* xcpp */
2093 fluxij);
2094
2095 cs_i_diff_flux(idiffp,
2096 thetap,
2097 pip,
2098 pjp,
2099 pip,/* no relaxation */
2100 pjp,/* no relaxation */
2101 i_visc[face_id],
2102 fluxij);
2103
2104 rhs[ii] -= fluxij[0];
2105 rhs[jj] += fluxij[1];
2106
2107 }
2108 }
2109 }
2110
2111 }
2112
2113 /* --> Flux with no slope test or Min/Max Beta limiter
2114 ====================================================*/
2115
2116 } else if (isstpp == 1 || isstpp == 2) {
2117
2118 if (ischcp < 0 || ischcp > 4) {
2119 bft_error(__FILE__, __LINE__, 0,
2120 _("invalid value of ischcv"));
2121 }
2122
2123 /* Steady */
2124 if (idtvar < 0) {
2125
2126 for (int g_id = 0; g_id < n_i_groups; g_id++) {
2127 # pragma omp parallel for
2128 for (int t_id = 0; t_id < n_i_threads; t_id++) {
2129 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
2130 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
2131 face_id++) {
2132
2133 cs_lnum_t ii = i_face_cells[face_id][0];
2134 cs_lnum_t jj = i_face_cells[face_id][1];
2135
2136 cs_real_2_t fluxij = {0.,0.};
2137
2138 cs_real_t pifri, pjfri, pifrj, pjfrj;
2139 cs_real_t pip, pjp, pipr, pjpr;
2140
2141 cs_real_t bldfrp = (cs_real_t) ircflp;
2142 /* Local limitation of the reconstruction */
2143 if (df_limiter != NULL && ircflp > 0)
2144 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
2145
2146 cs_i_cd_steady(bldfrp,
2147 ischcp,
2148 relaxp,
2149 blencp,
2150 weight[face_id],
2151 cell_cen[ii],
2152 cell_cen[jj],
2153 i_face_cog[face_id],
2154 diipf[face_id],
2155 djjpf[face_id],
2156 grad[ii],
2157 grad[jj],
2158 gradup[ii],
2159 gradup[jj],
2160 _pvar[ii],
2161 _pvar[jj],
2162 pvara[ii],
2163 pvara[jj],
2164 &pifri,
2165 &pifrj,
2166 &pjfri,
2167 &pjfrj,
2168 &pip,
2169 &pjp,
2170 &pipr,
2171 &pjpr);
2172
2173 cs_i_conv_flux(iconvp,
2174 1.,
2175 1,
2176 _pvar[ii],
2177 _pvar[jj],
2178 pifri,
2179 pifrj,
2180 pjfri,
2181 pjfrj,
2182 i_massflux[face_id],
2183 1., /* xcpp */
2184 1., /* xcpp */
2185 fluxij);
2186
2187 cs_i_diff_flux(idiffp,
2188 1.,
2189 pip,
2190 pjp,
2191 pipr,
2192 pjpr,
2193 i_visc[face_id],
2194 fluxij);
2195
2196 rhs[ii] -= fluxij[0];
2197 rhs[jj] += fluxij[1];
2198
2199 }
2200 }
2201 }
2202
2203 /* Unsteady */
2204 } else {
2205
2206 for (int g_id = 0; g_id < n_i_groups; g_id++) {
2207 # pragma omp parallel for
2208 for (int t_id = 0; t_id < n_i_threads; t_id++) {
2209 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
2210 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
2211 face_id++) {
2212
2213 cs_lnum_t ii = i_face_cells[face_id][0];
2214 cs_lnum_t jj = i_face_cells[face_id][1];
2215
2216 cs_real_t beta = blencp;
2217
2218 cs_real_t pif, pjf;
2219 cs_real_t pip, pjp;
2220
2221 /* Beta blending coefficient ensuring positivity of the scalar */
2222 if (isstpp == 2) {
2223 beta = CS_MAX(CS_MIN(cv_limiter[ii], cv_limiter[jj]), 0.);
2224 }
2225
2226 cs_real_2_t fluxij = {0.,0.};
2227
2228 cs_real_t bldfrp = (cs_real_t) ircflp;
2229 /* Local limitation of the reconstruction */
2230 if (df_limiter != NULL && ircflp > 0)
2231 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
2232
2233 if (ischcp != 4) {
2234 cs_real_t hybrid_coef_ii, hybrid_coef_jj;
2235 if (ischcp == 3) {
2236 hybrid_coef_ii = CS_F_(hybrid_blend)->val[ii];
2237 hybrid_coef_jj = CS_F_(hybrid_blend)->val[jj];
2238 } else {
2239 hybrid_coef_ii = 0.;
2240 hybrid_coef_jj = 0.;
2241 }
2242 cs_i_cd_unsteady(bldfrp,
2243 ischcp,
2244 beta,
2245 weight[face_id],
2246 cell_cen[ii],
2247 cell_cen[jj],
2248 i_face_cog[face_id],
2249 hybrid_coef_ii,
2250 hybrid_coef_jj,
2251 diipf[face_id],
2252 djjpf[face_id],
2253 grad[ii],
2254 grad[jj],
2255 gradup[ii],
2256 gradup[jj],
2257 _pvar[ii],
2258 _pvar[jj],
2259 &pif,
2260 &pjf,
2261 &pip,
2262 &pjp);
2263
2264 cs_i_conv_flux(iconvp,
2265 thetap,
2266 imasac,
2267 _pvar[ii],
2268 _pvar[jj],
2269 pif,
2270 pif, /* no relaxation */
2271 pjf,
2272 pjf, /* no relaxation */
2273 i_massflux[face_id],
2274 1., /* xcpp */
2275 1., /* xcpp */
2276 fluxij);
2277
2278 } else {
2279 /* NVD/TVD family of high accuracy schemes */
2280
2281 cs_lnum_t ic, id;
2282
2283 /* Determine central and downwind sides w.r.t. current face */
2284 cs_central_downwind_cells(ii,
2285 jj,
2286 i_massflux[face_id],
2287 &ic, /* central cell id */
2288 &id); /* downwind cell id */
2289
2290 cs_real_t courant_c = -1.;
2291 if (courant != NULL)
2292 courant_c = courant[ic];
2293
2294 cs_i_cd_unsteady_nvd(limiter_choice,
2295 beta,
2296 cell_cen[ic],
2297 cell_cen[id],
2298 i_face_normal[face_id],
2299 i_face_cog[face_id],
2300 grad[ic],
2301 _pvar[ic],
2302 _pvar[id],
2303 local_max[ic],
2304 local_min[ic],
2305 courant_c,
2306 &pif,
2307 &pjf);
2308
2309 cs_i_conv_flux(iconvp,
2310 thetap,
2311 imasac,
2312 _pvar[ii],
2313 _pvar[jj],
2314 pif,
2315 pif, /* no relaxation */
2316 pjf,
2317 pjf, /* no relaxation */
2318 i_massflux[face_id],
2319 1., /* xcpp */
2320 1., /* xcpp */
2321 fluxij);
2322
2323 /* Compute required quantities for diffusive flux */
2324 cs_real_t recoi, recoj;
2325
2326 cs_i_compute_quantities(bldfrp,
2327 diipf[face_id],
2328 djjpf[face_id],
2329 grad[ii],
2330 grad[jj],
2331 _pvar[ii],
2332 _pvar[jj],
2333 &recoi,
2334 &recoj,
2335 &pip,
2336 &pjp);
2337 }
2338
2339 cs_i_diff_flux(idiffp,
2340 thetap,
2341 pip,
2342 pjp,
2343 pip, /* no relaxation */
2344 pjp, /* no relaxation */
2345 i_visc[face_id],
2346 fluxij);
2347
2348 rhs[ii] -= fluxij[0];
2349 rhs[jj] += fluxij[1];
2350
2351 }
2352 }
2353 }
2354
2355 }
2356
2357 /* --> Flux with slope test
2358 ============================================*/
2359
2360 } else { /* isstpp = 0 */
2361
2362 if (ischcp < 0 || ischcp > 2) {
2363 bft_error(__FILE__, __LINE__, 0,
2364 _("invalid value of ischcv"));
2365 }
2366
2367 /* Steady */
2368 if (idtvar < 0) {
2369
2370 for (int g_id = 0; g_id < n_i_groups; g_id++) {
2371 # pragma omp parallel for reduction(+:n_upwind)
2372 for (int t_id = 0; t_id < n_i_threads; t_id++) {
2373 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
2374 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
2375 face_id++) {
2376
2377 cs_lnum_t ii = i_face_cells[face_id][0];
2378 cs_lnum_t jj = i_face_cells[face_id][1];
2379
2380 cs_real_2_t fluxij = {0., 0.};
2381
2382 bool upwind_switch = false;
2383 cs_real_t pifri, pjfri, pifrj, pjfrj;
2384 cs_real_t pip, pjp, pipr, pjpr;
2385
2386 cs_real_t bldfrp = (cs_real_t) ircflp;
2387 /* Local limitation of the reconstruction */
2388 if (df_limiter != NULL && ircflp > 0)
2389 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
2390
2391 cs_i_cd_steady_slope_test(&upwind_switch,
2392 iconvp,
2393 bldfrp,
2394 ischcp,
2395 relaxp,
2396 blencp,
2397 blend_st,
2398 weight[face_id],
2399 i_dist[face_id],
2400 i_face_surf[face_id],
2401 cell_cen[ii],
2402 cell_cen[jj],
2403 i_face_normal[face_id],
2404 i_face_cog[face_id],
2405 diipf[face_id],
2406 djjpf[face_id],
2407 i_massflux[face_id],
2408 grad[ii],
2409 grad[jj],
2410 gradup[ii],
2411 gradup[jj],
2412 gradst[ii],
2413 gradst[jj],
2414 _pvar[ii],
2415 _pvar[jj],
2416 pvara[ii],
2417 pvara[jj],
2418 &pifri,
2419 &pifrj,
2420 &pjfri,
2421 &pjfrj,
2422 &pip,
2423 &pjp,
2424 &pipr,
2425 &pjpr);
2426
2427 cs_i_conv_flux(iconvp,
2428 1.,
2429 1,
2430 _pvar[ii],
2431 _pvar[jj],
2432 pifri,
2433 pifrj,
2434 pjfri,
2435 pjfrj,
2436 i_massflux[face_id],
2437 1., /* xcpp */
2438 1., /* xcpp */
2439 fluxij);
2440
2441 cs_i_diff_flux(idiffp,
2442 1.,
2443 pip,
2444 pjp,
2445 pipr,
2446 pjpr,
2447 i_visc[face_id],
2448 fluxij);
2449
2450 if (upwind_switch) {
2451
2452 /* in parallel, face will be counted by one and only one rank */
2453 if (ii < n_cells)
2454 n_upwind++;
2455 if (v_slope_test != NULL) {
2456 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
2457 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
2458 }
2459
2460 }
2461
2462 rhs[ii] -= fluxij[0];
2463 rhs[jj] += fluxij[1];
2464
2465 }
2466 }
2467 }
2468
2469 /* Unsteady */
2470 } else {
2471
2472 for (int g_id = 0; g_id < n_i_groups; g_id++) {
2473 # pragma omp parallel for reduction(+:n_upwind)
2474 for (int t_id = 0; t_id < n_i_threads; t_id++) {
2475 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
2476 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
2477 face_id++) {
2478
2479 cs_lnum_t ii = i_face_cells[face_id][0];
2480 cs_lnum_t jj = i_face_cells[face_id][1];
2481
2482 bool upwind_switch = false;
2483
2484 cs_real_2_t fluxij = {0.,0.};
2485
2486 cs_real_t pif, pjf;
2487 cs_real_t pip, pjp;
2488
2489 cs_real_t bldfrp = (cs_real_t) ircflp;
2490 /* Local limitation of the reconstruction */
2491 if (df_limiter != NULL && ircflp > 0)
2492 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
2493
2494 cs_i_cd_unsteady_slope_test(&upwind_switch,
2495 iconvp,
2496 bldfrp,
2497 ischcp,
2498 blencp,
2499 blend_st,
2500 weight[face_id],
2501 i_dist[face_id],
2502 i_face_surf[face_id],
2503 cell_cen[ii],
2504 cell_cen[jj],
2505 i_face_normal[face_id],
2506 i_face_cog[face_id],
2507 diipf[face_id],
2508 djjpf[face_id],
2509 i_massflux[face_id],
2510 grad[ii],
2511 grad[jj],
2512 gradup[ii],
2513 gradup[jj],
2514 gradst[ii],
2515 gradst[jj],
2516 _pvar[ii],
2517 _pvar[jj],
2518 &pif,
2519 &pjf,
2520 &pip,
2521 &pjp);
2522
2523 cs_i_conv_flux(iconvp,
2524 thetap,
2525 imasac,
2526 _pvar[ii],
2527 _pvar[jj],
2528 pif,
2529 pif, /* no relaxation */
2530 pjf,
2531 pjf, /* no relaxation */
2532 i_massflux[face_id],
2533 1., /* xcpp */
2534 1., /* xcpp */
2535 fluxij);
2536
2537 cs_i_diff_flux(idiffp,
2538 thetap,
2539 pip,
2540 pjp,
2541 pip, /* no relaxation */
2542 pjp, /* no relaxation */
2543 i_visc[face_id],
2544 fluxij);
2545
2546 if (upwind_switch) {
2547 /* in parallel, face will be counted by one and only one rank */
2548 if (ii < n_cells)
2549 n_upwind++;
2550
2551 if (v_slope_test != NULL) {
2552 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
2553 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
2554 }
2555 }
2556
2557 rhs[ii] -= fluxij[0];
2558 rhs[jj] += fluxij[1];
2559
2560 }
2561 }
2562 }
2563
2564 } /* idtvar */
2565
2566 } /* iupwin */
2567
2568
2569 if (iwarnp >= 2 && iconvp == 1) {
2570
2571 /* Sum number of clippings */
2572 cs_parall_counter(&n_upwind, 1);
2573
2574 bft_printf(_(" %s: %llu Faces with upwind on %llu interior faces\n"),
2575 var_name, (unsigned long long)n_upwind,
2576 (unsigned long long)m->n_g_i_c_faces);
2577 }
2578
2579 /* ======================================================================
2580 ---> Contribution from boundary faces
2581 ======================================================================*/
2582
2583 /* Boundary convective flux are all computed with an upwind scheme */
2584 if (icvflb == 0) {
2585
2586 /* Steady */
2587 if (idtvar < 0) {
2588
2589 for (int g_id = 0; g_id < n_b_groups; g_id++) {
2590 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
2591 for (int t_id = 0; t_id < n_b_threads; t_id++) {
2592 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
2593 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
2594 face_id++) {
2595
2596 cs_lnum_t ii = b_face_cells[face_id];
2597
2598 cs_real_t fluxi = 0.;
2599 cs_real_t pir, pipr;
2600
2601 cs_real_t bldfrp = (cs_real_t) ircflp;
2602 /* Local limitation of the reconstruction */
2603 if (df_limiter != NULL && ircflp > 0)
2604 bldfrp = CS_MAX(df_limiter[ii], 0.);
2605
2606 cs_b_cd_steady(bldfrp,
2607 relaxp,
2608 diipb[face_id],
2609 grad[ii],
2610 _pvar[ii],
2611 pvara[ii],
2612 &pir,
2613 &pipr);
2614
2615 cs_b_upwind_flux(iconvp,
2616 1.,
2617 1,
2618 inc,
2619 bc_type[face_id],
2620 _pvar[ii],
2621 pir,
2622 pipr,
2623 coefap[face_id],
2624 coefbp[face_id],
2625 b_massflux[face_id],
2626 1., /* xcpp */
2627 &fluxi);
2628
2629 cs_b_diff_flux(idiffp,
2630 1., /* thetap */
2631 inc,
2632 pipr,
2633 cofafp[face_id],
2634 cofbfp[face_id],
2635 b_visc[face_id],
2636 &fluxi);
2637
2638 rhs[ii] -= fluxi;
2639
2640 }
2641 }
2642 }
2643
2644 /* The scalar is internal_coupled and an implicit contribution
2645 * is required */
2646 if (icoupl > 0) {
2647 /* Prepare data for sending */
2648 BFT_MALLOC(pvar_distant, n_distant, cs_real_t);
2649
2650 for (cs_lnum_t ii = 0; ii < n_distant; ii++) {
2651 cs_lnum_t face_id = faces_distant[ii];
2652 cs_lnum_t jj = b_face_cells[face_id];
2653 cs_real_t pip, pipr;
2654
2655 cs_real_t bldfrp = (cs_real_t) ircflp;
2656 /* Local limitation of the reconstruction */
2657 if (df_limiter != NULL && ircflp > 0)
2658 bldfrp = CS_MAX(df_limiter[jj], 0.);
2659
2660 cs_b_cd_steady(bldfrp,
2661 relaxp,
2662 diipb[face_id],
2663 grad[jj],
2664 _pvar[jj],
2665 pvara[jj],
2666 &pip,
2667 &pipr);
2668 pvar_distant[ii] = pipr;
2669 }
2670
2671 /* Receive data */
2672 BFT_MALLOC(pvar_local, n_local, cs_real_t);
2673 cs_internal_coupling_exchange_var(cpl,
2674 1, /* Dimension */
2675 pvar_distant,
2676 pvar_local);
2677
2678 /* Exchange diffusion limiter */
2679 if (df_limiter != NULL) {
2680 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
2681 cs_internal_coupling_exchange_var(cpl,
2682 1, /* Dimension */
2683 df_limiter,
2684 df_limiter_local);
2685 }
2686
2687 /* Flux contribution */
2688 assert(f != NULL);
2689 cs_real_t *hintp = f->bc_coeffs->hint;
2690 cs_real_t *hextp = f->bc_coeffs->hext;
2691 for (cs_lnum_t ii = 0; ii < n_local; ii++) {
2692 cs_lnum_t face_id = faces_local[ii];
2693 cs_lnum_t jj = b_face_cells[face_id];
2694 cs_real_t pip, pipr, pjpr;
2695 cs_real_t fluxi = 0.;
2696
2697 cs_real_t bldfrp = (cs_real_t) ircflp;
2698 /* Local limitation of the reconstruction */
2699 if (df_limiter != NULL && ircflp > 0)
2700 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
2701
2702 cs_b_cd_steady(bldfrp,
2703 relaxp,
2704 diipb[face_id],
2705 grad[jj],
2706 _pvar[jj],
2707 pvara[jj],
2708 &pip,
2709 &pipr);
2710
2711 pjpr = pvar_local[ii];
2712
2713 cs_real_t hint = hintp[face_id];
2714 cs_real_t hext = hextp[face_id];
2715 cs_real_t heq = _calc_heq(hint, hext);
2716
2717 cs_b_diff_flux_coupling(idiffp,
2718 pipr,
2719 pjpr,
2720 heq,
2721 &fluxi);
2722
2723 rhs[jj] -= thetap * fluxi;
2724 }
2725
2726 BFT_FREE(pvar_local);
2727 /* Sending structures are no longer needed */
2728 BFT_FREE(pvar_distant);
2729 if (df_limiter != NULL)
2730 BFT_FREE(df_limiter_local);
2731 }
2732
2733 /* Unsteady */
2734 } else {
2735
2736 for (int g_id = 0; g_id < n_b_groups; g_id++) {
2737 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
2738 for (int t_id = 0; t_id < n_b_threads; t_id++) {
2739 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
2740 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
2741 face_id++) {
2742
2743 cs_lnum_t ii = b_face_cells[face_id];
2744
2745 cs_real_t fluxi = 0.;
2746 cs_real_t pip;
2747
2748 cs_real_t bldfrp = (cs_real_t) ircflp;
2749 /* Local limitation of the reconstruction */
2750 if (df_limiter != NULL && ircflp > 0)
2751 bldfrp = CS_MAX(df_limiter[ii], 0.);
2752
2753 cs_b_cd_unsteady(bldfrp,
2754 diipb[face_id],
2755 grad[ii],
2756 _pvar[ii],
2757 &pip);
2758
2759 cs_b_upwind_flux(iconvp,
2760 thetap,
2761 imasac,
2762 inc,
2763 bc_type[face_id],
2764 _pvar[ii],
2765 _pvar[ii], /* no relaxation */
2766 pip,
2767 coefap[face_id],
2768 coefbp[face_id],
2769 b_massflux[face_id],
2770 1., /* xcpp */
2771 &fluxi);
2772
2773 cs_b_diff_flux(idiffp,
2774 thetap,
2775 inc,
2776 pip,
2777 cofafp[face_id],
2778 cofbfp[face_id],
2779 b_visc[face_id],
2780 &fluxi);
2781
2782 rhs[ii] -= fluxi;
2783
2784 }
2785 }
2786 }
2787
2788 /* The scalar is internally coupled and an implicit contribution
2789 * is required */
2790 if (icoupl > 0) {
2791 /* Prepare data for sending */
2792 BFT_MALLOC(pvar_distant, n_distant, cs_real_t);
2793
2794 for (cs_lnum_t ii = 0; ii < n_distant; ii++) {
2795 cs_lnum_t face_id = faces_distant[ii];
2796 cs_lnum_t jj = b_face_cells[face_id];
2797 cs_real_t pip;
2798
2799 cs_real_t bldfrp = (cs_real_t) ircflp;
2800 /* Local limitation of the reconstruction */
2801 if (df_limiter != NULL && ircflp > 0)
2802 bldfrp = CS_MAX(df_limiter[jj], 0.);
2803
2804 cs_b_cd_unsteady(bldfrp,
2805 diipb[face_id],
2806 grad[jj],
2807 _pvar[jj],
2808 &pip);
2809 pvar_distant[ii] = pip;
2810 }
2811
2812 /* Receive data */
2813 BFT_MALLOC(pvar_local, n_local, cs_real_t);
2814 cs_internal_coupling_exchange_var(cpl,
2815 1, /* Dimension */
2816 pvar_distant,
2817 pvar_local);
2818
2819 /* Exchange diffusion limiter */
2820 if (df_limiter != NULL) {
2821 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
2822 cs_internal_coupling_exchange_var(cpl,
2823 1, /* Dimension */
2824 df_limiter,
2825 df_limiter_local);
2826 }
2827
2828 /* Flux contribution */
2829 assert(f != NULL);
2830 cs_real_t *hintp = f->bc_coeffs->hint;
2831 cs_real_t *hextp = f->bc_coeffs->hext;
2832 for (cs_lnum_t ii = 0; ii < n_local; ii++) {
2833 cs_lnum_t face_id = faces_local[ii];
2834 cs_lnum_t jj = b_face_cells[face_id];
2835 cs_real_t pip, pjp;
2836 cs_real_t fluxi = 0.;
2837
2838 cs_real_t bldfrp = (cs_real_t) ircflp;
2839 /* Local limitation of the reconstruction */
2840 if (df_limiter != NULL && ircflp > 0)
2841 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
2842
2843 cs_b_cd_unsteady(bldfrp,
2844 diipb[face_id],
2845 grad[jj],
2846 _pvar[jj],
2847 &pip);
2848
2849 pjp = pvar_local[ii];
2850
2851 cs_real_t hint = hintp[face_id];
2852 cs_real_t hext = hextp[face_id];
2853 cs_real_t heq = _calc_heq(hint, hext);
2854
2855 cs_b_diff_flux_coupling(idiffp,
2856 pip,
2857 pjp,
2858 heq,
2859 &fluxi);
2860
2861 rhs[jj] -= thetap * fluxi;
2862 }
2863
2864 BFT_FREE(pvar_local);
2865 /* Sending structures are no longer needed */
2866 BFT_FREE(pvar_distant);
2867 if (df_limiter != NULL)
2868 BFT_FREE(df_limiter_local);
2869 }
2870 }
2871
2872 /* Boundary convective flux is imposed at some faces
2873 (tagged in icvfli array) */
2874 } else if (icvflb == 1) {
2875
2876 /* Retrieve the value of the convective flux to be imposed */
2877 if (f_id != -1) {
2878 coface = f->bc_coeffs->ac;
2879 cofbce = f->bc_coeffs->bc;
2880 } else {
2881 bft_error(__FILE__, __LINE__, 0,
2882 _("invalid value of icvflb and f_id"));
2883 }
2884
2885 /* Steady */
2886 if (idtvar < 0) {
2887
2888 for (int g_id = 0; g_id < n_b_groups; g_id++) {
2889 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
2890 for (int t_id = 0; t_id < n_b_threads; t_id++) {
2891 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
2892 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
2893 face_id++) {
2894
2895 cs_lnum_t ii = b_face_cells[face_id];
2896
2897 cs_real_t fluxi = 0.;
2898 cs_real_t pir, pipr;
2899
2900 cs_real_t bldfrp = (cs_real_t) ircflp;
2901 /* Local limitation of the reconstruction */
2902 if (df_limiter != NULL && ircflp > 0)
2903 bldfrp = CS_MAX(df_limiter[ii], 0.);
2904
2905 cs_b_cd_steady(bldfrp,
2906 relaxp,
2907 diipb[face_id],
2908 grad[ii],
2909 _pvar[ii],
2910 pvara[ii],
2911 &pir,
2912 &pipr);
2913
2914 cs_b_imposed_conv_flux(iconvp,
2915 1.,
2916 1,
2917 inc,
2918 bc_type[face_id],
2919 icvfli[face_id],
2920 _pvar[ii],
2921 pir,
2922 pipr,
2923 coefap[face_id],
2924 coefbp[face_id],
2925 coface[face_id],
2926 cofbce[face_id],
2927 b_massflux[face_id],
2928 1., /* xcpp */
2929 &fluxi);
2930
2931 cs_b_diff_flux(idiffp,
2932 1., /* thetap */
2933 inc,
2934 pipr,
2935 cofafp[face_id],
2936 cofbfp[face_id],
2937 b_visc[face_id],
2938 &fluxi);
2939
2940 rhs[ii] -= fluxi;
2941
2942 }
2943 }
2944 }
2945
2946 /* Unsteady */
2947 } else {
2948
2949 for (int g_id = 0; g_id < n_b_groups; g_id++) {
2950 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
2951 for (int t_id = 0; t_id < n_b_threads; t_id++) {
2952 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
2953 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
2954 face_id++) {
2955
2956 cs_lnum_t ii = b_face_cells[face_id];
2957
2958 cs_real_t fluxi = 0.;
2959 cs_real_t pip;
2960
2961 cs_real_t bldfrp = (cs_real_t) ircflp;
2962 /* Local limitation of the reconstruction */
2963 if (df_limiter != NULL && ircflp > 0)
2964 bldfrp = CS_MAX(df_limiter[ii], 0.);
2965
2966 cs_b_cd_unsteady(bldfrp,
2967 diipb[face_id],
2968 grad[ii],
2969 _pvar[ii],
2970 &pip);
2971
2972 cs_b_imposed_conv_flux(iconvp,
2973 thetap,
2974 imasac,
2975 inc,
2976 bc_type[face_id],
2977 icvfli[face_id],
2978 _pvar[ii],
2979 _pvar[ii], /* no relaxation */
2980 pip,
2981 coefap[face_id],
2982 coefbp[face_id],
2983 coface[face_id],
2984 cofbce[face_id],
2985 b_massflux[face_id],
2986 1., /* xcpp */
2987 &fluxi);
2988
2989 cs_b_diff_flux(idiffp,
2990 thetap,
2991 inc,
2992 pip,
2993 cofafp[face_id],
2994 cofbfp[face_id],
2995 b_visc[face_id],
2996 &fluxi);
2997
2998 rhs[ii] -= fluxi;
2999
3000 }
3001 }
3002 }
3003
3004 }
3005 }
3006
3007 /* Free memory */
3008 BFT_FREE(grad);
3009 BFT_FREE(gradup);
3010 BFT_FREE(gradst);
3011 BFT_FREE(local_max);
3012 BFT_FREE(local_min);
3013 BFT_FREE(courant);
3014 }
3015
3016 /*----------------------------------------------------------------------------*/
3017 /*!
3018 * <a name="cs_face_convection_scalar"></a>
3019 *
3020 * \brief Update face flux with convection contribution of a standard transport
3021 * equation of a scalar field \f$ \varia \f$.
3022 *
3023 * \f[
3024 * C_\ij = \dot{m}_\ij \left( \varia_\fij - \varia_\celli \right)
3025 * \f]
3026 *
3027 * \param[in] idtvar indicator of the temporal scheme
3028 * \param[in] f_id field id (or -1)
3029 * \param[in] var_cal_opt variable calculation options
3030 * \param[in] icvflb global indicator of boundary convection flux
3031 * - 0 upwind scheme at all boundary faces
3032 * - 1 imposed flux at some boundary faces
3033 * \param[in] inc indicator
3034 * - 0 when solving an increment
3035 * - 1 otherwise
3036 * \param[in] iccocg indicator
3037 * - 1 re-compute cocg matrix
3038 * (for iterative gradients)
3039 * - 0 otherwise
3040 * \param[in] imasac take mass accumulation into account?
3041 * \param[in] pvar solved variable (current time step)
3042 * \param[in] pvara solved variable (previous time step)
3043 * \param[in] icvfli boundary face indicator array of convection flux
3044 * - 0 upwind scheme
3045 * - 1 imposed flux
3046 * \param[in] coefap boundary condition array for the variable
3047 * (explicit part)
3048 * \param[in] coefbp boundary condition array for the variable
3049 * (implicit part)
3050 * \param[in] i_massflux mass flux at interior faces
3051 * \param[in] b_massflux mass flux at boundary faces
3052 * \param[in,out] i_conv_flux scalar convection flux at interior faces
3053 * \param[in,out] b_conv_flux scalar convection flux at boundary faces
3054 */
3055 /*----------------------------------------------------------------------------*/
3056
3057 void
cs_face_convection_scalar(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int icvflb,int inc,int iccocg,int imasac,cs_real_t * restrict pvar,const cs_real_t * restrict pvara,const int icvfli[],const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t i_massflux[],const cs_real_t b_massflux[],cs_real_2_t i_conv_flux[],cs_real_t b_conv_flux[])3058 cs_face_convection_scalar(int idtvar,
3059 int f_id,
3060 const cs_var_cal_opt_t var_cal_opt,
3061 int icvflb,
3062 int inc,
3063 int iccocg,
3064 int imasac,
3065 cs_real_t *restrict pvar,
3066 const cs_real_t *restrict pvara,
3067 const int icvfli[],
3068 const cs_real_t coefap[],
3069 const cs_real_t coefbp[],
3070 const cs_real_t i_massflux[],
3071 const cs_real_t b_massflux[],
3072 cs_real_2_t i_conv_flux[],
3073 cs_real_t b_conv_flux[])
3074 {
3075 const int iconvp = var_cal_opt.iconv;
3076 const int nswrgp = var_cal_opt.nswrgr;
3077 const int imrgra = var_cal_opt.imrgra;
3078 const int imligp = var_cal_opt.imligr;
3079 const int ircflp = var_cal_opt.ircflu;
3080 const int ischcp = var_cal_opt.ischcv;
3081 const int isstpp = var_cal_opt.isstpc;
3082 const int iwarnp = var_cal_opt.verbosity;
3083 const int icoupl = var_cal_opt.icoupl;
3084 int limiter_choice = -1;
3085 const double blencp = var_cal_opt.blencv;
3086 const double blend_st = var_cal_opt.blend_st;
3087 const double epsrgp = var_cal_opt.epsrgr;
3088 const double climgp = var_cal_opt.climgr;
3089 const double relaxp = var_cal_opt.relaxv;
3090 const double thetap = var_cal_opt.thetav;
3091
3092 const cs_mesh_t *m = cs_glob_mesh;
3093 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
3094
3095 const cs_lnum_t n_cells = m->n_cells;
3096 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
3097 const int n_i_groups = m->i_face_numbering->n_groups;
3098 const int n_i_threads = m->i_face_numbering->n_threads;
3099 const int n_b_groups = m->b_face_numbering->n_groups;
3100 const int n_b_threads = m->b_face_numbering->n_threads;
3101 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
3102 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
3103
3104 const cs_lnum_2_t *restrict i_face_cells
3105 = (const cs_lnum_2_t *restrict)m->i_face_cells;
3106 const cs_lnum_t *restrict b_face_cells
3107 = (const cs_lnum_t *restrict)m->b_face_cells;
3108 const cs_real_t *restrict weight = fvq->weight;
3109 const cs_real_t *restrict i_dist = fvq->i_dist;
3110 const cs_real_t *restrict i_face_surf = fvq->i_face_surf;
3111 const cs_real_t *restrict cell_vol = fvq->cell_vol;
3112 const cs_real_3_t *restrict cell_cen
3113 = (const cs_real_3_t *restrict)fvq->cell_cen;
3114 const cs_real_3_t *restrict i_face_normal
3115 = (const cs_real_3_t *restrict)fvq->i_face_normal;
3116 const cs_real_3_t *restrict i_face_cog
3117 = (const cs_real_3_t *restrict)fvq->i_face_cog;
3118 const cs_real_3_t *restrict diipf
3119 = (const cs_real_3_t *restrict)fvq->diipf;
3120 const cs_real_3_t *restrict djjpf
3121 = (const cs_real_3_t *restrict)fvq->djjpf;
3122 const cs_real_3_t *restrict diipb
3123 = (const cs_real_3_t *restrict)fvq->diipb;
3124
3125 const int *bc_type = cs_glob_bc_type;
3126
3127 /* Local variables */
3128
3129 char var_name[64];
3130
3131 int iupwin = 0;
3132 int w_stride = 1;
3133
3134 bool recompute_cocg = (iccocg) ? true : false;
3135
3136 cs_real_t *coface = NULL, *cofbce = NULL;
3137
3138 cs_real_3_t *grad;
3139 cs_real_3_t *gradup = NULL;
3140 cs_real_3_t *gradst = NULL;
3141 cs_field_t *f = NULL;
3142
3143 cs_real_t *local_min = NULL;
3144 cs_real_t *local_max = NULL;
3145 cs_real_t *courant = NULL;
3146
3147 cs_real_t *cv_limiter = NULL;
3148 cs_real_t *df_limiter = NULL;
3149
3150 cs_real_t *gweight = NULL;
3151
3152 const int key_lim_choice = cs_field_key_id("limiter_choice");
3153
3154 cs_real_t *v_slope_test = cs_get_v_slope_test(f_id, var_cal_opt);
3155
3156 /* Internal coupling variables */
3157 int coupling_id;
3158 cs_internal_coupling_t *cpl = NULL;
3159
3160 /* Initialization */
3161
3162 /* Allocate work arrays */
3163
3164 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
3165
3166 /* Choose gradient type */
3167
3168 cs_halo_type_t halo_type = CS_HALO_STANDARD;
3169 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
3170
3171 cs_gradient_type_by_imrgra(imrgra,
3172 &gradient_type,
3173 &halo_type);
3174
3175 /* Handle cases where only the previous values (already synchronized)
3176 or current values are provided */
3177
3178 if (pvar != NULL)
3179 cs_sync_scalar_halo(m, pvar);
3180 if (pvara == NULL)
3181 pvara = (const cs_real_t *restrict)pvar;
3182
3183 const cs_real_t *restrict _pvar = (pvar != NULL) ? pvar : pvara;
3184
3185 /* Slope limiters */
3186
3187 if (f_id != -1) {
3188 f = cs_field_by_id(f_id);
3189
3190 /* NVD/TVD limiters */
3191 if (ischcp == 4) {
3192 limiter_choice = cs_field_get_key_int(f, key_lim_choice);
3193 BFT_MALLOC(local_max, n_cells_ext, cs_real_t);
3194 BFT_MALLOC(local_min, n_cells_ext, cs_real_t);
3195 cs_field_local_extrema_scalar(f_id,
3196 halo_type,
3197 local_max,
3198 local_min);
3199 if (limiter_choice >= CS_NVD_VOF_HRIC) {
3200 BFT_MALLOC(courant, n_cells_ext, cs_real_t);
3201 cs_cell_courant_number(f_id, courant);
3202 }
3203 }
3204
3205 int cv_limiter_id =
3206 cs_field_get_key_int(f, cs_field_key_id("convection_limiter_id"));
3207 if (cv_limiter_id > -1)
3208 cv_limiter = cs_field_by_id(cv_limiter_id)->val;
3209
3210 int df_limiter_id =
3211 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
3212 if (df_limiter_id > -1)
3213 df_limiter = cs_field_by_id(df_limiter_id)->val;
3214
3215 snprintf(var_name, 63, "%s", f->name);
3216 }
3217 else if (isstpp > 1) {
3218 bft_error(__FILE__, __LINE__, 0,
3219 _("invalid value of isstpp for a work array"));
3220 } else {
3221 strncpy(var_name, "[scalar face flux from convection]", 63);
3222 }
3223 var_name[63] = '\0';
3224
3225 if (iwarnp >= 2) {
3226 if (ischcp == 1) {
3227 bft_printf(
3228 _(" %s: Convection in centered blending with %f percent of upwind\n"),
3229 var_name, (1.-blencp)*100.);
3230 } else {
3231 bft_printf(
3232 _(" %s: Convection in 2nd order blending with %f percent of upwind\n"),
3233 var_name, (1.-blencp)*100.);
3234 }
3235 }
3236
3237 iupwin = (blencp > 0.) ? 0 : 1;
3238
3239 if (icoupl > 0) {
3240 assert(f_id != -1);
3241 const int coupling_key_id = cs_field_key_id("coupling_entity");
3242 coupling_id = cs_field_get_key_int(f, coupling_key_id);
3243 cpl = cs_internal_coupling_by_id(coupling_id);
3244 }
3245
3246 /* Compute the balance with reconstruction */
3247
3248 /* Compute the gradient of the variable */
3249
3250 /* The gradient (grad) is used in the flux reconstruction and the slope test.
3251 Thus we must compute it:
3252 - when the convection scheme is the legacy SOLU,
3253 - when we have convection, we are not in pure upwind
3254 and we reconstruct the fluxes,
3255 - when we have convection, we are not in pure upwind
3256 and we have not shunted the slope test,
3257 - when we use NVD / TVD schemes.
3258 */
3259
3260 if ( iconvp != 0 && iupwin == 0
3261 && (ischcp == 0 || ircflp == 1 || isstpp == 0 || ischcp == 4)) {
3262
3263 if (f_id != -1) {
3264 /* Get the calculation option from the field */
3265 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
3266 if (var_cal_opt.idiff > 0) {
3267 int key_id = cs_field_key_id("gradient_weighting_id");
3268 int diff_id = cs_field_get_key_int(f, key_id);
3269 if (diff_id > -1) {
3270 cs_field_t *weight_f = cs_field_by_id(diff_id);
3271 gweight = weight_f->val;
3272 w_stride = weight_f->dim;
3273 cs_field_synchronize(weight_f, halo_type);
3274 }
3275 }
3276 }
3277 }
3278
3279 cs_gradient_scalar_synced_input(var_name,
3280 gradient_type,
3281 halo_type,
3282 inc,
3283 recompute_cocg,
3284 nswrgp,
3285 0, /* hyd_p_flag */
3286 w_stride,
3287 iwarnp,
3288 imligp,
3289 epsrgp,
3290 climgp,
3291 NULL, /* f_ext exterior force */
3292 coefap,
3293 coefbp,
3294 _pvar,
3295 gweight, /* Weighted gradient */
3296 cpl,
3297 grad);
3298
3299 } else {
3300
3301 # pragma omp parallel for
3302 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
3303 grad[cell_id][0] = 0.;
3304 grad[cell_id][1] = 0.;
3305 grad[cell_id][2] = 0.;
3306 }
3307 }
3308
3309 /* Compute gradients used in convection schemes */
3310
3311 if (iconvp > 0 && iupwin == 0) {
3312
3313 /* Compute cell gradient used in slope test */
3314 if (isstpp == 0) {
3315
3316 BFT_MALLOC(gradst, n_cells_ext, cs_real_3_t);
3317
3318 # pragma omp parallel for
3319 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
3320 gradst[cell_id][0] = 0.;
3321 gradst[cell_id][1] = 0.;
3322 gradst[cell_id][2] = 0.;
3323 }
3324
3325 cs_slope_test_gradient(f_id,
3326 inc,
3327 halo_type,
3328 (const cs_real_3_t *)grad,
3329 gradst,
3330 _pvar,
3331 coefap,
3332 coefbp,
3333 i_massflux);
3334
3335 }
3336
3337 /* Pure SOLU scheme */
3338 if (ischcp == 2) {
3339
3340 BFT_MALLOC(gradup, n_cells_ext, cs_real_3_t);
3341
3342 # pragma omp parallel for
3343 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
3344 gradup[cell_id][0] = 0.;
3345 gradup[cell_id][1] = 0.;
3346 gradup[cell_id][2] = 0.;
3347 }
3348
3349 cs_upwind_gradient(f_id,
3350 inc,
3351 halo_type,
3352 coefap,
3353 coefbp,
3354 i_massflux,
3355 b_massflux,
3356 _pvar,
3357 gradup);
3358
3359 }
3360
3361 }
3362
3363 /* ======================================================================
3364 ---> Contribution from interior faces
3365 ======================================================================*/
3366
3367 cs_gnum_t n_upwind = 0;
3368
3369 /* --> Pure upwind flux
3370 =====================*/
3371
3372 if (iupwin == 1) {
3373
3374 /* Steady */
3375 if (idtvar < 0) {
3376
3377 for (int g_id = 0; g_id < n_i_groups; g_id++) {
3378 # pragma omp parallel for reduction(+:n_upwind)
3379 for (int t_id = 0; t_id < n_i_threads; t_id++) {
3380 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
3381 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
3382 face_id++) {
3383
3384 cs_lnum_t ii = i_face_cells[face_id][0];
3385 cs_lnum_t jj = i_face_cells[face_id][1];
3386
3387 /* in parallel, face will be counted by one and only one rank */
3388 if (ii < n_cells) {
3389 n_upwind++;
3390 }
3391
3392 cs_real_t pifri, pjfri, pifrj, pjfrj;
3393 cs_real_t pip, pjp, pipr, pjpr;
3394
3395 cs_real_t bldfrp = (cs_real_t) ircflp;
3396 /* Local limitation of the reconstruction */
3397 if (df_limiter != NULL && ircflp > 0)
3398 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
3399
3400 cs_i_cd_steady_upwind(bldfrp,
3401 relaxp,
3402 diipf[face_id],
3403 djjpf[face_id],
3404 grad[ii],
3405 grad[jj],
3406 _pvar[ii],
3407 _pvar[jj],
3408 pvara[ii],
3409 pvara[jj],
3410 &pifri,
3411 &pifrj,
3412 &pjfri,
3413 &pjfrj,
3414 &pip,
3415 &pjp,
3416 &pipr,
3417 &pjpr);
3418
3419 cs_i_conv_flux(iconvp,
3420 1.,
3421 1,
3422 _pvar[ii],
3423 _pvar[jj],
3424 pifri,
3425 pifrj,
3426 pjfri,
3427 pjfrj,
3428 i_massflux[face_id],
3429 1., /* xcpp */
3430 1., /* xcpp */
3431 i_conv_flux[face_id]);
3432
3433 }
3434 }
3435 }
3436
3437 /* Unsteady */
3438 } else {
3439
3440 for (int g_id = 0; g_id < n_i_groups; g_id++) {
3441 # pragma omp parallel for reduction(+:n_upwind)
3442 for (int t_id = 0; t_id < n_i_threads; t_id++) {
3443 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
3444 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
3445 face_id++) {
3446
3447 cs_lnum_t ii = i_face_cells[face_id][0];
3448 cs_lnum_t jj = i_face_cells[face_id][1];
3449
3450 /* in parallel, face will be counted by one and only one rank */
3451 if (ii < n_cells) {
3452 n_upwind++;
3453 }
3454
3455 cs_real_t pif, pjf;
3456 cs_real_t pip, pjp;
3457
3458 cs_real_t bldfrp = (cs_real_t) ircflp;
3459 /* Local limitation of the reconstruction */
3460 if (df_limiter != NULL && ircflp > 0)
3461 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
3462
3463 cs_i_cd_unsteady_upwind(bldfrp,
3464 diipf[face_id],
3465 djjpf[face_id],
3466 grad[ii],
3467 grad[jj],
3468 _pvar[ii],
3469 _pvar[jj],
3470 &pif,
3471 &pjf,
3472 &pip,
3473 &pjp);
3474
3475 cs_i_conv_flux(iconvp,
3476 thetap,
3477 imasac,
3478 _pvar[ii],
3479 _pvar[jj],
3480 pif,
3481 pif, /* no relaxation */
3482 pjf,
3483 pjf, /* no relaxation */
3484 i_massflux[face_id],
3485 1., /* xcpp */
3486 1., /* xcpp */
3487 i_conv_flux[face_id]);
3488
3489 }
3490 }
3491 }
3492
3493 }
3494
3495 /* --> Flux with no slope test or Min/Max Beta limiter
3496 ====================================================*/
3497
3498 } else if (isstpp == 1 || isstpp == 2) {
3499
3500 if (ischcp < 0 || ischcp > 4) {
3501 bft_error(__FILE__, __LINE__, 0,
3502 _("invalid value of ischcv"));
3503 }
3504
3505 /* Steady */
3506 if (idtvar < 0) {
3507
3508 for (int g_id = 0; g_id < n_i_groups; g_id++) {
3509 # pragma omp parallel for
3510 for (int t_id = 0; t_id < n_i_threads; t_id++) {
3511 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
3512 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
3513 face_id++) {
3514
3515 cs_lnum_t ii = i_face_cells[face_id][0];
3516 cs_lnum_t jj = i_face_cells[face_id][1];
3517
3518 cs_real_t pifri, pjfri, pifrj, pjfrj;
3519 cs_real_t pip, pjp, pipr, pjpr;
3520
3521 cs_real_t bldfrp = (cs_real_t) ircflp;
3522 /* Local limitation of the reconstruction */
3523 if (df_limiter != NULL && ircflp > 0)
3524 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
3525
3526 cs_i_cd_steady(bldfrp,
3527 ischcp,
3528 relaxp,
3529 blencp,
3530 weight[face_id],
3531 cell_cen[ii],
3532 cell_cen[jj],
3533 i_face_cog[face_id],
3534 diipf[face_id],
3535 djjpf[face_id],
3536 grad[ii],
3537 grad[jj],
3538 gradup[ii],
3539 gradup[jj],
3540 _pvar[ii],
3541 _pvar[jj],
3542 pvara[ii],
3543 pvara[jj],
3544 &pifri,
3545 &pifrj,
3546 &pjfri,
3547 &pjfrj,
3548 &pip,
3549 &pjp,
3550 &pipr,
3551 &pjpr);
3552
3553 cs_i_conv_flux(iconvp,
3554 1.,
3555 1,
3556 _pvar[ii],
3557 _pvar[jj],
3558 pifri,
3559 pifrj,
3560 pjfri,
3561 pjfrj,
3562 i_massflux[face_id],
3563 1., /* xcpp */
3564 1., /* xcpp */
3565 i_conv_flux[face_id]);
3566
3567 }
3568 }
3569 }
3570
3571 /* Unsteady */
3572 } else {
3573
3574 for (int g_id = 0; g_id < n_i_groups; g_id++) {
3575 # pragma omp parallel for
3576 for (int t_id = 0; t_id < n_i_threads; t_id++) {
3577 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
3578 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
3579 face_id++) {
3580
3581 cs_lnum_t ii = i_face_cells[face_id][0];
3582 cs_lnum_t jj = i_face_cells[face_id][1];
3583
3584 cs_real_t beta = blencp;
3585
3586 cs_real_t pif, pjf;
3587 cs_real_t pip, pjp;
3588
3589 /* Beta blending coefficient ensuring positivity of the scalar */
3590 if (isstpp == 2) {
3591 beta = CS_MAX(CS_MIN(cv_limiter[ii], cv_limiter[jj]), 0.);
3592 }
3593
3594 cs_real_t bldfrp = (cs_real_t) ircflp;
3595 /* Local limitation of the reconstruction */
3596 if (df_limiter != NULL && ircflp > 0)
3597 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
3598
3599 if (ischcp != 4) {
3600 cs_real_t hybrid_coef_ii, hybrid_coef_jj;
3601 if (ischcp == 3) {
3602 hybrid_coef_ii = CS_F_(hybrid_blend)->val[ii];
3603 hybrid_coef_jj = CS_F_(hybrid_blend)->val[jj];
3604 } else {
3605 hybrid_coef_ii = 0.;
3606 hybrid_coef_jj = 0.;
3607 }
3608 cs_i_cd_unsteady(bldfrp,
3609 ischcp,
3610 beta,
3611 weight[face_id],
3612 cell_cen[ii],
3613 cell_cen[jj],
3614 i_face_cog[face_id],
3615 hybrid_coef_ii,
3616 hybrid_coef_jj,
3617 diipf[face_id],
3618 djjpf[face_id],
3619 grad[ii],
3620 grad[jj],
3621 gradup[ii],
3622 gradup[jj],
3623 _pvar[ii],
3624 _pvar[jj],
3625 &pif,
3626 &pjf,
3627 &pip,
3628 &pjp);
3629
3630 cs_i_conv_flux(iconvp,
3631 thetap,
3632 imasac,
3633 _pvar[ii],
3634 _pvar[jj],
3635 pif,
3636 pif, /* no relaxation */
3637 pjf,
3638 pjf, /* no relaxation */
3639 i_massflux[face_id],
3640 1., /* xcpp */
3641 1., /* xcpp */
3642 i_conv_flux[face_id]);
3643 } else {
3644 /* NVD/TVD family of high accuracy schemes */
3645
3646 cs_lnum_t ic, id;
3647
3648 /* Determine central and downwind sides w.r.t. current face */
3649 cs_central_downwind_cells(ii,
3650 jj,
3651 i_massflux[face_id],
3652 &ic, /* central cell id */
3653 &id); /* downwind cell id */
3654
3655 cs_real_t courant_c = -1.;
3656 if (courant != NULL)
3657 courant_c = courant[ic];
3658
3659 cs_i_cd_unsteady_nvd(limiter_choice,
3660 beta,
3661 cell_cen[ic],
3662 cell_cen[id],
3663 i_face_normal[face_id],
3664 i_face_cog[face_id],
3665 grad[ic],
3666 _pvar[ic],
3667 _pvar[id],
3668 local_max[ic],
3669 local_min[ic],
3670 courant_c,
3671 &pif,
3672 &pjf);
3673
3674 cs_i_conv_flux(iconvp,
3675 thetap,
3676 imasac,
3677 _pvar[ii],
3678 _pvar[jj],
3679 pif,
3680 pif, /* no relaxation */
3681 pjf,
3682 pjf, /* no relaxation */
3683 i_massflux[face_id],
3684 1., /* xcpp */
3685 1., /* xcpp */
3686 i_conv_flux[face_id]);
3687 }
3688
3689 }
3690 }
3691 }
3692
3693 }
3694
3695 /* --> Flux with slope test or NVD/TVD limiter
3696 ============================================*/
3697
3698 } else { /* isstpp = 0 */
3699
3700 if (ischcp < 0 || ischcp > 2) {
3701 bft_error(__FILE__, __LINE__, 0,
3702 _("invalid value of ischcv"));
3703 }
3704
3705 /* Steady */
3706 if (idtvar < 0) {
3707
3708 for (int g_id = 0; g_id < n_i_groups; g_id++) {
3709 # pragma omp parallel for reduction(+:n_upwind)
3710 for (int t_id = 0; t_id < n_i_threads; t_id++) {
3711 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
3712 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
3713 face_id++) {
3714
3715 cs_lnum_t ii = i_face_cells[face_id][0];
3716 cs_lnum_t jj = i_face_cells[face_id][1];
3717
3718 bool upwind_switch = false;
3719 cs_real_t pifri, pjfri, pifrj, pjfrj;
3720 cs_real_t pip, pjp, pipr, pjpr;
3721
3722 cs_real_t bldfrp = (cs_real_t) ircflp;
3723 /* Local limitation of the reconstruction */
3724 if (df_limiter != NULL && ircflp > 0)
3725 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
3726
3727 cs_i_cd_steady_slope_test(&upwind_switch,
3728 iconvp,
3729 bldfrp,
3730 ischcp,
3731 relaxp,
3732 blencp,
3733 blend_st,
3734 weight[face_id],
3735 i_dist[face_id],
3736 i_face_surf[face_id],
3737 cell_cen[ii],
3738 cell_cen[jj],
3739 i_face_normal[face_id],
3740 i_face_cog[face_id],
3741 diipf[face_id],
3742 djjpf[face_id],
3743 i_massflux[face_id],
3744 grad[ii],
3745 grad[jj],
3746 gradup[ii],
3747 gradup[jj],
3748 gradst[ii],
3749 gradst[jj],
3750 _pvar[ii],
3751 _pvar[jj],
3752 pvara[ii],
3753 pvara[jj],
3754 &pifri,
3755 &pifrj,
3756 &pjfri,
3757 &pjfrj,
3758 &pip,
3759 &pjp,
3760 &pipr,
3761 &pjpr);
3762
3763 cs_i_conv_flux(iconvp,
3764 1.,
3765 1,
3766 _pvar[ii],
3767 _pvar[jj],
3768 pifri,
3769 pifrj,
3770 pjfri,
3771 pjfrj,
3772 i_massflux[face_id],
3773 1., /* xcpp */
3774 1., /* xcpp */
3775 i_conv_flux[face_id]);
3776
3777 if (upwind_switch) {
3778
3779 /* in parallel, face will be counted by one and only one rank */
3780 if (ii < n_cells)
3781 n_upwind++;
3782 if (v_slope_test != NULL) {
3783 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
3784 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
3785 }
3786
3787 }
3788
3789 }
3790 }
3791 }
3792
3793 /* Unsteady */
3794 } else {
3795
3796 for (int g_id = 0; g_id < n_i_groups; g_id++) {
3797 # pragma omp parallel for reduction(+:n_upwind)
3798 for (int t_id = 0; t_id < n_i_threads; t_id++) {
3799 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
3800 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
3801 face_id++) {
3802
3803 cs_lnum_t ii = i_face_cells[face_id][0];
3804 cs_lnum_t jj = i_face_cells[face_id][1];
3805
3806 bool upwind_switch = false;
3807
3808 cs_real_t pif, pjf;
3809 cs_real_t pip, pjp;
3810
3811 cs_real_t bldfrp = (cs_real_t) ircflp;
3812 /* Local limitation of the reconstruction */
3813 if (df_limiter != NULL && ircflp > 0)
3814 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
3815
3816 cs_i_cd_unsteady_slope_test(&upwind_switch,
3817 iconvp,
3818 bldfrp,
3819 ischcp,
3820 blencp,
3821 blend_st,
3822 weight[face_id],
3823 i_dist[face_id],
3824 i_face_surf[face_id],
3825 cell_cen[ii],
3826 cell_cen[jj],
3827 i_face_normal[face_id],
3828 i_face_cog[face_id],
3829 diipf[face_id],
3830 djjpf[face_id],
3831 i_massflux[face_id],
3832 grad[ii],
3833 grad[jj],
3834 gradup[ii],
3835 gradup[jj],
3836 gradst[ii],
3837 gradst[jj],
3838 _pvar[ii],
3839 _pvar[jj],
3840 &pif,
3841 &pjf,
3842 &pip,
3843 &pjp);
3844
3845 cs_i_conv_flux(iconvp,
3846 thetap,
3847 imasac,
3848 _pvar[ii],
3849 _pvar[jj],
3850 pif,
3851 pif, /* no relaxation */
3852 pjf,
3853 pjf, /* no relaxation */
3854 i_massflux[face_id],
3855 1., /* xcpp */
3856 1., /* xcpp */
3857 i_conv_flux[face_id]);
3858
3859 if (upwind_switch) {
3860 /* in parallel, face will be counted by one and only one rank */
3861 if (ii < n_cells)
3862 n_upwind++;
3863
3864 if (v_slope_test != NULL) {
3865 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
3866 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
3867 }
3868 }
3869
3870 }
3871 }
3872 }
3873
3874 } /* idtvar */
3875
3876 } /* iupwin */
3877
3878
3879 if (iwarnp >= 2 && iconvp == 1) {
3880
3881 /* Sum number of clippings */
3882 cs_parall_counter(&n_upwind, 1);
3883
3884 bft_printf(_(" %s: %llu Faces with upwind on %llu interior faces\n"),
3885 var_name, (unsigned long long)n_upwind,
3886 (unsigned long long)m->n_g_i_c_faces);
3887 }
3888
3889 /* ======================================================================
3890 ---> Contribution from boundary faces
3891 ======================================================================*/
3892
3893 /* Boundary convective flux are all computed with an upwind scheme */
3894 if (icvflb == 0) {
3895
3896 /* Steady */
3897 if (idtvar < 0) {
3898
3899 for (int g_id = 0; g_id < n_b_groups; g_id++) {
3900 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
3901 for (int t_id = 0; t_id < n_b_threads; t_id++) {
3902 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
3903 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
3904 face_id++) {
3905
3906 cs_lnum_t ii = b_face_cells[face_id];
3907
3908 cs_real_t pir, pipr;
3909
3910 cs_real_t bldfrp = (cs_real_t) ircflp;
3911 /* Local limitation of the reconstruction */
3912 if (df_limiter != NULL && ircflp > 0)
3913 bldfrp = CS_MAX(df_limiter[ii], 0.);
3914
3915 cs_b_cd_steady(bldfrp,
3916 relaxp,
3917 diipb[face_id],
3918 grad[ii],
3919 _pvar[ii],
3920 pvara[ii],
3921 &pir,
3922 &pipr);
3923
3924 cs_b_upwind_flux(iconvp,
3925 1.,
3926 1,
3927 inc,
3928 bc_type[face_id],
3929 _pvar[ii],
3930 pir,
3931 pipr,
3932 coefap[face_id],
3933 coefbp[face_id],
3934 b_massflux[face_id],
3935 1., /* xcpp */
3936 &(b_conv_flux[face_id]));
3937
3938 }
3939 }
3940 }
3941
3942 /* Unsteady */
3943 } else {
3944
3945 for (int g_id = 0; g_id < n_b_groups; g_id++) {
3946 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
3947 for (int t_id = 0; t_id < n_b_threads; t_id++) {
3948 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
3949 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
3950 face_id++) {
3951
3952 cs_lnum_t ii = b_face_cells[face_id];
3953
3954 cs_real_t pip;
3955
3956 cs_real_t bldfrp = (cs_real_t) ircflp;
3957 /* Local limitation of the reconstruction */
3958 if (df_limiter != NULL && ircflp > 0)
3959 bldfrp = CS_MAX(df_limiter[ii], 0.);
3960
3961 cs_b_cd_unsteady(bldfrp,
3962 diipb[face_id],
3963 grad[ii],
3964 _pvar[ii],
3965 &pip);
3966
3967 cs_b_upwind_flux(iconvp,
3968 thetap,
3969 imasac,
3970 inc,
3971 bc_type[face_id],
3972 _pvar[ii],
3973 _pvar[ii], /* no relaxation */
3974 pip,
3975 coefap[face_id],
3976 coefbp[face_id],
3977 b_massflux[face_id],
3978 1., /* xcpp */
3979 &(b_conv_flux[face_id]));
3980
3981 }
3982 }
3983 }
3984 }
3985
3986 /* Boundary convective flux is imposed at some faces
3987 (tagged in icvfli array) */
3988 } else if (icvflb == 1) {
3989
3990 /* Retrieve the value of the convective flux to be imposed */
3991 if (f_id != -1) {
3992 coface = f->bc_coeffs->ac;
3993 cofbce = f->bc_coeffs->bc;
3994 } else {
3995 bft_error(__FILE__, __LINE__, 0,
3996 _("invalid value of icvflb and f_id"));
3997 }
3998
3999 /* Steady */
4000 if (idtvar < 0) {
4001
4002 for (int g_id = 0; g_id < n_b_groups; g_id++) {
4003 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
4004 for (int t_id = 0; t_id < n_b_threads; t_id++) {
4005 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
4006 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
4007 face_id++) {
4008
4009 cs_lnum_t ii = b_face_cells[face_id];
4010
4011 cs_real_t pir, pipr;
4012
4013 cs_real_t bldfrp = (cs_real_t) ircflp;
4014 /* Local limitation of the reconstruction */
4015 if (df_limiter != NULL && ircflp > 0)
4016 bldfrp = CS_MAX(df_limiter[ii], 0.);
4017
4018 cs_b_cd_steady(bldfrp,
4019 relaxp,
4020 diipb[face_id],
4021 grad[ii],
4022 _pvar[ii],
4023 pvara[ii],
4024 &pir,
4025 &pipr);
4026
4027 cs_b_imposed_conv_flux(iconvp,
4028 1.,
4029 1,
4030 inc,
4031 bc_type[face_id],
4032 icvfli[face_id],
4033 _pvar[ii],
4034 pir,
4035 pipr,
4036 coefap[face_id],
4037 coefbp[face_id],
4038 coface[face_id],
4039 cofbce[face_id],
4040 b_massflux[face_id],
4041 1., /* xcpp */
4042 &(b_conv_flux[face_id]));
4043
4044 }
4045 }
4046 }
4047
4048 /* Unsteady */
4049 } else {
4050
4051 for (int g_id = 0; g_id < n_b_groups; g_id++) {
4052 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
4053 for (int t_id = 0; t_id < n_b_threads; t_id++) {
4054 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
4055 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
4056 face_id++) {
4057
4058 cs_lnum_t ii = b_face_cells[face_id];
4059
4060 cs_real_t pip;
4061
4062 cs_real_t bldfrp = (cs_real_t) ircflp;
4063 /* Local limitation of the reconstruction */
4064 if (df_limiter != NULL && ircflp > 0)
4065 bldfrp = CS_MAX(df_limiter[ii], 0.);
4066
4067 cs_b_cd_unsteady(bldfrp,
4068 diipb[face_id],
4069 grad[ii],
4070 _pvar[ii],
4071 &pip);
4072
4073 cs_b_imposed_conv_flux(iconvp,
4074 thetap,
4075 imasac,
4076 inc,
4077 bc_type[face_id],
4078 icvfli[face_id],
4079 _pvar[ii],
4080 _pvar[ii], /* no relaxation */
4081 pip,
4082 coefap[face_id],
4083 coefbp[face_id],
4084 coface[face_id],
4085 cofbce[face_id],
4086 b_massflux[face_id],
4087 1., /* xcpp */
4088 &(b_conv_flux[face_id]));
4089
4090 }
4091 }
4092 }
4093
4094 }
4095 }
4096
4097 /* Free memory */
4098 BFT_FREE(grad);
4099 BFT_FREE(gradup);
4100 BFT_FREE(gradst);
4101 BFT_FREE(local_max);
4102 BFT_FREE(local_min);
4103 BFT_FREE(courant);
4104 }
4105
4106 /*----------------------------------------------------------------------------*/
4107 /*!
4108 * \brief Add the explicit part of the convection/diffusion terms of a transport
4109 * equation of a vector field \f$ \vect{\varia} \f$.
4110 *
4111 * More precisely, the right hand side \f$ \vect{Rhs} \f$ is updated as
4112 * follows:
4113 * \f[
4114 * \vect{Rhs} = \vect{Rhs} - \sum_{\fij \in \Facei{\celli}} \left(
4115 * \dot{m}_\ij \left( \vect{\varia}_\fij - \vect{\varia}_\celli \right)
4116 * - \mu_\fij \gradt_\fij \vect{\varia} \cdot \vect{S}_\ij \right)
4117 * \f]
4118 *
4119 * Remark:
4120 * if ivisep = 1, then we also take \f$ \mu \transpose{\gradt\vect{\varia}}
4121 * + \lambda \trace{\gradt\vect{\varia}} \f$, where \f$ \lambda \f$ is
4122 * the secondary viscosity, i.e. usually \f$ -\frac{2}{3} \mu \f$.
4123 *
4124 * Warning:
4125 * - \f$ \vect{Rhs} \f$ has already been initialized before calling bilsc!
4126 * - mind the sign minus
4127 *
4128 * \param[in] idtvar indicator of the temporal scheme
4129 * \param[in] f_id index of the current variable
4130 * \param[in] var_cal_opt variable calculation options
4131 * \param[in] icvflb global indicator of boundary convection flux
4132 * - 0 upwind scheme at all boundary faces
4133 * - 1 imposed flux at some boundary faces
4134 * \param[in] inc indicator
4135 * - 0 when solving an increment
4136 * - 1 otherwise
4137 * \param[in] ivisep indicator to take \f$ \divv
4138 * \left(\mu \gradt \transpose{\vect{a}} \right)
4139 * -2/3 \grad\left( \mu \dive \vect{a} \right)\f$
4140 * - 1 take into account,
4141 * - 0 otherwise
4142 * \param[in] imasac take mass accumulation into account?
4143 * \param[in] pvar solved velocity (current time step)
4144 * \param[in] pvara solved velocity (previous time step)
4145 * \param[in] icvfli boundary face indicator array of convection flux
4146 * - 0 upwind scheme
4147 * - 1 imposed flux
4148 * \param[in] coefav boundary condition array for the variable
4149 * (explicit part)
4150 * \param[in] coefbv boundary condition array for the variable
4151 * (implicit part)
4152 * \param[in] cofafv boundary condition array for the diffusion
4153 * of the variable (explicit part)
4154 * \param[in] cofbfv boundary condition array for the diffusion
4155 * of the variable (implicit part)
4156 * \param[in] i_massflux mass flux at interior faces
4157 * \param[in] b_massflux mass flux at boundary faces
4158 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
4159 * at interior faces for the r.h.s.
4160 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
4161 * at border faces for the r.h.s.
4162 * \param[in] i_secvis secondary viscosity at interior faces
4163 * \param[in] b_secvis secondary viscosity at boundary faces
4164 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
4165 */
4166 /*----------------------------------------------------------------------------*/
4167
4168 void
cs_convection_diffusion_vector(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int icvflb,int inc,int ivisep,int imasac,cs_real_3_t * restrict pvar,const cs_real_3_t * restrict pvara,const int icvfli[],const cs_real_3_t coefav[],const cs_real_33_t coefbv[],const cs_real_3_t cofafv[],const cs_real_33_t cofbfv[],const cs_real_t i_massflux[],const cs_real_t b_massflux[],const cs_real_t i_visc[],const cs_real_t b_visc[],const cs_real_t i_secvis[],const cs_real_t b_secvis[],cs_real_3_t * restrict rhs)4169 cs_convection_diffusion_vector(int idtvar,
4170 int f_id,
4171 const cs_var_cal_opt_t var_cal_opt,
4172 int icvflb,
4173 int inc,
4174 int ivisep,
4175 int imasac,
4176 cs_real_3_t *restrict pvar,
4177 const cs_real_3_t *restrict pvara,
4178 const int icvfli[],
4179 const cs_real_3_t coefav[],
4180 const cs_real_33_t coefbv[],
4181 const cs_real_3_t cofafv[],
4182 const cs_real_33_t cofbfv[],
4183 const cs_real_t i_massflux[],
4184 const cs_real_t b_massflux[],
4185 const cs_real_t i_visc[],
4186 const cs_real_t b_visc[],
4187 const cs_real_t i_secvis[],
4188 const cs_real_t b_secvis[],
4189 cs_real_3_t *restrict rhs)
4190 {
4191 const int iconvp = var_cal_opt.iconv;
4192 const int idiffp = var_cal_opt.idiff;
4193 const int nswrgp = var_cal_opt.nswrgr;
4194 const int imrgra = var_cal_opt.imrgra;
4195 const int imligp = var_cal_opt.imligr;
4196 const int ircflp = var_cal_opt.ircflu;
4197 const int ischcp = var_cal_opt.ischcv;
4198 const int isstpp = var_cal_opt.isstpc;
4199 const int iwarnp = var_cal_opt.verbosity;
4200 const int icoupl = var_cal_opt.icoupl;
4201 const double blencp = var_cal_opt.blencv;
4202 const double blend_st = var_cal_opt.blend_st;
4203 const double epsrgp = var_cal_opt.epsrgr;
4204 const double climgp = var_cal_opt.climgr;
4205 const double relaxp = var_cal_opt.relaxv;
4206 const double thetap = var_cal_opt.thetav;
4207
4208 const cs_mesh_t *m = cs_glob_mesh;
4209 const cs_halo_t *halo = m->halo;
4210 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
4211
4212 const cs_lnum_t n_cells = m->n_cells;
4213 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
4214 const int n_i_groups = m->i_face_numbering->n_groups;
4215 const int n_i_threads = m->i_face_numbering->n_threads;
4216 const int n_b_groups = m->b_face_numbering->n_groups;
4217 const int n_b_threads = m->b_face_numbering->n_threads;
4218 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
4219 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
4220
4221 const cs_lnum_2_t *restrict i_face_cells
4222 = (const cs_lnum_2_t *restrict)m->i_face_cells;
4223 const cs_lnum_t *restrict b_face_cells
4224 = (const cs_lnum_t *restrict)m->b_face_cells;
4225 const cs_real_t *restrict weight = fvq->weight;
4226 const cs_real_t *restrict i_dist = fvq->i_dist;
4227 const cs_real_t *restrict i_face_surf = fvq->i_face_surf;
4228 const cs_real_t *restrict cell_vol = fvq->cell_vol;
4229 const cs_real_3_t *restrict cell_cen
4230 = (const cs_real_3_t *restrict)fvq->cell_cen;
4231 const cs_real_3_t *restrict i_face_normal
4232 = (const cs_real_3_t *restrict)fvq->i_face_normal;
4233 const cs_real_3_t *restrict i_f_face_normal
4234 = (const cs_real_3_t *restrict)fvq->i_f_face_normal;
4235 const cs_real_3_t *restrict b_face_normal
4236 = (const cs_real_3_t *restrict)fvq->b_face_normal;
4237 const cs_real_3_t *restrict b_f_face_normal
4238 = (const cs_real_3_t *restrict)fvq->b_f_face_normal;
4239 const cs_real_3_t *restrict i_face_cog
4240 = (const cs_real_3_t *restrict)fvq->i_face_cog;
4241 const cs_real_3_t *restrict diipf
4242 = (const cs_real_3_t *restrict)fvq->diipf;
4243 const cs_real_3_t *restrict djjpf
4244 = (const cs_real_3_t *restrict)fvq->djjpf;
4245 const cs_real_3_t *restrict diipb
4246 = (const cs_real_3_t *restrict)fvq->diipb;
4247
4248 const int *bc_type = cs_glob_bc_type;
4249 cs_real_2_t *i_f_face_factor = NULL;
4250 cs_real_t *b_f_face_factor = NULL;
4251
4252 /* Local variables */
4253
4254 cs_real_t *df_limiter = NULL;
4255
4256 cs_field_t *f = NULL;
4257 char var_name[64];
4258
4259 if (f_id != -1) {
4260 f = cs_field_by_id(f_id);
4261
4262 int df_limiter_id =
4263 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
4264 if (df_limiter_id > -1)
4265 df_limiter = cs_field_by_id(df_limiter_id)->val;
4266
4267 snprintf(var_name, 63, "%s", f->name);
4268 }
4269 else
4270 strncpy(var_name, "[convection-diffusion, vector]", 63);
4271 var_name[63] = '\0';
4272
4273 /* Discontinuous porous treatment */
4274 if (cs_glob_porous_model == 3 && f == CS_F_(vel)) {
4275 i_f_face_factor = fvq->i_f_face_factor;
4276 b_f_face_factor = fvq->b_f_face_factor;
4277 }
4278
4279 cs_gnum_t n_upwind;
4280 int iupwin = 0;
4281
4282 cs_real_33_t *grad, *grdpa;
4283 cs_real_t *bndcel;
4284
4285 const cs_real_3_t *coface = NULL;
4286 const cs_real_33_t *cofbce = NULL;
4287
4288 cs_real_t *gweight = NULL;
4289
4290 cs_real_t *v_slope_test = cs_get_v_slope_test(f_id, var_cal_opt);
4291
4292 /* Internal coupling variables */
4293 cs_real_3_t *pvar_local = NULL;
4294 cs_real_3_t *pvar_distant = NULL;
4295 cs_real_t *df_limiter_local = NULL;
4296 const cs_lnum_t *faces_local = NULL, *faces_distant = NULL;
4297 cs_lnum_t n_local = 0, n_distant = 0;
4298 int coupling_id = -1;
4299 cs_internal_coupling_t *cpl = NULL;
4300
4301 /*==========================================================================*/
4302
4303 /* 1. Initialization */
4304
4305 /* Allocate work arrays */
4306
4307 BFT_MALLOC(grad, n_cells_ext, cs_real_33_t);
4308 BFT_MALLOC(grdpa, n_cells_ext, cs_real_33_t);
4309
4310 /* Choose gradient type */
4311
4312 cs_halo_type_t halo_type = CS_HALO_STANDARD;
4313 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
4314
4315 cs_gradient_type_by_imrgra(imrgra,
4316 &gradient_type,
4317 &halo_type);
4318
4319 /* Handle cases where only the previous values (already synchronized)
4320 or current values are provided */
4321
4322 if (pvar != NULL && halo != NULL) {
4323 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)pvar, 3);
4324 if (cs_glob_mesh->n_init_perio > 0)
4325 cs_halo_perio_sync_var_vect(halo, halo_type, (cs_real_t *)pvar, 3);
4326 }
4327 if (pvara == NULL)
4328 pvara = (const cs_real_3_t *restrict)pvar;
4329
4330 const cs_real_3_t *restrict _pvar
4331 = (pvar != NULL) ? (const cs_real_3_t *restrict)pvar : pvara;
4332
4333 /* Slope limiters */
4334
4335 if (iwarnp >= 2 && iconvp == 1) {
4336 if (ischcp == 1) {
4337 bft_printf
4338 (
4339 _(" %s: Convection in centered blending with %f percent of upwind\n"),
4340 var_name, (1.-blencp)*100.);
4341 } else {
4342 bft_printf
4343 (
4344 _(" %s: Convection in 2nd order blending with %f percent of upwind\n"),
4345 var_name, (1.-blencp)*100.);
4346 }
4347 }
4348
4349 iupwin = (blencp > 0.) ? 0 : 1;
4350
4351 if (icoupl > 0) {
4352 assert(f_id != -1);
4353 const int coupling_key_id = cs_field_key_id("coupling_entity");
4354 coupling_id = cs_field_get_key_int(f, coupling_key_id);
4355 cpl = cs_internal_coupling_by_id(coupling_id);
4356 cs_internal_coupling_coupled_faces(cpl,
4357 &n_local,
4358 &faces_local,
4359 &n_distant,
4360 &faces_distant);
4361 }
4362
4363 /* 2. Compute the balance with reconstruction */
4364
4365 /* Compute the gradient of the velocity
4366
4367 The gradient (grad) is used in the flux reconstruction and the slope test.
4368 Thus we must compute it:
4369 - when we have diffusion and we reconstruct the fluxes,
4370 - when the convection scheme is SOLU,
4371 - when we have convection, we are not in pure upwind
4372 and we reconstruct the fluxes,
4373 - when we have convection, we are not in pure upwind
4374 and we have not shunted the slope test. */
4375
4376 if ( (idiffp != 0 && ircflp == 1) || ivisep == 1
4377 || ( iconvp != 0 && iupwin == 0
4378 && (ischcp == 0 || ircflp == 1 || isstpp == 0))) {
4379
4380 if (f_id != -1) {
4381 /* Get the calculation option from the field */
4382 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
4383 if (var_cal_opt.idiff > 0) {
4384 int key_id = cs_field_key_id("gradient_weighting_id");
4385 int diff_id = cs_field_get_key_int(f, key_id);
4386 if (diff_id > -1) {
4387 cs_field_t *weight_f = cs_field_by_id(diff_id);
4388 gweight = weight_f->val;
4389 cs_field_synchronize(weight_f, halo_type);
4390 }
4391 }
4392 }
4393 }
4394
4395 cs_gradient_vector_synced_input(var_name,
4396 gradient_type,
4397 halo_type,
4398 inc,
4399 nswrgp,
4400 iwarnp,
4401 imligp,
4402 epsrgp,
4403 climgp,
4404 coefav,
4405 coefbv,
4406 _pvar,
4407 gweight, /* weighted gradient */
4408 cpl,
4409 grad);
4410
4411 } else {
4412 # pragma omp parallel for
4413 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
4414 for (int isou = 0; isou < 3; isou++) {
4415 for (int jsou = 0; jsou < 3; jsou++)
4416 grad[cell_id][isou][jsou] = 0.;
4417 }
4418 }
4419 }
4420
4421 /* ======================================================================
4422 ---> Compute uncentered gradient grdpa for the slope test
4423 ======================================================================*/
4424
4425 # pragma omp parallel for
4426 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
4427 for (int jsou = 0; jsou < 3; jsou++) {
4428 for (int isou = 0; isou < 3; isou++)
4429 grdpa[cell_id][isou][jsou] = 0.;
4430 }
4431 }
4432
4433 if (iconvp > 0 && iupwin == 0 && isstpp == 0) {
4434
4435 cs_slope_test_gradient_vector(inc,
4436 halo_type,
4437 (const cs_real_33_t *)grad,
4438 grdpa,
4439 _pvar,
4440 coefav,
4441 coefbv,
4442 i_massflux);
4443
4444 }
4445
4446 /* ======================================================================
4447 ---> Contribution from interior faces
4448 ======================================================================*/
4449
4450 n_upwind = 0;
4451
4452 if (n_cells_ext > n_cells) {
4453 # pragma omp parallel for if(n_cells_ext -n_cells > CS_THR_MIN)
4454 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
4455 for (int isou = 0; isou < 3; isou++)
4456 rhs[cell_id][isou] = 0.;
4457 }
4458 }
4459
4460 /* --> Pure upwind flux
4461 =====================*/
4462
4463 if (iupwin == 1) {
4464
4465 /* Steady */
4466 if (idtvar < 0) {
4467
4468 for (int g_id = 0; g_id < n_i_groups; g_id++) {
4469 # pragma omp parallel for reduction(+:n_upwind)
4470 for (int t_id = 0; t_id < n_i_threads; t_id++) {
4471 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
4472 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
4473 face_id++) {
4474
4475 cs_lnum_t ii = i_face_cells[face_id][0];
4476 cs_lnum_t jj = i_face_cells[face_id][1];
4477
4478 /* in parallel, face will be counted by one and only one rank */
4479 if (ii < n_cells) {
4480 n_upwind++;
4481 }
4482
4483 cs_real_t fluxi[3], fluxj[3] ;
4484 for (int isou = 0; isou < 3; isou++) {
4485 fluxi[isou] = 0;
4486 fluxj[isou] = 0;
4487 }
4488
4489 cs_real_3_t pip, pjp, pipr, pjpr;
4490 cs_real_3_t pifri, pifrj, pjfri, pjfrj;
4491 cs_real_3_t _pi, _pj, _pia, _pja;
4492
4493 for (int i = 0; i < 3; i++) {
4494 _pi[i] = _pvar[ii][i];
4495 _pj[i] = _pvar[jj][i];
4496 _pia[i] = pvara[ii][i];
4497 _pja[i] = pvara[jj][i];
4498 }
4499
4500 /* Scaling due to mass balance in porous modelling */
4501 if (i_f_face_factor != NULL) {
4502 cs_real_3_t n;
4503 cs_math_3_normalise(i_face_normal[face_id], n);
4504
4505 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pi);
4506 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pia);
4507 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pj);
4508 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pja);
4509 }
4510
4511 cs_real_t bldfrp = (cs_real_t) ircflp;
4512 /* Local limitation of the reconstruction */
4513 if (df_limiter != NULL && ircflp > 0)
4514 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
4515
4516 cs_i_cd_steady_upwind_vector(bldfrp,
4517 relaxp,
4518 diipf[face_id],
4519 djjpf[face_id],
4520 (const cs_real_3_t *)grad[ii],
4521 (const cs_real_3_t *)grad[jj],
4522 _pi,
4523 _pj,
4524 _pia,
4525 _pja,
4526 pifri,
4527 pifrj,
4528 pjfri,
4529 pjfrj,
4530 pip,
4531 pjp,
4532 pipr,
4533 pjpr);
4534
4535
4536 cs_i_conv_flux_vector(iconvp,
4537 1.,
4538 1,
4539 _pvar[ii],
4540 _pvar[jj],
4541 pifri,
4542 pifrj,
4543 pjfri,
4544 pjfrj,
4545 i_massflux[face_id],
4546 fluxi,
4547 fluxj);
4548
4549
4550 cs_i_diff_flux_vector(idiffp,
4551 1.,
4552 pip,
4553 pjp,
4554 pipr,
4555 pjpr,
4556 i_visc[face_id],
4557 fluxi,
4558 fluxj);
4559
4560 for (int isou = 0; isou < 3; isou++) {
4561 rhs[ii][isou] -= fluxi[isou];
4562 rhs[jj][isou] += fluxj[isou];
4563 }
4564
4565 }
4566 }
4567 }
4568
4569 /* Unsteady */
4570 } else {
4571
4572 for (int g_id = 0; g_id < n_i_groups; g_id++) {
4573 # pragma omp parallel for reduction(+:n_upwind)
4574 for (int t_id = 0; t_id < n_i_threads; t_id++) {
4575 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
4576 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
4577 face_id++) {
4578
4579 cs_lnum_t ii = i_face_cells[face_id][0];
4580 cs_lnum_t jj = i_face_cells[face_id][1];
4581
4582 /* in parallel, face will be counted by one and only one rank */
4583 if (ii < n_cells) {
4584 n_upwind++;
4585 }
4586
4587 cs_real_t fluxi[3], fluxj[3] ;
4588 for (int i = 0; i < 3; i++) {
4589 fluxi[i] = 0;
4590 fluxj[i] = 0;
4591 }
4592 cs_real_3_t pip, pjp;
4593 cs_real_3_t pif, pjf;
4594 cs_real_3_t _pi, _pj;
4595
4596 for (int i = 0; i < 3; i++) {
4597 _pi[i] = _pvar[ii][i];
4598 _pj[i] = _pvar[jj][i];
4599 }
4600
4601 /* Scaling due to mass balance in porous modelling */
4602 if (i_f_face_factor != NULL) {
4603 cs_real_3_t n;
4604 cs_math_3_normalise(i_face_normal[face_id], n);
4605
4606 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pi);
4607 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pj);
4608 }
4609
4610 cs_real_t bldfrp = (cs_real_t) ircflp;
4611 /* Local limitation of the reconstruction */
4612 if (df_limiter != NULL && ircflp > 0)
4613 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
4614
4615 cs_i_cd_unsteady_upwind_vector(bldfrp,
4616 diipf[face_id],
4617 djjpf[face_id],
4618 (const cs_real_3_t *)grad[ii],
4619 (const cs_real_3_t *)grad[jj],
4620 _pi,
4621 _pj,
4622 pif,
4623 pjf,
4624 pip,
4625 pjp);
4626
4627 cs_i_conv_flux_vector(iconvp,
4628 thetap,
4629 imasac,
4630 _pvar[ii],
4631 _pvar[jj],
4632 pif,
4633 pif, /* no relaxation */
4634 pjf,
4635 pjf, /* no relaxation */
4636 i_massflux[face_id],
4637 fluxi,
4638 fluxj);
4639
4640
4641 cs_i_diff_flux_vector(idiffp,
4642 thetap,
4643 pip,
4644 pjp,
4645 pip, /* no relaxation */
4646 pjp, /* no relaxation */
4647 i_visc[face_id],
4648 fluxi,
4649 fluxj);
4650
4651 for (int isou = 0; isou < 3; isou++) {
4652 rhs[ii][isou] -= fluxi[isou];
4653 rhs[jj][isou] += fluxj[isou];
4654 }
4655
4656 }
4657 }
4658 }
4659
4660 }
4661
4662 /* --> Flux with no slope test
4663 ============================*/
4664
4665 } else if (isstpp == 1) {
4666
4667 if (ischcp < 0 || ischcp == 2 || ischcp > 3) {
4668 bft_error(__FILE__, __LINE__, 0,
4669 _("invalid value of ischcv"));
4670 }
4671
4672 /* Steady */
4673 if (idtvar < 0) {
4674
4675 for (int g_id = 0; g_id < n_i_groups; g_id++) {
4676 # pragma omp parallel for
4677 for (int t_id = 0; t_id < n_i_threads; t_id++) {
4678 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
4679 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
4680 face_id++) {
4681
4682 cs_lnum_t ii = i_face_cells[face_id][0];
4683 cs_lnum_t jj = i_face_cells[face_id][1];
4684
4685 cs_real_t fluxi[3], fluxj[3] ;
4686 for (int isou = 0; isou < 3; isou++) {
4687 fluxi[isou] = 0;
4688 fluxj[isou] = 0;
4689 }
4690 cs_real_3_t pip, pjp, pipr, pjpr;
4691 cs_real_3_t pifri, pifrj, pjfri, pjfrj;
4692 cs_real_3_t _pi, _pj, _pia, _pja;
4693
4694 for (int i = 0; i < 3; i++) {
4695 _pi[i] = _pvar[ii][i];
4696 _pj[i] = _pvar[jj][i];
4697 _pia[i] = pvara[ii][i];
4698 _pja[i] = pvara[jj][i];
4699 }
4700
4701 /* Scaling due to mass balance in porous modelling */
4702 if (i_f_face_factor != NULL) {
4703 cs_real_3_t n;
4704 cs_math_3_normalise(i_face_normal[face_id], n);
4705
4706 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pi);
4707 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pia);
4708 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pj);
4709 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pja);
4710 }
4711
4712 cs_real_t bldfrp = (cs_real_t) ircflp;
4713 /* Local limitation of the reconstruction */
4714 if (df_limiter != NULL && ircflp > 0)
4715 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
4716
4717 cs_i_cd_steady_vector(bldfrp,
4718 ischcp,
4719 relaxp,
4720 blencp,
4721 weight[face_id],
4722 cell_cen[ii],
4723 cell_cen[jj],
4724 i_face_cog[face_id],
4725 diipf[face_id],
4726 djjpf[face_id],
4727 (const cs_real_3_t *)grad[ii],
4728 (const cs_real_3_t *)grad[jj],
4729 _pi,
4730 _pj,
4731 _pia,
4732 _pja,
4733 pifri,
4734 pifrj,
4735 pjfri,
4736 pjfrj,
4737 pip,
4738 pjp,
4739 pipr,
4740 pjpr);
4741
4742 cs_i_conv_flux_vector(iconvp,
4743 1.,
4744 1,
4745 _pvar[ii],
4746 _pvar[jj],
4747 pifri,
4748 pifrj,
4749 pjfri,
4750 pjfrj,
4751 i_massflux[face_id],
4752 fluxi,
4753 fluxj);
4754
4755
4756 cs_i_diff_flux_vector(idiffp,
4757 1.,
4758 pip,
4759 pjp,
4760 pipr,
4761 pjpr,
4762 i_visc[face_id],
4763 fluxi,
4764 fluxj);
4765
4766 for (int isou = 0; isou < 3; isou++) {
4767 rhs[ii][isou] -= fluxi[isou];
4768 rhs[jj][isou] += fluxj[isou];
4769 }
4770
4771 }
4772 }
4773 }
4774
4775 /* Unsteady */
4776 } else {
4777
4778 for (int g_id = 0; g_id < n_i_groups; g_id++) {
4779 # pragma omp parallel for
4780 for (int t_id = 0; t_id < n_i_threads; t_id++) {
4781 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
4782 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
4783 face_id++) {
4784
4785 cs_lnum_t ii = i_face_cells[face_id][0];
4786 cs_lnum_t jj = i_face_cells[face_id][1];
4787
4788 cs_real_t fluxi[3], fluxj[3] ;
4789 for (int isou = 0; isou < 3; isou++) {
4790 fluxi[isou] = 0;
4791 fluxj[isou] = 0;
4792 }
4793
4794 cs_real_3_t pip, pjp;
4795 cs_real_3_t pif, pjf;
4796 cs_real_3_t _pi, _pj;
4797
4798 for (int i = 0; i < 3; i++) {
4799 _pi[i] = _pvar[ii][i];
4800 _pj[i] = _pvar[jj][i];
4801 }
4802
4803 /* Scaling due to mass balance in porous modelling */
4804 if (i_f_face_factor != NULL) {
4805 cs_real_3_t n;
4806 cs_math_3_normalise(i_face_normal[face_id], n);
4807
4808 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pi);
4809 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pj);
4810 }
4811
4812 cs_real_t hybrid_coef_ii, hybrid_coef_jj;
4813 if (ischcp == 3) {
4814 hybrid_coef_ii = CS_F_(hybrid_blend)->val[ii];
4815 hybrid_coef_jj = CS_F_(hybrid_blend)->val[jj];
4816 } else {
4817 hybrid_coef_ii = 0.;
4818 hybrid_coef_jj = 0.;
4819 }
4820
4821 cs_real_t bldfrp = (cs_real_t) ircflp;
4822 /* Local limitation of the reconstruction */
4823 if (df_limiter != NULL && ircflp > 0)
4824 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
4825
4826 cs_i_cd_unsteady_vector(bldfrp,
4827 ischcp,
4828 blencp,
4829 weight[face_id],
4830 cell_cen[ii],
4831 cell_cen[jj],
4832 i_face_cog[face_id],
4833 hybrid_coef_ii,
4834 hybrid_coef_jj,
4835 diipf[face_id],
4836 djjpf[face_id],
4837 (const cs_real_3_t *)grad[ii],
4838 (const cs_real_3_t *)grad[jj],
4839 _pi,
4840 _pj,
4841 pif,
4842 pjf,
4843 pip,
4844 pjp);
4845
4846 cs_i_conv_flux_vector(iconvp,
4847 thetap,
4848 imasac,
4849 _pvar[ii],
4850 _pvar[jj],
4851 pif,
4852 pif, /* no relaxation */
4853 pjf,
4854 pjf, /* no relaxation */
4855 i_massflux[face_id],
4856 fluxi,
4857 fluxj);
4858
4859
4860 cs_i_diff_flux_vector(idiffp,
4861 thetap,
4862 pip,
4863 pjp,
4864 pip, /* no relaxation */
4865 pjp, /* no relaxation */
4866 i_visc[face_id],
4867 fluxi,
4868 fluxj);
4869
4870 for (int isou = 0; isou < 3; isou++) {
4871 rhs[ii][isou] -= fluxi[isou];
4872 rhs[jj][isou] += fluxj[isou];
4873 }
4874
4875 }
4876 }
4877 }
4878
4879 }
4880
4881 /* --> Flux with slope test
4882 =========================*/
4883
4884 } else {
4885
4886 if (ischcp < 0 || ischcp > 1) {
4887 bft_error(__FILE__, __LINE__, 0,
4888 _("invalid value of ischcv"));
4889 }
4890
4891 /* Steady */
4892 if (idtvar < 0) {
4893
4894 for (int g_id = 0; g_id < n_i_groups; g_id++) {
4895 # pragma omp parallel for reduction(+:n_upwind)
4896 for (int t_id = 0; t_id < n_i_threads; t_id++) {
4897 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
4898 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
4899 face_id++) {
4900
4901 cs_lnum_t ii = i_face_cells[face_id][0];
4902 cs_lnum_t jj = i_face_cells[face_id][1];
4903
4904 cs_real_t fluxi[3], fluxj[3] ;
4905 for (int isou = 0; isou < 3; isou++) {
4906 fluxi[isou] = 0;
4907 fluxj[isou] = 0;
4908 }
4909 cs_real_3_t pip, pjp, pipr, pjpr;
4910 cs_real_3_t pifri, pifrj, pjfri, pjfrj;
4911 bool upwind_switch = false;
4912 cs_real_3_t _pi, _pj, _pia, _pja;
4913
4914 for (int i = 0; i < 3; i++) {
4915 _pi[i] = _pvar[ii][i];
4916 _pj[i] = _pvar[jj][i];
4917 _pia[i] = pvara[ii][i];
4918 _pja[i] = pvara[jj][i];
4919 }
4920
4921 /* Scaling due to mass balance in porous modelling */
4922 if (i_f_face_factor != NULL) {
4923 cs_real_3_t n;
4924 cs_math_3_normalise(i_face_normal[face_id], n);
4925
4926 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pi);
4927 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pia);
4928 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pj);
4929 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pja);
4930 }
4931
4932 cs_real_t bldfrp = (cs_real_t) ircflp;
4933 /* Local limitation of the reconstruction */
4934 if (df_limiter != NULL && ircflp > 0)
4935 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
4936
4937 cs_i_cd_steady_slope_test_vector(&upwind_switch,
4938 iconvp,
4939 bldfrp,
4940 ischcp,
4941 relaxp,
4942 blencp,
4943 blend_st,
4944 weight[face_id],
4945 i_dist[face_id],
4946 i_face_surf[face_id],
4947 cell_cen[ii],
4948 cell_cen[jj],
4949 i_face_normal[face_id],
4950 i_face_cog[face_id],
4951 diipf[face_id],
4952 djjpf[face_id],
4953 i_massflux[face_id],
4954 (const cs_real_3_t *)grad[ii],
4955 (const cs_real_3_t *)grad[jj],
4956 (const cs_real_3_t *)grdpa[ii],
4957 (const cs_real_3_t *)grdpa[jj],
4958 _pi,
4959 _pj,
4960 _pia,
4961 _pja,
4962 pifri,
4963 pifrj,
4964 pjfri,
4965 pjfrj,
4966 pip,
4967 pjp,
4968 pipr,
4969 pjpr);
4970
4971 cs_i_conv_flux_vector(iconvp,
4972 1.,
4973 1,
4974 _pvar[ii],
4975 _pvar[jj],
4976 pifri,
4977 pifrj,
4978 pjfri,
4979 pjfrj,
4980 i_massflux[face_id],
4981 fluxi,
4982 fluxj);
4983
4984
4985 cs_i_diff_flux_vector(idiffp,
4986 1.,
4987 pip,
4988 pjp,
4989 pipr,
4990 pjpr,
4991 i_visc[face_id],
4992 fluxi,
4993 fluxj);
4994
4995 for (int isou = 0; isou < 3; isou++) {
4996 rhs[ii][isou] -= fluxi[isou];
4997 rhs[jj][isou] += fluxj[isou];
4998 }
4999
5000 }
5001 }
5002 }
5003
5004 /* Unsteady */
5005 } else {
5006
5007 for (int g_id = 0; g_id < n_i_groups; g_id++) {
5008 # pragma omp parallel for reduction(+:n_upwind)
5009 for (int t_id = 0; t_id < n_i_threads; t_id++) {
5010 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
5011 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
5012 face_id++) {
5013
5014 cs_lnum_t ii = i_face_cells[face_id][0];
5015 cs_lnum_t jj = i_face_cells[face_id][1];
5016
5017 cs_real_t fluxi[3], fluxj[3] ;
5018 for (int isou = 0; isou < 3; isou++) {
5019 fluxi[isou] = 0;
5020 fluxj[isou] = 0;
5021 }
5022 cs_real_3_t pip, pjp;
5023 cs_real_3_t pif, pjf;
5024 bool upwind_switch = false;
5025 cs_real_3_t _pi, _pj;
5026
5027 for (int i = 0; i < 3; i++) {
5028 _pi[i] = _pvar[ii][i];
5029 _pj[i] = _pvar[jj][i];
5030 }
5031
5032 /* Scaling due to mass balance in porous modelling */
5033 if (i_f_face_factor != NULL) {
5034 cs_real_3_t n;
5035 cs_math_3_normalise(i_face_normal[face_id], n);
5036
5037 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][0], _pi);
5038 cs_math_3_normal_scaling(n, i_f_face_factor[face_id][1], _pj);
5039 }
5040
5041 cs_real_t bldfrp = (cs_real_t) ircflp;
5042 /* Local limitation of the reconstruction */
5043 if (df_limiter != NULL && ircflp > 0)
5044 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
5045
5046 cs_i_cd_unsteady_slope_test_vector(&upwind_switch,
5047 iconvp,
5048 bldfrp,
5049 ischcp,
5050 blencp,
5051 blend_st,
5052 weight[face_id],
5053 i_dist[face_id],
5054 i_face_surf[face_id],
5055 cell_cen[ii],
5056 cell_cen[jj],
5057 i_face_normal[face_id],
5058 i_face_cog[face_id],
5059 diipf[face_id],
5060 djjpf[face_id],
5061 i_massflux[face_id],
5062 (const cs_real_3_t *)grad[ii],
5063 (const cs_real_3_t *)grad[jj],
5064 (const cs_real_3_t *)grdpa[ii],
5065 (const cs_real_3_t *)grdpa[jj],
5066 _pi,
5067 _pj,
5068 pif,
5069 pjf,
5070 pip,
5071 pjp);
5072
5073 cs_i_conv_flux_vector(iconvp,
5074 thetap,
5075 imasac,
5076 _pvar[ii],
5077 _pvar[jj],
5078 pif,
5079 pif, /* no relaxation */
5080 pjf,
5081 pjf, /* no relaxation */
5082 i_massflux[face_id],
5083 fluxi,
5084 fluxj);
5085
5086
5087 cs_i_diff_flux_vector(idiffp,
5088 thetap,
5089 pip,
5090 pjp,
5091 pip, /* no relaxation */
5092 pjp, /* no relaxation */
5093 i_visc[face_id],
5094 fluxi,
5095 fluxj);
5096
5097 if (upwind_switch) {
5098
5099 /* in parallel, face will be counted by one and only one rank */
5100 if (ii < n_cells)
5101 n_upwind++;
5102
5103 if (v_slope_test != NULL) {
5104 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
5105 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
5106 }
5107 }
5108
5109 for (int isou = 0; isou < 3; isou++) {
5110
5111 rhs[ii][isou] -= fluxi[isou];
5112 rhs[jj][isou] += fluxj[isou];
5113
5114 } /* isou */
5115
5116 }
5117 }
5118 }
5119
5120 } /* idtvar */
5121
5122 } /* iupwin */
5123
5124 if (iwarnp >= 2 && iconvp == 1) {
5125
5126 /* Sum number of clippings */
5127 cs_parall_counter(&n_upwind, 1);
5128
5129 bft_printf(_(" %s: %llu Faces with upwind on %llu interior faces\n"),
5130 var_name, (unsigned long long)n_upwind,
5131 (unsigned long long)m->n_g_i_c_faces);
5132 }
5133
5134 /* ======================================================================
5135 ---> Contribution from boundary faces
5136 ======================================================================*/
5137
5138 /* Boundary convective flux are all computed with an upwind scheme */
5139 if (icvflb == 0) {
5140
5141 /* Steady */
5142 if (idtvar < 0) {
5143
5144 for (int g_id = 0; g_id < n_b_groups; g_id++) {
5145 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
5146 for (int t_id = 0; t_id < n_b_threads; t_id++) {
5147 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
5148 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
5149 face_id++) {
5150
5151 cs_lnum_t ii = b_face_cells[face_id];
5152
5153 cs_real_t fluxi[3] ;
5154 for (int isou = 0; isou < 3; isou++) {
5155 fluxi[isou] = 0;
5156 }
5157 cs_real_3_t pir, pipr;
5158 cs_real_3_t _pi, _pia;
5159
5160 for (int i = 0; i < 3; i++) {
5161 _pi[i] = _pvar[ii][i];
5162 _pia[i] = pvara[ii][i];
5163 }
5164
5165 /* Scaling due to mass balance in porous modelling */
5166 if (b_f_face_factor != NULL) {
5167 cs_real_3_t n;
5168 cs_math_3_normalise(b_face_normal[face_id], n);
5169
5170 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pi);
5171 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pia);
5172 }
5173
5174 cs_real_t bldfrp = (cs_real_t) ircflp;
5175 /* Local limitation of the reconstruction */
5176 if (df_limiter != NULL && ircflp > 0)
5177 bldfrp = CS_MAX(df_limiter[ii], 0.);
5178
5179 cs_b_cd_steady_vector(bldfrp,
5180 relaxp,
5181 diipb[face_id],
5182 (const cs_real_3_t *)grad[ii],
5183 _pi,
5184 _pia,
5185 pir,
5186 pipr);
5187
5188 cs_b_upwind_flux_vector(iconvp,
5189 1., /* thetap */
5190 1, /* imasac */
5191 inc,
5192 bc_type[face_id],
5193 _pi,
5194 pir,
5195 pipr,
5196 coefav[face_id],
5197 coefbv[face_id],
5198 b_massflux[face_id],
5199 fluxi);
5200
5201 cs_b_diff_flux_vector(idiffp,
5202 1., /* thetap */
5203 inc,
5204 pipr,
5205 cofafv[face_id],
5206 cofbfv[face_id],
5207 b_visc[face_id],
5208 fluxi);
5209
5210 for (int isou = 0; isou < 3; isou++) {
5211 rhs[ii][isou] -= fluxi[isou];
5212 } /* isou */
5213
5214 }
5215 }
5216 }
5217
5218 if (icoupl > 0) {
5219 /* Prepare data for sending */
5220 BFT_MALLOC(pvar_distant, n_distant, cs_real_3_t);
5221
5222 for (cs_lnum_t ii = 0; ii < n_distant; ii++) {
5223 cs_lnum_t face_id = faces_distant[ii];
5224 cs_lnum_t jj = b_face_cells[face_id];
5225
5226 cs_real_3_t pip, pipr;
5227 cs_real_3_t _pj, _pja;
5228
5229 for (int i = 0; i < 3; i++) {
5230 _pj[i] = _pvar[jj][i];
5231 _pja[i] = pvara[jj][i];
5232 }
5233
5234 cs_real_t bldfrp = (cs_real_t) ircflp;
5235 /* Local limitation of the reconstruction */
5236 /* Note: to be treated exactly as a internal face, should be a bending
5237 * between the two cells... */
5238 if (df_limiter != NULL && ircflp > 0)
5239 bldfrp = CS_MAX(df_limiter[jj], 0.);
5240
5241 /* Scaling due to mass balance in porous modelling */
5242 if (b_f_face_factor != NULL) {
5243 cs_real_3_t n;
5244 cs_math_3_normalise(b_face_normal[face_id], n);
5245
5246 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pj);
5247 }
5248
5249 cs_b_cd_steady_vector(bldfrp,
5250 relaxp,
5251 diipb[face_id],
5252 (const cs_real_3_t *)grad[jj],
5253 _pj,
5254 _pja,
5255 pip,
5256 pipr);
5257
5258 for (int k = 0; k < 3; k++)
5259 pvar_distant[ii][k] = pipr[k];
5260 }
5261
5262 /* Receive data */
5263 BFT_MALLOC(pvar_local, n_local, cs_real_3_t);
5264 cs_internal_coupling_exchange_var(cpl,
5265 3, /* Dimension */
5266 (cs_real_t *)pvar_distant,
5267 (cs_real_t *)pvar_local);
5268
5269 if (df_limiter != NULL) {
5270 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
5271 cs_internal_coupling_exchange_var(cpl,
5272 1, /* Dimension */
5273 df_limiter,
5274 df_limiter_local);
5275 }
5276
5277 /* Flux contribution */
5278 assert(f != NULL);
5279 cs_real_t *hintp = f->bc_coeffs->hint;
5280 cs_real_t *hextp = f->bc_coeffs->hext;
5281 for (cs_lnum_t ii = 0; ii < n_local; ii++) {
5282 cs_lnum_t face_id = faces_local[ii];
5283 cs_lnum_t jj = b_face_cells[face_id];
5284 cs_real_t pip[3], pipr[3], pjpr[3];
5285 cs_real_t fluxi[3] = {0., 0., 0.};
5286 cs_real_3_t _pj, _pja;
5287
5288 for (cs_lnum_t i = 0; i < 3; i++) {
5289 _pj[i] = _pvar[jj][i];
5290 _pja[i] = pvara[jj][i];
5291 }
5292
5293 /* Scaling due to mass balance in porous modelling */
5294 if (b_f_face_factor != NULL) {
5295 cs_real_3_t n;
5296 cs_math_3_normalise(b_face_normal[face_id], n);
5297
5298 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pj);
5299 }
5300
5301 cs_real_t bldfrp = (cs_real_t) ircflp;
5302 /* Local limitation of the reconstruction */
5303 if (df_limiter != NULL && ircflp > 0)
5304 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
5305
5306 cs_b_cd_steady_vector(bldfrp,
5307 relaxp,
5308 diipb[face_id],
5309 (const cs_real_3_t *)grad[jj],
5310 _pj,
5311 _pja,
5312 pip,
5313 pipr);
5314
5315 for (cs_lnum_t k = 0; k < 3; k++)
5316 pjpr[k] = pvar_local[ii][k];
5317
5318 cs_real_t hint = hintp[face_id];
5319 cs_real_t hext = hextp[face_id];
5320 cs_real_t heq = _calc_heq(hint, hext);
5321
5322 cs_b_diff_flux_coupling_vector(idiffp,
5323 pipr,
5324 pjpr,
5325 heq,
5326 fluxi);
5327
5328 for (int k = 0; k < 3; k++)
5329 rhs[jj][k] -= thetap * fluxi[k];
5330 }
5331
5332 BFT_FREE(pvar_local);
5333 /* Sending structures are no longer needed */
5334 BFT_FREE(pvar_distant);
5335 if (df_limiter != NULL) {
5336 BFT_FREE(df_limiter_local);
5337 }
5338 }
5339
5340 /* Unsteady */
5341 } else {
5342
5343 for (int g_id = 0; g_id < n_b_groups; g_id++) {
5344 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
5345 for (int t_id = 0; t_id < n_b_threads; t_id++) {
5346 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
5347 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
5348 face_id++) {
5349
5350 cs_lnum_t ii = b_face_cells[face_id];
5351
5352 cs_real_t fluxi[3] ;
5353 for (int isou = 0; isou < 3; isou++) {
5354 fluxi[isou] = 0;
5355 }
5356 cs_real_3_t pip;
5357 cs_real_3_t _pi;
5358
5359 for (int i = 0; i < 3; i++) {
5360 _pi[i] = _pvar[ii][i];
5361 }
5362
5363 /* Scaling due to mass balance in porous modelling */
5364 if (b_f_face_factor != NULL) {
5365 cs_real_3_t n;
5366 cs_math_3_normalise(b_face_normal[face_id], n);
5367
5368 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pi);
5369 }
5370
5371 cs_real_t bldfrp = (cs_real_t) ircflp;
5372 /* Local limitation of the reconstruction */
5373 if (df_limiter != NULL && ircflp > 0)
5374 bldfrp = CS_MAX(df_limiter[ii], 0.);
5375
5376 cs_b_cd_unsteady_vector(bldfrp,
5377 diipb[face_id],
5378 (const cs_real_3_t *)grad[ii],
5379 _pi,
5380 pip);
5381
5382 cs_b_upwind_flux_vector(iconvp,
5383 thetap,
5384 imasac,
5385 inc,
5386 bc_type[face_id],
5387 _pi,
5388 _pi, /* no relaxation */
5389 pip,
5390 coefav[face_id],
5391 coefbv[face_id],
5392 b_massflux[face_id],
5393 fluxi);
5394
5395 cs_b_diff_flux_vector(idiffp,
5396 thetap,
5397 inc,
5398 pip,
5399 cofafv[face_id],
5400 cofbfv[face_id],
5401 b_visc[face_id],
5402 fluxi);
5403
5404 for(int isou = 0; isou < 3; isou++) {
5405 rhs[ii][isou] -= fluxi[isou];
5406 }
5407
5408 }
5409 }
5410 }
5411
5412 /* The variable is internally coupled and an implicit contribution
5413 * is required */
5414 if (icoupl > 0) {
5415 /* Prepare data for sending */
5416 BFT_MALLOC(pvar_distant, n_distant, cs_real_3_t);
5417
5418 for (cs_lnum_t ii = 0; ii < n_distant; ii++) {
5419 cs_lnum_t face_id = faces_distant[ii];
5420 cs_lnum_t jj = b_face_cells[face_id];
5421
5422 cs_real_3_t pip;
5423 cs_real_3_t _pj;
5424
5425 for (int i = 0; i < 3; i++) {
5426 _pj[i] = _pvar[jj][i];
5427 }
5428
5429 cs_real_t bldfrp = (cs_real_t) ircflp;
5430 /* Local limitation of the reconstruction */
5431 /* Note: to be treated exactly as a internal face, should be a bending
5432 * between the two cells... */
5433 if (df_limiter != NULL && ircflp > 0)
5434 bldfrp = CS_MAX(df_limiter[jj], 0.);
5435
5436 /* Scaling due to mass balance in porous modelling */
5437 if (b_f_face_factor != NULL) {
5438 cs_real_3_t n;
5439 cs_math_3_normalise(b_face_normal[face_id], n);
5440
5441 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pj);
5442 }
5443
5444 cs_b_cd_unsteady_vector(bldfrp,
5445 diipb[face_id],
5446 (const cs_real_3_t *)grad[jj],
5447 _pj,
5448 pip);
5449
5450 for (int k = 0; k < 3; k++)
5451 pvar_distant[ii][k] = pip[k];
5452 }
5453
5454 /* Receive data */
5455 BFT_MALLOC(pvar_local, n_local, cs_real_3_t);
5456 cs_internal_coupling_exchange_var(cpl,
5457 3, /* Dimension */
5458 (cs_real_t *)pvar_distant,
5459 (cs_real_t *)pvar_local);
5460
5461 if (df_limiter != NULL) {
5462 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
5463 cs_internal_coupling_exchange_var(cpl,
5464 1, /* Dimension */
5465 df_limiter,
5466 df_limiter_local);
5467 }
5468
5469 /* Flux contribution */
5470 assert(f != NULL);
5471 cs_real_t *hintp = f->bc_coeffs->hint;
5472 cs_real_t *hextp = f->bc_coeffs->hext;
5473 for (cs_lnum_t ii = 0; ii < n_local; ii++) {
5474 cs_lnum_t face_id = faces_local[ii];
5475 cs_lnum_t jj = b_face_cells[face_id];
5476 cs_real_t pip[3], pjp[3];
5477 cs_real_t fluxi[3] = {0., 0., 0.};
5478 cs_real_3_t _pj;
5479
5480 for (int i = 0; i < 3; i++) {
5481 _pj[i] = _pvar[jj][i];
5482 }
5483
5484 /* Scaling due to mass balance in porous modelling */
5485 if (b_f_face_factor != NULL) {
5486 cs_real_3_t n;
5487 cs_math_3_normalise(b_face_normal[face_id], n);
5488
5489 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pj);
5490 }
5491
5492 cs_real_t bldfrp = (cs_real_t) ircflp;
5493 /* Local limitation of the reconstruction */
5494 if (df_limiter != NULL && ircflp > 0)
5495 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
5496
5497 cs_b_cd_unsteady_vector(bldfrp,
5498 diipb[face_id],
5499 (const cs_real_3_t *)grad[jj],
5500 _pj,
5501 pip);
5502
5503 for (int k = 0; k < 3; k++)
5504 pjp[k] = pvar_local[ii][k];
5505
5506 cs_real_t hint = hintp[face_id];
5507 cs_real_t hext = hextp[face_id];
5508 cs_real_t heq = _calc_heq(hint, hext);
5509
5510 cs_b_diff_flux_coupling_vector(idiffp,
5511 pip,
5512 pjp,
5513 heq,
5514 fluxi);
5515
5516 for (int k = 0; k < 3; k++)
5517 rhs[jj][k] -= thetap * fluxi[k];
5518 }
5519
5520 BFT_FREE(pvar_local);
5521 /* Sending structures are no longer needed */
5522 BFT_FREE(pvar_distant);
5523 if (df_limiter != NULL) {
5524 BFT_FREE(df_limiter_local);
5525 }
5526 }
5527 } /* idtvar */
5528
5529 /* Boundary convective flux imposed at some faces (tags in icvfli array) */
5530 } else if (icvflb == 1) {
5531
5532 /* Retrieve the value of the convective flux to be imposed */
5533 if (f_id != -1) {
5534 coface = (const cs_real_3_t *)(f->bc_coeffs->ac);
5535 cofbce = (const cs_real_33_t *)(f->bc_coeffs->bc);
5536 } else {
5537 bft_error(__FILE__, __LINE__, 0,
5538 _("invalid value of icvflb and f_id"));
5539 }
5540
5541 /* Steady */
5542 if (idtvar < 0) {
5543
5544 for (int g_id = 0; g_id < n_b_groups; g_id++) {
5545 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
5546 for (int t_id = 0; t_id < n_b_threads; t_id++) {
5547 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
5548 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
5549 face_id++) {
5550
5551 cs_lnum_t ii = b_face_cells[face_id];
5552
5553 cs_real_t fluxi[3], pir[3], pipr[3];
5554
5555 for (int isou = 0; isou < 3; isou++) {
5556 fluxi[isou] = 0;
5557 }
5558 cs_real_3_t _pi, _pia;
5559
5560 for (int i = 0; i < 3; i++) {
5561 _pi[i] = _pvar[ii][i];
5562 _pia[i] = pvara[ii][i];
5563 }
5564
5565 /* Scaling due to mass balance in porous modelling */
5566 if (b_f_face_factor != NULL) {
5567 cs_real_3_t n;
5568 cs_math_3_normalise(b_face_normal[face_id], n);
5569
5570 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pi);
5571 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pia);
5572 }
5573
5574 cs_real_t bldfrp = (cs_real_t) ircflp;
5575 /* Local limitation of the reconstruction */
5576 if (df_limiter != NULL && ircflp > 0)
5577 bldfrp = CS_MAX(df_limiter[ii], 0.);
5578
5579 cs_b_cd_steady_vector(bldfrp,
5580 relaxp,
5581 diipb[face_id],
5582 (const cs_real_3_t *)grad[ii],
5583 _pi,
5584 _pia,
5585 pir,
5586 pipr);
5587
5588 cs_b_imposed_conv_flux_vector(iconvp,
5589 1., /* thetap */
5590 1., /* imasac */
5591 inc,
5592 bc_type[face_id],
5593 icvfli[face_id],
5594 _pvar[ii],
5595 pir,
5596 pipr,
5597 coefav[face_id],
5598 coefbv[face_id],
5599 coface[face_id],
5600 cofbce[face_id],
5601 b_massflux[face_id],
5602 fluxi);
5603
5604 cs_b_diff_flux_vector(idiffp,
5605 1., /* thetap */
5606 inc,
5607 pipr,
5608 cofafv[face_id],
5609 cofbfv[face_id],
5610 b_visc[face_id],
5611 fluxi);
5612
5613 for (int isou = 0; isou < 3; isou++) {
5614 rhs[ii][isou] -= fluxi[isou];
5615 }
5616
5617 }
5618 }
5619 }
5620
5621 /* Unsteady */
5622 } else {
5623
5624 for (int g_id = 0; g_id < n_b_groups; g_id++) {
5625 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
5626 for (int t_id = 0; t_id < n_b_threads; t_id++) {
5627 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
5628 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
5629 face_id++) {
5630
5631 cs_lnum_t ii = b_face_cells[face_id];
5632
5633 cs_real_t fluxi[3] ;
5634 for (int isou = 0; isou < 3; isou++) {
5635 fluxi[isou] = 0;
5636 }
5637 cs_real_3_t pip;
5638 cs_real_3_t _pi;
5639
5640 for (int i = 0; i < 3; i++) {
5641 _pi[i] = _pvar[ii][i];
5642 }
5643
5644 /* Scaling due to mass balance in porous modelling */
5645 if (b_f_face_factor != NULL) {
5646 cs_real_3_t n;
5647 cs_math_3_normalise(b_face_normal[face_id], n);
5648
5649 cs_math_3_normal_scaling(n, b_f_face_factor[face_id], _pi);
5650 }
5651
5652 cs_real_t bldfrp = (cs_real_t) ircflp;
5653 /* Local limitation of the reconstruction */
5654 if (df_limiter != NULL && ircflp > 0)
5655 bldfrp = CS_MAX(df_limiter[ii], 0.);
5656
5657 cs_b_cd_unsteady_vector(bldfrp,
5658 diipb[face_id],
5659 (const cs_real_3_t *)grad[ii],
5660 _pi,
5661 pip);
5662
5663 cs_b_imposed_conv_flux_vector(iconvp,
5664 thetap,
5665 imasac,
5666 inc,
5667 bc_type[face_id],
5668 icvfli[face_id],
5669 _pvar[ii],
5670 _pvar[ii], /* no relaxation */
5671 pip,
5672 coefav[face_id],
5673 coefbv[face_id],
5674 coface[face_id],
5675 cofbce[face_id],
5676 b_massflux[face_id],
5677 fluxi);
5678
5679 cs_b_diff_flux_vector(idiffp,
5680 thetap,
5681 inc,
5682 pip,
5683 cofafv[face_id],
5684 cofbfv[face_id],
5685 b_visc[face_id],
5686 fluxi);
5687
5688 for (int isou = 0; isou < 3; isou++) {
5689 rhs[ii][isou] -= fluxi[isou];
5690 }
5691
5692 }
5693 }
5694 }
5695
5696 } /* idtvar */
5697
5698 }
5699
5700 /* 3. Computation of the transpose grad(vel) term and grad(-2/3 div(vel)) */
5701
5702 if (ivisep == 1 && idiffp == 1) {
5703
5704 /* We do not know what condition to put in the inlets and the outlets, so we
5705 assume that there is an equilibrium. Moreover, cells containing a coupled
5706 are removed. */
5707
5708 /* Allocate a temporary array */
5709 BFT_MALLOC(bndcel, n_cells_ext, cs_real_t);
5710
5711 # pragma omp parallel for
5712 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++)
5713 bndcel[cell_id] = 1.;
5714
5715 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
5716 for (cs_lnum_t face_id = 0; face_id < m->n_b_faces; face_id++) {
5717 int ityp = bc_type[face_id];
5718 if ( ityp == CS_OUTLET
5719 || ityp == CS_INLET
5720 || ityp == CS_FREE_INLET
5721 || ityp == CS_CONVECTIVE_INLET
5722 || ityp == CS_COUPLED_FD)
5723 bndcel[b_face_cells[face_id]] = 0.;
5724 }
5725
5726 if (halo != NULL)
5727 cs_halo_sync_var(halo, halo_type, bndcel);
5728
5729 /* ---> Interior faces */
5730
5731 for (int g_id = 0; g_id < n_i_groups; g_id++) {
5732 # pragma omp parallel for
5733 for (int t_id = 0; t_id < n_i_threads; t_id++) {
5734 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
5735 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
5736 face_id++) {
5737
5738 cs_lnum_t ii = i_face_cells[face_id][0];
5739 cs_lnum_t jj = i_face_cells[face_id][1];
5740
5741 double pnd = weight[face_id];
5742 double secvis = i_secvis[face_id]; /* - 2/3 * mu */
5743 double visco = i_visc[face_id]; /* mu S_ij / d_ij */
5744
5745 double grdtrv = pnd*(grad[ii][0][0]+grad[ii][1][1]+grad[ii][2][2])
5746 + (1.-pnd)*(grad[jj][0][0]+grad[jj][1][1]+grad[jj][2][2]);
5747
5748 cs_real_3_t n, ipjp;
5749 cs_math_3_normalise(i_face_normal[face_id], n);
5750
5751 /* I'J' */
5752 for (int i = 0; i < 3; i++)
5753 ipjp[i] = n[i] * i_dist[face_id];
5754
5755 /* We need to compute trans_grad(u).I'J' which is equal to I'J'.grad(u) */
5756 for (int isou = 0; isou < 3; isou++) {
5757
5758 double tgrdfl = ipjp[0] * ( pnd*grad[ii][0][isou]
5759 + (1.-pnd)*grad[jj][0][isou])
5760 + ipjp[1] * ( pnd*grad[ii][1][isou]
5761 + (1.-pnd)*grad[jj][1][isou])
5762 + ipjp[2] * ( pnd*grad[ii][2][isou]
5763 + (1.-pnd)*grad[jj][2][isou]);
5764
5765 double flux = visco*tgrdfl + secvis*grdtrv*i_f_face_normal[face_id][isou];
5766
5767 rhs[ii][isou] += thetap * flux*bndcel[ii];
5768 rhs[jj][isou] -= thetap * flux*bndcel[jj];
5769
5770 }
5771
5772 }
5773 }
5774 }
5775
5776 /* ---> Boundary FACES
5777 the whole flux term of the stress tensor is already taken into account
5778 (so, no corresponding term in forbr)
5779 TODO in theory we should take the normal component into account (the
5780 tangential one is modeled by the wall law) */
5781
5782 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
5783 for (cs_lnum_t face_id = 0; face_id < m->n_b_faces; face_id++) {
5784 cs_lnum_t ii = b_face_cells[face_id];
5785
5786 /* Trace of velocity gradient */
5787 double grdtrv = (grad[ii][0][0]+grad[ii][1][1]+grad[ii][2][2]);
5788 double secvis = b_secvis[face_id]; /* - 2/3 * mu */
5789
5790 for (int isou = 0; isou < 3; isou++) {
5791
5792 double flux = secvis*grdtrv*b_f_face_normal[face_id][isou];
5793 rhs[ii][isou] += thetap * flux * bndcel[ii];
5794
5795 }
5796
5797 }
5798
5799 /*Free memory */
5800 BFT_FREE(bndcel);
5801
5802 }
5803
5804 /* Free memory */
5805 BFT_FREE(grdpa);
5806 BFT_FREE(grad);
5807 }
5808
5809 /*----------------------------------------------------------------------------*/
5810 /*!
5811 * \brief Add the explicit part of the convection/diffusion terms of a transport
5812 * equation of a vector field \f$ \vect{\varia} \f$.
5813 *
5814 * More precisely, the right hand side \f$ \vect{Rhs} \f$ is updated as
5815 * follows:
5816 * \f[
5817 * \vect{Rhs} = \vect{Rhs} - \sum_{\fij \in \Facei{\celli}} \left(
5818 * \dot{m}_\ij \left( \vect{\varia}_\fij - \vect{\varia}_\celli \right)
5819 * - \mu_\fij \gradt_\fij \vect{\varia} \cdot \vect{S}_\ij \right)
5820 * \f]
5821 *
5822 * Warning:
5823 * - \f$ \vect{Rhs} \f$ has already been initialized before calling bilsc!
5824 * - mind the sign minus
5825 *
5826 * \param[in] idtvar indicator of the temporal scheme
5827 * \param[in] f_id index of the current variable
5828 * \param[in] var_cal_opt variable calculation options
5829 * \param[in] icvflb global indicator of boundary convection flux
5830 * - 0 upwind scheme at all boundary faces
5831 * - 1 imposed flux at some boundary faces
5832 * \param[in] inc indicator
5833 * - 0 when solving an increment
5834 * - 1 otherwise
5835 * \param[in] imasac take mass accumulation into account?
5836 * \param[in] pvar solved velocity (current time step)
5837 * \param[in] pvara solved velocity (previous time step)
5838 * \param[in] coefa boundary condition array for the variable
5839 * (Explicit part)
5840 * \param[in] coefb boundary condition array for the variable
5841 * (Implicit part)
5842 * \param[in] cofaf boundary condition array for the diffusion
5843 * of the variable (Explicit part)
5844 * \param[in] cofbf boundary condition array for the diffusion
5845 * of the variable (Implicit part)
5846 * \param[in] i_massflux mass flux at interior faces
5847 * \param[in] b_massflux mass flux at boundary faces
5848 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
5849 * at interior faces for the r.h.s.
5850 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
5851 * at border faces for the r.h.s.
5852 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
5853 */
5854 /*----------------------------------------------------------------------------*/
5855
5856 void
cs_convection_diffusion_tensor(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int icvflb,int inc,int imasac,cs_real_6_t * restrict pvar,const cs_real_6_t * restrict pvara,const cs_real_6_t coefa[],const cs_real_66_t coefb[],const cs_real_6_t cofaf[],const cs_real_66_t cofbf[],const cs_real_t i_massflux[],const cs_real_t b_massflux[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_6_t * restrict rhs)5857 cs_convection_diffusion_tensor(int idtvar,
5858 int f_id,
5859 const cs_var_cal_opt_t var_cal_opt,
5860 int icvflb,
5861 int inc,
5862 int imasac,
5863 cs_real_6_t *restrict pvar,
5864 const cs_real_6_t *restrict pvara,
5865 const cs_real_6_t coefa[],
5866 const cs_real_66_t coefb[],
5867 const cs_real_6_t cofaf[],
5868 const cs_real_66_t cofbf[],
5869 const cs_real_t i_massflux[],
5870 const cs_real_t b_massflux[],
5871 const cs_real_t i_visc[],
5872 const cs_real_t b_visc[],
5873 cs_real_6_t *restrict rhs)
5874 {
5875 const int iconvp = var_cal_opt.iconv;
5876 const int idiffp = var_cal_opt.idiff;
5877 const int nswrgp = var_cal_opt.nswrgr;
5878 const int imrgra = var_cal_opt.imrgra;
5879 const int imligp = var_cal_opt.imligr;
5880 const int ircflp = var_cal_opt.ircflu;
5881 const int ischcp = var_cal_opt.ischcv;
5882 const int isstpp = var_cal_opt.isstpc;
5883 const int iwarnp = var_cal_opt.verbosity;
5884 const double blencp = var_cal_opt.blencv;
5885 const double blend_st = var_cal_opt.blend_st;
5886 const double epsrgp = var_cal_opt.epsrgr;
5887 const double climgp = var_cal_opt.climgr;
5888 const double relaxp = var_cal_opt.relaxv;
5889 const double thetap = var_cal_opt.thetav;
5890
5891 const cs_mesh_t *m = cs_glob_mesh;
5892 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
5893
5894 const cs_lnum_t n_cells = m->n_cells;
5895 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
5896 const int n_i_groups = m->i_face_numbering->n_groups;
5897 const int n_i_threads = m->i_face_numbering->n_threads;
5898 const int n_b_groups = m->b_face_numbering->n_groups;
5899 const int n_b_threads = m->b_face_numbering->n_threads;
5900 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
5901 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
5902
5903 const cs_lnum_2_t *restrict i_face_cells
5904 = (const cs_lnum_2_t *restrict)m->i_face_cells;
5905 const cs_lnum_t *restrict b_face_cells
5906 = (const cs_lnum_t *restrict)m->b_face_cells;
5907 const cs_real_t *restrict weight = fvq->weight;
5908 const cs_real_t *restrict i_dist = fvq->i_dist;
5909 const cs_real_t *restrict i_face_surf = fvq->i_face_surf;
5910 const cs_real_t *restrict cell_vol = fvq->cell_vol;
5911 const cs_real_3_t *restrict cell_cen
5912 = (const cs_real_3_t *restrict)fvq->cell_cen;
5913 const cs_real_3_t *restrict i_face_normal
5914 = (const cs_real_3_t *restrict)fvq->i_face_normal;
5915 const cs_real_3_t *restrict i_face_cog
5916 = (const cs_real_3_t *restrict)fvq->i_face_cog;
5917 const cs_real_3_t *restrict diipf
5918 = (const cs_real_3_t *restrict)fvq->diipf;
5919 const cs_real_3_t *restrict djjpf
5920 = (const cs_real_3_t *restrict)fvq->djjpf;
5921 const cs_real_3_t *restrict diipb
5922 = (const cs_real_3_t *restrict)fvq->diipb;
5923
5924 cs_real_t *df_limiter = NULL;
5925
5926 const int *bc_type = cs_glob_bc_type;
5927
5928 /* Local variables */
5929
5930 char var_name[64];
5931
5932 cs_gnum_t n_upwind;
5933 int iupwin;
5934
5935 cs_real_63_t *grad, *grdpa;
5936
5937 cs_field_t *f;
5938
5939 cs_real_t *v_slope_test = cs_get_v_slope_test(f_id, var_cal_opt);
5940
5941 /*==========================================================================*/
5942
5943 /* 1. Initialization */
5944
5945 /* Allocate work arrays */
5946
5947 BFT_MALLOC(grad, n_cells_ext, cs_real_63_t);
5948 BFT_MALLOC(grdpa, n_cells_ext, cs_real_63_t);
5949
5950 /* Choose gradient type */
5951
5952 cs_halo_type_t halo_type = CS_HALO_STANDARD;
5953 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
5954
5955 cs_gradient_type_by_imrgra(imrgra,
5956 &gradient_type,
5957 &halo_type);
5958
5959 /* Handle cases where only the previous values (already synchronized)
5960 or current values are provided */
5961
5962 if (pvar != NULL && m->halo != NULL) {
5963 cs_halo_sync_var_strided(m->halo, halo_type, (cs_real_t *)pvar, 6);
5964 if (cs_glob_mesh->n_init_perio > 0)
5965 cs_halo_perio_sync_var_sym_tens(m->halo, halo_type, (cs_real_t *)pvar);
5966 }
5967 if (pvara == NULL)
5968 pvara = (const cs_real_6_t *restrict)pvar;
5969
5970 const cs_real_6_t *restrict _pvar
5971 = (pvar != NULL) ? (const cs_real_6_t *restrict)pvar : pvara;
5972
5973 /* Logging info */
5974
5975 if (f_id != -1) {
5976 f = cs_field_by_id(f_id);
5977
5978 int df_limiter_id =
5979 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
5980 if (df_limiter_id > -1)
5981 df_limiter = cs_field_by_id(df_limiter_id)->val;
5982
5983 snprintf(var_name, 63, "%s", f->name);
5984 }
5985 else
5986 strncpy(var_name, "[convection-diffusion, tensor]", 63);
5987 var_name[63] = '\0';
5988
5989 if (iwarnp >= 2 && iconvp == 1) {
5990 if (ischcp == 1) {
5991 bft_printf
5992 (
5993 _(" %s: Convection in centered blending with %f percent of upwind\n"),
5994 var_name, (1.-blencp)*100.);
5995 } else {
5996 bft_printf
5997 (
5998 _(" %s: Convection in 2nd order blending with %f percent of upwind\n"),
5999 var_name, (1.-blencp)*100.);
6000 }
6001 }
6002
6003 iupwin = (blencp > 0.) ? 0 : 1;
6004
6005 /* 2. Compute the balance with reconstruction */
6006
6007 /* Compute the gradient of the velocity
6008
6009 The gradient (grad) is used in the flux reconstruction and the slope test.
6010 Thus we must compute it:
6011 - when we have diffusion and we reconstruct the fluxes,
6012 - when the convection scheme is SOLU,
6013 - when we have convection, we are not in pure upwind
6014 and we reconstruct the fluxes,
6015 - when we have convection, we are not in pure upwind
6016 and we have not shunted the slope test. */
6017
6018 if ( (idiffp != 0 && ircflp == 1)
6019 || ( iconvp != 0 && iupwin == 0
6020 && (ischcp == 0 || ircflp == 1 || isstpp == 0))) {
6021
6022 cs_gradient_tensor_synced_input(var_name,
6023 gradient_type,
6024 halo_type,
6025 inc,
6026 nswrgp,
6027 iwarnp,
6028 imligp,
6029 epsrgp,
6030 climgp,
6031 coefa,
6032 coefb,
6033 _pvar,
6034 grad);
6035
6036 } else {
6037 # pragma omp parallel for
6038 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
6039 for (int isou = 0; isou < 6; isou++) {
6040 for (int jsou = 0; jsou < 3; jsou++)
6041 grad[cell_id][isou][jsou] = 0.;
6042 }
6043 }
6044 }
6045
6046 /* ======================================================================
6047 ---> Compute uncentered gradient grdpa for the slope test
6048 ======================================================================*/
6049
6050 # pragma omp parallel for
6051 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
6052 for (int jsou = 0; jsou < 3; jsou++) {
6053 for (int isou = 0; isou < 6; isou++)
6054 grdpa[cell_id][isou][jsou] = 0.;
6055 }
6056 }
6057
6058 if (iconvp > 0 && iupwin == 0 && isstpp == 0) {
6059
6060 cs_slope_test_gradient_tensor(inc,
6061 halo_type,
6062 (const cs_real_63_t *)grad,
6063 grdpa,
6064 _pvar,
6065 coefa,
6066 coefb,
6067 i_massflux);
6068
6069 }
6070
6071 /* ======================================================================
6072 ---> Contribution from interior faces
6073 ======================================================================*/
6074
6075 n_upwind = 0;
6076
6077 if (n_cells_ext > n_cells) {
6078 # pragma omp parallel for
6079 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
6080 for (int isou = 0; isou < 6; isou++)
6081 rhs[cell_id][isou] = 0.;
6082 }
6083 }
6084
6085 /* --> Pure upwind flux
6086 =====================*/
6087
6088 if (iupwin == 1) {
6089
6090 /* Steady */
6091 if (idtvar < 0) {
6092
6093 for (int g_id = 0; g_id < n_i_groups; g_id++) {
6094 # pragma omp parallel for reduction(+:n_upwind)
6095 for (int t_id = 0; t_id < n_i_threads; t_id++) {
6096 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
6097 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
6098 face_id++) {
6099
6100 cs_lnum_t ii = i_face_cells[face_id][0];
6101 cs_lnum_t jj = i_face_cells[face_id][1];
6102
6103 /* in parallel, face will be counted by one and only one rank */
6104 if (ii < n_cells) {
6105 n_upwind++;
6106 }
6107 double fluxi[6], fluxj[6] ;
6108 for (int isou = 0; isou < 6; isou++) {
6109 fluxi[isou] = 0;
6110 fluxj[isou] = 0;
6111 }
6112 cs_real_6_t pip, pjp, pipr, pjpr;
6113 cs_real_6_t pifri, pifrj, pjfri, pjfrj;
6114
6115 cs_real_t bldfrp = (cs_real_t) ircflp;
6116 /* Local limitation of the reconstruction */
6117 if (df_limiter != NULL && ircflp > 0)
6118 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
6119
6120 cs_i_cd_steady_upwind_tensor(bldfrp,
6121 relaxp,
6122 diipf[face_id],
6123 djjpf[face_id],
6124 (const cs_real_3_t *)grad[ii],
6125 (const cs_real_3_t *)grad[jj],
6126 _pvar[ii],
6127 _pvar[jj],
6128 pvara[ii],
6129 pvara[jj],
6130 pifri,
6131 pifrj,
6132 pjfri,
6133 pjfrj,
6134 pip,
6135 pjp,
6136 pipr,
6137 pjpr);
6138
6139
6140 cs_i_conv_flux_tensor(iconvp,
6141 1.,
6142 1,
6143 _pvar[ii],
6144 _pvar[jj],
6145 pifri,
6146 pifrj,
6147 pjfri,
6148 pjfrj,
6149 i_massflux[face_id],
6150 fluxi,
6151 fluxj);
6152
6153
6154 cs_i_diff_flux_tensor(idiffp,
6155 1.,
6156 pip,
6157 pjp,
6158 pipr,
6159 pjpr,
6160 i_visc[face_id],
6161 fluxi,
6162 fluxj);
6163
6164 for (int isou = 0; isou < 6; isou++) {
6165 rhs[ii][isou] -= fluxi[isou];
6166 rhs[jj][isou] += fluxj[isou];
6167 }
6168
6169 }
6170 }
6171 }
6172
6173 /* Unsteady */
6174 } else {
6175
6176 for (int g_id = 0; g_id < n_i_groups; g_id++) {
6177 # pragma omp parallel for reduction(+:n_upwind)
6178 for (int t_id = 0; t_id < n_i_threads; t_id++) {
6179 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
6180 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
6181 face_id++) {
6182
6183 cs_lnum_t ii = i_face_cells[face_id][0];
6184 cs_lnum_t jj = i_face_cells[face_id][1];
6185
6186 /* in parallel, face will be counted by one and only one rank */
6187 if (ii < n_cells) {
6188 n_upwind++;
6189 }
6190 double fluxi[6], fluxj[6] ;
6191 for (int isou = 0; isou < 6; isou++) {
6192 fluxi[isou] = 0;
6193 fluxj[isou] = 0;
6194 }
6195 cs_real_6_t pip, pjp;
6196 cs_real_6_t pif, pjf;
6197
6198 cs_real_t bldfrp = (cs_real_t) ircflp;
6199 /* Local limitation of the reconstruction */
6200 if (df_limiter != NULL && ircflp > 0)
6201 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
6202
6203 cs_i_cd_unsteady_upwind_tensor(bldfrp,
6204 diipf[face_id],
6205 djjpf[face_id],
6206 (const cs_real_3_t *)grad[ii],
6207 (const cs_real_3_t *)grad[jj],
6208 _pvar[ii],
6209 _pvar[jj],
6210 pif,
6211 pjf,
6212 pip,
6213 pjp);
6214
6215 cs_i_conv_flux_tensor(iconvp,
6216 thetap,
6217 imasac,
6218 _pvar[ii],
6219 _pvar[jj],
6220 pif,
6221 pif, /* no relaxation */
6222 pjf,
6223 pjf, /* no relaxation */
6224 i_massflux[face_id],
6225 fluxi,
6226 fluxj);
6227
6228
6229 cs_i_diff_flux_tensor(idiffp,
6230 thetap,
6231 pip,
6232 pjp,
6233 pip, /* no relaxation */
6234 pjp, /* no relaxation */
6235 i_visc[face_id],
6236 fluxi,
6237 fluxj);
6238
6239 for (int isou = 0; isou < 6; isou++) {
6240
6241 rhs[ii][isou] -= fluxi[isou];
6242 rhs[jj][isou] += fluxj[isou];
6243 }
6244
6245 }
6246 }
6247 }
6248
6249 }
6250
6251 /* --> Flux with no slope test
6252 ============================*/
6253
6254 } else if (isstpp == 1) {
6255
6256 if (ischcp < 0 || ischcp > 1) {
6257 bft_error(__FILE__, __LINE__, 0,
6258 _("invalid value of ischcp"));
6259 }
6260
6261 /* Steady */
6262 if (idtvar < 0) {
6263
6264 for (int g_id = 0; g_id < n_i_groups; g_id++) {
6265 # pragma omp parallel for
6266
6267 for (int t_id = 0; t_id < n_i_threads; t_id++) {
6268 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
6269 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
6270 face_id++) {
6271
6272 cs_lnum_t ii = i_face_cells[face_id][0];
6273 cs_lnum_t jj = i_face_cells[face_id][1];
6274
6275 double fluxi[6], fluxj[6] ;
6276 for (int isou = 0; isou < 6; isou++) {
6277 fluxi[isou] = 0;
6278 fluxj[isou] = 0;
6279 }
6280 cs_real_6_t pip, pjp, pipr, pjpr;
6281 cs_real_6_t pifri, pifrj, pjfri, pjfrj;
6282
6283 cs_real_t bldfrp = (cs_real_t) ircflp;
6284 /* Local limitation of the reconstruction */
6285 if (df_limiter != NULL && ircflp > 0)
6286 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
6287
6288 cs_i_cd_steady_tensor(bldfrp,
6289 ischcp,
6290 relaxp,
6291 blencp,
6292 weight[face_id],
6293 cell_cen[ii],
6294 cell_cen[jj],
6295 i_face_cog[face_id],
6296 diipf[face_id],
6297 djjpf[face_id],
6298 (const cs_real_3_t *)grad[ii],
6299 (const cs_real_3_t *)grad[jj],
6300 _pvar[ii],
6301 _pvar[jj],
6302 pvara[ii],
6303 pvara[jj],
6304 pifri,
6305 pifrj,
6306 pjfri,
6307 pjfrj,
6308 pip,
6309 pjp,
6310 pipr,
6311 pjpr);
6312
6313 cs_i_conv_flux_tensor(iconvp,
6314 1.,
6315 1,
6316 _pvar[ii],
6317 _pvar[jj],
6318 pifri,
6319 pifrj,
6320 pjfri,
6321 pjfrj,
6322 i_massflux[face_id],
6323 fluxi,
6324 fluxj);
6325
6326
6327 cs_i_diff_flux_tensor(idiffp,
6328 1.,
6329 pip,
6330 pjp,
6331 pipr,
6332 pjpr,
6333 i_visc[face_id],
6334 fluxi,
6335 fluxj);
6336
6337 for (int isou = 0; isou < 6; isou++) {
6338 rhs[ii][isou] -= fluxi[isou];
6339 rhs[jj][isou] += fluxj[isou];
6340 }
6341
6342 }
6343 }
6344 }
6345
6346 /* Unsteady */
6347 } else {
6348
6349 for (int g_id = 0; g_id < n_i_groups; g_id++) {
6350 # pragma omp parallel for
6351 for (int t_id = 0; t_id < n_i_threads; t_id++) {
6352 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
6353 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
6354 face_id++) {
6355
6356 cs_lnum_t ii = i_face_cells[face_id][0];
6357 cs_lnum_t jj = i_face_cells[face_id][1];
6358
6359 double fluxi[6], fluxj[6] ;
6360 for (int isou = 0; isou < 6; isou++) {
6361 fluxi[isou] = 0;
6362 fluxj[isou] = 0;
6363 }
6364 cs_real_6_t pip, pjp;
6365 cs_real_6_t pif, pjf;
6366
6367 cs_real_t bldfrp = (cs_real_t) ircflp;
6368 /* Local limitation of the reconstruction */
6369 if (df_limiter != NULL && ircflp > 0)
6370 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
6371
6372 cs_i_cd_unsteady_tensor(bldfrp,
6373 ischcp,
6374 blencp,
6375 weight[face_id],
6376 cell_cen[ii],
6377 cell_cen[jj],
6378 i_face_cog[face_id],
6379 diipf[face_id],
6380 djjpf[face_id],
6381 (const cs_real_3_t *)grad[ii],
6382 (const cs_real_3_t *)grad[jj],
6383 _pvar[ii],
6384 _pvar[jj],
6385 pif,
6386 pjf,
6387 pip,
6388 pjp);
6389
6390 cs_i_conv_flux_tensor(iconvp,
6391 thetap,
6392 imasac,
6393 _pvar[ii],
6394 _pvar[jj],
6395 pif,
6396 pif, /* no relaxation */
6397 pjf,
6398 pjf, /* no relaxation */
6399 i_massflux[face_id],
6400 fluxi,
6401 fluxj);
6402
6403
6404 cs_i_diff_flux_tensor(idiffp,
6405 thetap,
6406 pip,
6407 pjp,
6408 pip, /* no relaxation */
6409 pjp, /* no relaxation */
6410 i_visc[face_id],
6411 fluxi,
6412 fluxj);
6413
6414 for (int isou = 0; isou < 6; isou++) {
6415 rhs[ii][isou] -= fluxi[isou];
6416 rhs[jj][isou] += fluxj[isou];
6417 }
6418 }
6419 }
6420 }
6421 }
6422
6423 /* --> Flux with slope test
6424 =========================*/
6425
6426 } else {
6427
6428 if (ischcp < 0 || ischcp > 1) {
6429 bft_error(__FILE__, __LINE__, 0,
6430 _("invalid value of ischcp"));
6431 }
6432
6433 /* Steady */
6434 if (idtvar < 0) {
6435
6436 for (int g_id = 0; g_id < n_i_groups; g_id++) {
6437 # pragma omp parallel for reduction(+:n_upwind)
6438 for (int t_id = 0; t_id < n_i_threads; t_id++) {
6439 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
6440 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
6441 face_id++) {
6442
6443 cs_lnum_t ii = i_face_cells[face_id][0];
6444 cs_lnum_t jj = i_face_cells[face_id][1];
6445
6446 double fluxi[6], fluxj[6] ;
6447 for (int isou = 0; isou < 6; isou++) {
6448 fluxi[isou] = 0;
6449 fluxj[isou] = 0;
6450 }
6451 cs_real_6_t pip, pjp, pipr, pjpr;
6452 cs_real_6_t pifri, pifrj, pjfri, pjfrj;
6453 bool upwind_switch = false;
6454
6455 cs_real_t bldfrp = (cs_real_t) ircflp;
6456 /* Local limitation of the reconstruction */
6457 if (df_limiter != NULL && ircflp > 0)
6458 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
6459
6460 cs_i_cd_steady_slope_test_tensor(&upwind_switch,
6461 iconvp,
6462 bldfrp,
6463 ischcp,
6464 relaxp,
6465 blencp,
6466 blend_st,
6467 weight[face_id],
6468 i_dist[face_id],
6469 i_face_surf[face_id],
6470 cell_cen[ii],
6471 cell_cen[jj],
6472 i_face_normal[face_id],
6473 i_face_cog[face_id],
6474 diipf[face_id],
6475 djjpf[face_id],
6476 i_massflux[face_id],
6477 (const cs_real_3_t *)grad[ii],
6478 (const cs_real_3_t *)grad[jj],
6479 (const cs_real_3_t *)grdpa[ii],
6480 (const cs_real_3_t *)grdpa[jj],
6481 _pvar[ii],
6482 _pvar[jj],
6483 pvara[ii],
6484 pvara[jj],
6485 pifri,
6486 pifrj,
6487 pjfri,
6488 pjfrj,
6489 pip,
6490 pjp,
6491 pipr,
6492 pjpr);
6493
6494 cs_i_conv_flux_tensor(iconvp,
6495 1.,
6496 1,
6497 _pvar[ii],
6498 _pvar[jj],
6499 pifri,
6500 pifrj,
6501 pjfri,
6502 pjfrj,
6503 i_massflux[face_id],
6504 fluxi,
6505 fluxj);
6506
6507
6508 cs_i_diff_flux_tensor(idiffp,
6509 1.,
6510 pip,
6511 pjp,
6512 pipr,
6513 pjpr,
6514 i_visc[face_id],
6515 fluxi,
6516 fluxj);
6517
6518 for (int isou = 0; isou < 6; isou++) {
6519 rhs[ii][isou] -= fluxi[isou];
6520 rhs[jj][isou] += fluxj[isou];
6521 }
6522
6523 }
6524 }
6525 }
6526
6527 /* Unsteady */
6528 } else {
6529
6530 for (int g_id = 0; g_id < n_i_groups; g_id++) {
6531 # pragma omp parallel for reduction(+:n_upwind)
6532 for (int t_id = 0; t_id < n_i_threads; t_id++) {
6533 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
6534 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
6535 face_id++) {
6536
6537 cs_lnum_t ii = i_face_cells[face_id][0];
6538 cs_lnum_t jj = i_face_cells[face_id][1];
6539
6540 double fluxi[6], fluxj[6] ;
6541 for (int isou = 0; isou < 6; isou++) {
6542 fluxi[isou] = 0;
6543 fluxj[isou] = 0;
6544 }
6545 cs_real_6_t pip, pjp;
6546 cs_real_6_t pif, pjf;
6547 bool upwind_switch = false;
6548
6549 cs_real_t bldfrp = (cs_real_t) ircflp;
6550 /* Local limitation of the reconstruction */
6551 if (df_limiter != NULL && ircflp > 0)
6552 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
6553
6554 cs_i_cd_unsteady_slope_test_tensor(&upwind_switch,
6555 iconvp,
6556 bldfrp,
6557 ischcp,
6558 blencp,
6559 blend_st,
6560 weight[face_id],
6561 i_dist[face_id],
6562 i_face_surf[face_id],
6563 cell_cen[ii],
6564 cell_cen[jj],
6565 i_face_normal[face_id],
6566 i_face_cog[face_id],
6567 diipf[face_id],
6568 djjpf[face_id],
6569 i_massflux[face_id],
6570 (const cs_real_3_t *)grad[ii],
6571 (const cs_real_3_t *)grad[jj],
6572 (const cs_real_3_t *)grdpa[ii],
6573 (const cs_real_3_t *)grdpa[jj],
6574 _pvar[ii],
6575 _pvar[jj],
6576 pif,
6577 pjf,
6578 pip,
6579 pjp);
6580
6581 cs_i_conv_flux_tensor(iconvp,
6582 thetap,
6583 imasac,
6584 _pvar[ii],
6585 _pvar[jj],
6586 pif,
6587 pif, /* no relaxation */
6588 pjf,
6589 pjf, /* no relaxation */
6590 i_massflux[face_id],
6591 fluxi,
6592 fluxj);
6593
6594
6595 cs_i_diff_flux_tensor(idiffp,
6596 thetap,
6597 pip,
6598 pjp,
6599 pip, /* no relaxation */
6600 pjp, /* no relaxation */
6601 i_visc[face_id],
6602 fluxi,
6603 fluxj);
6604
6605 if (upwind_switch) {
6606 /* in parallel, face will be counted by one and only one rank */
6607 if (ii < n_cells)
6608 n_upwind++;
6609
6610 if (v_slope_test != NULL) {
6611 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
6612 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
6613 }
6614 }
6615
6616 for (int isou = 0; isou < 6; isou++) {
6617 rhs[ii][isou] -= fluxi[isou];
6618 rhs[jj][isou] += fluxj[isou];
6619 } /* isou */
6620 }
6621 }
6622 }
6623 } /* idtvar */
6624 } /* iupwin */
6625
6626 if (iwarnp >= 2 && iconvp == 1) {
6627
6628 /* Sum number of clippings */
6629 cs_parall_counter(&n_upwind, 1);
6630
6631 bft_printf(_(" %s: %llu Faces with upwind on %llu interior faces\n"),
6632 var_name, (unsigned long long)n_upwind,
6633 (unsigned long long)m->n_g_i_c_faces);
6634 }
6635
6636 /* ======================================================================
6637 ---> Contribution from boundary faces
6638 ======================================================================*/
6639
6640 /* Boundary convective flux are all computed with an upwind scheme */
6641 if (icvflb == 0) {
6642
6643 /* Steady */
6644 if (idtvar < 0) {
6645
6646 for (int g_id = 0; g_id < n_b_groups; g_id++) {
6647 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
6648 for (int t_id = 0; t_id < n_b_threads; t_id++) {
6649 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
6650 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
6651 face_id++) {
6652
6653 cs_lnum_t ii = b_face_cells[face_id];
6654
6655 double fluxi[6] ;
6656 for (int isou = 0; isou < 6; isou++) {
6657 fluxi[isou] = 0;
6658 }
6659 cs_real_6_t pir, pipr;
6660
6661 cs_real_t bldfrp = (cs_real_t) ircflp;
6662 /* Local limitation of the reconstruction */
6663 if (df_limiter != NULL && ircflp > 0)
6664 bldfrp = CS_MAX(df_limiter[ii], 0.);
6665
6666 cs_b_cd_steady_tensor(bldfrp,
6667 relaxp,
6668 diipb[face_id],
6669 (const cs_real_3_t *)grad[ii],
6670 _pvar[ii],
6671 pvara[ii],
6672 pir,
6673 pipr);
6674
6675 cs_b_upwind_flux_tensor(iconvp,
6676 1., /* thetap */
6677 1, /* imasac */
6678 inc,
6679 bc_type[face_id],
6680 _pvar[ii],
6681 pir,
6682 pipr,
6683 coefa[face_id],
6684 coefb[face_id],
6685 b_massflux[face_id],
6686 fluxi);
6687
6688 cs_b_diff_flux_tensor(idiffp,
6689 1., /* thetap */
6690 inc,
6691 pipr,
6692 cofaf[face_id],
6693 cofbf[face_id],
6694 b_visc[face_id],
6695 fluxi);
6696
6697 for (int isou = 0; isou < 6; isou++) {
6698 rhs[ii][isou] -= fluxi[isou];
6699 }
6700 }
6701 }
6702 }
6703
6704 /* Unsteady */
6705 } else {
6706
6707 for (int g_id = 0; g_id < n_b_groups; g_id++) {
6708 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
6709 for (int t_id = 0; t_id < n_b_threads; t_id++) {
6710 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
6711 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
6712 face_id++) {
6713
6714 cs_lnum_t ii = b_face_cells[face_id];
6715
6716 double fluxi[6] ;
6717 for (int isou = 0; isou < 6; isou++) {
6718 fluxi[isou] = 0;
6719 }
6720 cs_real_6_t pip;
6721
6722 cs_real_t bldfrp = (cs_real_t) ircflp;
6723 /* Local limitation of the reconstruction */
6724 if (df_limiter != NULL && ircflp > 0)
6725 bldfrp = CS_MAX(df_limiter[ii], 0.);
6726
6727 cs_b_cd_unsteady_tensor(bldfrp,
6728 diipb[face_id],
6729 (const cs_real_3_t *)grad[ii],
6730 _pvar[ii],
6731 pip);
6732
6733 cs_b_upwind_flux_tensor(iconvp,
6734 thetap,
6735 imasac,
6736 inc,
6737 bc_type[face_id],
6738 _pvar[ii],
6739 _pvar[ii], /* no relaxation */
6740 pip,
6741 coefa[face_id],
6742 coefb[face_id],
6743 b_massflux[face_id],
6744 fluxi);
6745
6746 cs_b_diff_flux_tensor(idiffp,
6747 thetap,
6748 inc,
6749 pip,
6750 cofaf[face_id],
6751 cofbf[face_id],
6752 b_visc[face_id],
6753 fluxi);
6754
6755 for(int isou = 0; isou < 6; isou++) {
6756 rhs[ii][isou] -= fluxi[isou];
6757 } /* isou */
6758 }
6759 }
6760 }
6761
6762 } /* idtvar */
6763
6764 }
6765
6766 /* Free memory */
6767 BFT_FREE(grdpa);
6768 BFT_FREE(grad);
6769 }
6770
6771 /*----------------------------------------------------------------------------*/
6772 /*!
6773 * \brief Add the explicit part of the convection/diffusion terms of a transport
6774 * equation of a scalar field \f$ \varia \f$ such as the temperature.
6775 *
6776 * More precisely, the right hand side \f$ Rhs \f$ is updated as
6777 * follows:
6778 * \f[
6779 * Rhs = Rhs + \sum_{\fij \in \Facei{\celli}} \left(
6780 * C_p\dot{m}_\ij \varia_\fij
6781 * - \lambda_\fij \gradv_\fij \varia \cdot \vect{S}_\ij \right)
6782 * \f]
6783 *
6784 * Warning:
6785 * \f$ Rhs \f$ has already been initialized before calling bilsct!
6786 *
6787 * \param[in] idtvar indicator of the temporal scheme
6788 * \param[in] f_id index of the current variable
6789 * \param[in] var_cal_opt variable calculation options
6790 * \param[in] inc indicator
6791 * - 0 when solving an increment
6792 * - 1 otherwise
6793 * \param[in] iccocg indicator
6794 * - 1 re-compute cocg matrix
6795 * (for iterative gradients)
6796 * - 0 otherwise
6797 * \param[in] imasac take mass accumulation into account?
6798 * \param[in] pvar solved variable (current time step)
6799 * \param[in] pvara solved variable (previous time step)
6800 * \param[in] coefap boundary condition array for the variable
6801 * (explicit part)
6802 * \param[in] coefbp boundary condition array for the variable
6803 * (implicit part)
6804 * \param[in] cofafp boundary condition array for the diffusion
6805 * of the variable (explicit part)
6806 * \param[in] cofbfp boundary condition array for the diffusion
6807 * of the variable (implicit part)
6808 * \param[in] i_massflux mass flux at interior faces
6809 * \param[in] b_massflux mass flux at boundary faces
6810 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
6811 * at interior faces for the r.h.s.
6812 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
6813 * at border faces for the r.h.s.
6814 * \param[in] xcpp array of specific heat (\f$ C_p \f$)
6815 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
6816 */
6817 /*----------------------------------------------------------------------------*/
6818
6819 void
cs_convection_diffusion_thermal(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int inc,int iccocg,int imasac,cs_real_t * restrict pvar,const cs_real_t * restrict pvara,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_massflux[],const cs_real_t b_massflux[],const cs_real_t i_visc[],const cs_real_t b_visc[],const cs_real_t xcpp[],cs_real_t * restrict rhs)6820 cs_convection_diffusion_thermal(int idtvar,
6821 int f_id,
6822 const cs_var_cal_opt_t var_cal_opt,
6823 int inc,
6824 int iccocg,
6825 int imasac,
6826 cs_real_t *restrict pvar,
6827 const cs_real_t *restrict pvara,
6828 const cs_real_t coefap[],
6829 const cs_real_t coefbp[],
6830 const cs_real_t cofafp[],
6831 const cs_real_t cofbfp[],
6832 const cs_real_t i_massflux[],
6833 const cs_real_t b_massflux[],
6834 const cs_real_t i_visc[],
6835 const cs_real_t b_visc[],
6836 const cs_real_t xcpp[],
6837 cs_real_t *restrict rhs)
6838 {
6839 const int iconvp = var_cal_opt.iconv ;
6840 const int idiffp = var_cal_opt.idiff ;
6841 const int nswrgp = var_cal_opt.nswrgr;
6842 const int imrgra = var_cal_opt.imrgra;
6843 const int imligp = var_cal_opt.imligr;
6844 const int ircflp = var_cal_opt.ircflu;
6845 const int ischcp = var_cal_opt.ischcv;
6846 const int isstpp = var_cal_opt.isstpc;
6847 const int iwarnp = var_cal_opt.verbosity;
6848 const int icoupl = var_cal_opt.icoupl;
6849 int limiter_choice = -1;
6850 const double blencp = var_cal_opt.blencv;
6851 const double blend_st = var_cal_opt.blend_st;
6852 const double epsrgp = var_cal_opt.epsrgr;
6853 const double climgp = var_cal_opt.climgr;
6854 const double relaxp = var_cal_opt.relaxv;
6855 const double thetap = var_cal_opt.thetav;
6856
6857 const cs_mesh_t *m = cs_glob_mesh;
6858 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
6859
6860 const cs_lnum_t n_cells = m->n_cells;
6861 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
6862 const int n_i_groups = m->i_face_numbering->n_groups;
6863 const int n_i_threads = m->i_face_numbering->n_threads;
6864 const int n_b_groups = m->b_face_numbering->n_groups;
6865 const int n_b_threads = m->b_face_numbering->n_threads;
6866 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
6867 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
6868
6869 const cs_lnum_2_t *restrict i_face_cells
6870 = (const cs_lnum_2_t *restrict)m->i_face_cells;
6871 const cs_lnum_t *restrict b_face_cells
6872 = (const cs_lnum_t *restrict)m->b_face_cells;
6873 const cs_real_t *restrict weight = fvq->weight;
6874 const cs_real_t *restrict i_dist = fvq->i_dist;
6875 const cs_real_t *restrict i_face_surf = fvq->i_face_surf;
6876 const cs_real_t *restrict cell_vol = fvq->cell_vol;
6877 const cs_real_3_t *restrict cell_cen
6878 = (const cs_real_3_t *restrict)fvq->cell_cen;
6879 const cs_real_3_t *restrict i_face_normal
6880 = (const cs_real_3_t *restrict)fvq->i_face_normal;
6881 const cs_real_3_t *restrict i_face_cog
6882 = (const cs_real_3_t *restrict)fvq->i_face_cog;
6883 const cs_real_3_t *restrict diipf
6884 = (const cs_real_3_t *restrict)fvq->diipf;
6885 const cs_real_3_t *restrict djjpf
6886 = (const cs_real_3_t *restrict)fvq->djjpf;
6887 const cs_real_3_t *restrict diipb
6888 = (const cs_real_3_t *restrict)fvq->diipb;
6889
6890 const int *bc_type = cs_glob_bc_type;
6891
6892 /* Local variables */
6893
6894 char var_name[64];
6895
6896 cs_gnum_t n_upwind;
6897 int iupwin;
6898 int w_stride = 1;
6899
6900 bool recompute_cocg = (iccocg) ? true : false;
6901
6902 cs_real_3_t *grad;
6903 cs_real_3_t *gradup = NULL;
6904 cs_real_3_t *gradst = NULL;
6905 cs_field_t *f = NULL;
6906
6907 cs_real_t *local_min = NULL;
6908 cs_real_t *local_max = NULL;
6909
6910 cs_real_t *cv_limiter = NULL;
6911 cs_real_t *df_limiter = NULL;
6912
6913 cs_real_t *gweight = NULL;
6914
6915 cs_real_t *v_slope_test = cs_get_v_slope_test(f_id, var_cal_opt);
6916
6917 /* Internal coupling variables */
6918 cs_real_t *pvar_local = NULL;
6919 cs_real_t *pvar_distant = NULL;
6920 cs_real_t *df_limiter_local = NULL;
6921 const cs_lnum_t *faces_local = NULL, *faces_distant = NULL;
6922 cs_lnum_t n_local = 0, n_distant = 0;
6923 int coupling_id = -1;
6924 cs_internal_coupling_t *cpl = NULL;
6925
6926 /*==========================================================================*/
6927
6928 /* 1. Initialization */
6929
6930 /* Allocate work arrays */
6931 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
6932
6933 /* Choose gradient type */
6934
6935 cs_halo_type_t halo_type = CS_HALO_STANDARD;
6936 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
6937
6938 cs_gradient_type_by_imrgra(imrgra,
6939 &gradient_type,
6940 &halo_type);
6941
6942 /* Handle cases where only the previous values (already synchronized)
6943 or current values are provided */
6944
6945 if (pvar != NULL)
6946 cs_sync_scalar_halo(m, pvar);
6947 if (pvara == NULL)
6948 pvara = (const cs_real_t *restrict)pvar;
6949
6950 const cs_real_t *restrict _pvar = (pvar != NULL) ? pvar : pvara;
6951
6952 /* Slope limiters */
6953
6954 if (f_id != -1) {
6955 f = cs_field_by_id(f_id);
6956 /* Get option from the field */
6957 if (ischcp == 4) {
6958 const int key_limiter = cs_field_key_id("limiter_choice");
6959 limiter_choice = cs_field_get_key_int(f, key_limiter);
6960 BFT_MALLOC(local_max, n_cells_ext, cs_real_t);
6961 BFT_MALLOC(local_min, n_cells_ext, cs_real_t);
6962 cs_field_local_extrema_scalar(f_id,
6963 halo_type,
6964 local_max,
6965 local_min);
6966
6967 assert(limiter_choice < CS_NVD_VOF_HRIC); /* VOF scheme forbidden here */
6968 }
6969
6970 int cv_limiter_id =
6971 cs_field_get_key_int(f, cs_field_key_id("convection_limiter_id"));
6972 if (cv_limiter_id > -1)
6973 cv_limiter = cs_field_by_id(cv_limiter_id)->val;
6974
6975 int df_limiter_id =
6976 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
6977 if (df_limiter_id > -1)
6978 df_limiter = cs_field_by_id(df_limiter_id)->val;
6979
6980 snprintf(var_name, 63, "%s", f->name);
6981 }
6982 else
6983 strncpy(var_name, "[convection-diffusion, thermal]", 63);
6984 var_name[63] = '\0';
6985
6986 if (iwarnp >= 2) {
6987 if (ischcp == 1) {
6988 bft_printf
6989 (
6990 _(" %s: Convection in centered blending with %f percent of upwind\n"),
6991 var_name, (1.-blencp)*100.);
6992 } else {
6993 bft_printf
6994 (
6995 _(" %s: Convection in 2nd order blending with %f percent of upwind\n"),
6996 var_name, (1.-blencp)*100.);
6997 }
6998 }
6999
7000 iupwin = (blencp > 0.) ? 0 : 1;
7001
7002 if (icoupl > 0) {
7003 assert(f_id != -1);
7004 const int coupling_key_id = cs_field_key_id("coupling_entity");
7005 coupling_id = cs_field_get_key_int(f, coupling_key_id);
7006 cpl = cs_internal_coupling_by_id(coupling_id);
7007 cs_internal_coupling_coupled_faces(cpl,
7008 &n_local,
7009 &faces_local,
7010 &n_distant,
7011 &faces_distant);
7012 }
7013
7014 /* 2. Compute the balance with reconstruction technics */
7015
7016 /* Compute the gradient of the variable
7017
7018 The gradient (grad) is used in the flux reconstruction and the slope test.
7019 Thus we must compute it:
7020 - when we have diffusion and we reconstruct the fluxes,
7021 - when the convection scheme is SOLU,
7022 - when we have convection, we are not in pure upwind
7023 and we reconstruct the fluxes,
7024 - when we have convection, we are not in pure upwind
7025 and we have not shunted the slope test. */
7026
7027 if ( (idiffp != 0 && ircflp == 1)
7028 || ( iconvp != 0 && iupwin == 0
7029 && (ischcp == 0 || ircflp == 1 || isstpp == 0))) {
7030
7031 if (f_id != -1) {
7032 /* Get the calculation option from the field */
7033 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
7034 if (var_cal_opt.idiff > 0) {
7035 int key_id = cs_field_key_id("gradient_weighting_id");
7036 int diff_id = cs_field_get_key_int(f, key_id);
7037 if (diff_id > -1) {
7038 cs_field_t *weight_f = cs_field_by_id(diff_id);
7039 gweight = weight_f->val;
7040 w_stride = weight_f->dim;
7041 cs_field_synchronize(weight_f, halo_type);
7042 }
7043 }
7044 }
7045 }
7046
7047 cs_gradient_scalar_synced_input(var_name,
7048 gradient_type,
7049 halo_type,
7050 inc,
7051 recompute_cocg,
7052 nswrgp,
7053 0, /* hyd_p_flag */
7054 w_stride,
7055 iwarnp,
7056 imligp,
7057 epsrgp,
7058 climgp,
7059 NULL, /* f_ext exterior force */
7060 coefap,
7061 coefbp,
7062 _pvar,
7063 gweight, /* Weighted gradient */
7064 cpl, /* internal coupling */
7065 grad);
7066
7067 } else {
7068 # pragma omp parallel for
7069 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
7070 grad[cell_id][0] = 0.;
7071 grad[cell_id][1] = 0.;
7072 grad[cell_id][2] = 0.;
7073 }
7074 }
7075
7076 /* ======================================================================
7077 ---> Compute uncentered gradient gradpa for the slope test
7078 ======================================================================*/
7079
7080 /* 2.1 Compute the gradient for convective scheme (the slope test, limiter, SOLU, etc) */
7081
7082 /* Slope test gradient */
7083 if (iconvp > 0 && iupwin == 0 && isstpp == 0) {
7084
7085 BFT_MALLOC(gradst, n_cells_ext, cs_real_3_t);
7086
7087 # pragma omp parallel for
7088 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
7089 gradst[cell_id][0] = 0.;
7090 gradst[cell_id][1] = 0.;
7091 gradst[cell_id][2] = 0.;
7092 }
7093
7094 cs_slope_test_gradient(f_id,
7095 inc,
7096 halo_type,
7097 (const cs_real_3_t *)grad,
7098 gradst,
7099 _pvar,
7100 coefap,
7101 coefbp,
7102 i_massflux);
7103
7104 }
7105
7106 /* Pure SOLU scheme without using gradient_slope_test function
7107 or NVD/TVD limiters */
7108 if (iconvp > 0 && iupwin == 0 && (ischcp == 2 || ischcp == 4)) {
7109
7110 BFT_MALLOC(gradup, n_cells_ext, cs_real_3_t);
7111
7112 # pragma omp parallel for
7113 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
7114 gradup[cell_id][0] = 0.;
7115 gradup[cell_id][1] = 0.;
7116 gradup[cell_id][2] = 0.;
7117 }
7118
7119 cs_upwind_gradient(f_id,
7120 inc,
7121 halo_type,
7122 coefap,
7123 coefbp,
7124 i_massflux,
7125 b_massflux,
7126 _pvar,
7127 gradup);
7128
7129 }
7130
7131 /* ======================================================================
7132 ---> Contribution from interior faces
7133 ======================================================================*/
7134
7135 n_upwind = 0;
7136
7137 if (n_cells_ext > n_cells) {
7138 # pragma omp parallel for if(n_cells_ext - n_cells > CS_THR_MIN)
7139 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++)
7140 rhs[cell_id] = 0.;
7141 }
7142
7143 /* --> Pure upwind flux
7144 =====================*/
7145
7146 if (iupwin == 1) {
7147
7148 /* Steady */
7149 if (idtvar < 0) {
7150
7151 for (int g_id = 0; g_id < n_i_groups; g_id++) {
7152 # pragma omp parallel for reduction(+:n_upwind)
7153 for (int t_id = 0; t_id < n_i_threads; t_id++) {
7154 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
7155 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
7156 face_id++) {
7157
7158 cs_lnum_t ii = i_face_cells[face_id][0];
7159 cs_lnum_t jj = i_face_cells[face_id][1];
7160
7161 /* in parallel, face will be counted by one and only one rank */
7162 if (ii < n_cells) {
7163 n_upwind++;
7164 }
7165
7166 cs_real_2_t fluxij = {0.,0.};
7167
7168 cs_real_t pifri, pjfri, pifrj, pjfrj;
7169 cs_real_t pip, pjp, pipr, pjpr;
7170
7171 cs_real_t bldfrp = (cs_real_t) ircflp;
7172 /* Local limitation of the reconstruction */
7173 if (df_limiter != NULL && ircflp > 0)
7174 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
7175
7176 cs_i_cd_steady_upwind(bldfrp,
7177 relaxp,
7178 diipf[face_id],
7179 djjpf[face_id],
7180 grad[ii],
7181 grad[jj],
7182 _pvar[ii],
7183 _pvar[jj],
7184 pvara[ii],
7185 pvara[jj],
7186 &pifri,
7187 &pifrj,
7188 &pjfri,
7189 &pjfrj,
7190 &pip,
7191 &pjp,
7192 &pipr,
7193 &pjpr);
7194
7195 cs_i_conv_flux(iconvp,
7196 1.,
7197 1,
7198 _pvar[ii],
7199 _pvar[jj],
7200 pifri,
7201 pifrj,
7202 pjfri,
7203 pjfrj,
7204 i_massflux[face_id],
7205 xcpp[ii],
7206 xcpp[jj],
7207 fluxij);
7208
7209 cs_i_diff_flux(idiffp,
7210 1.,
7211 pip,
7212 pjp,
7213 pipr,
7214 pjpr,
7215 i_visc[face_id],
7216 fluxij);
7217
7218 rhs[ii] -= fluxij[0];
7219 rhs[jj] += fluxij[1];
7220
7221 }
7222 }
7223 }
7224
7225 /* Unsteady */
7226 } else {
7227
7228 for (int g_id = 0; g_id < n_i_groups; g_id++) {
7229 # pragma omp parallel for reduction(+:n_upwind)
7230 for (int t_id = 0; t_id < n_i_threads; t_id++) {
7231 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
7232 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
7233 face_id++) {
7234
7235 cs_lnum_t ii = i_face_cells[face_id][0];
7236 cs_lnum_t jj = i_face_cells[face_id][1];
7237
7238 /* in parallel, face will be counted by one and only one rank */
7239 if (ii < n_cells) {
7240 n_upwind++;
7241 }
7242
7243 cs_real_2_t fluxij = {0.,0.};
7244
7245 cs_real_t pif, pjf;
7246 cs_real_t pip, pjp;
7247
7248 cs_real_t bldfrp = (cs_real_t) ircflp;
7249 /* Local limitation of the reconstruction */
7250 if (df_limiter != NULL && ircflp > 0)
7251 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
7252
7253 cs_i_cd_unsteady_upwind(bldfrp,
7254 diipf[face_id],
7255 djjpf[face_id],
7256 grad[ii],
7257 grad[jj],
7258 _pvar[ii],
7259 _pvar[jj],
7260 &pif,
7261 &pjf,
7262 &pip,
7263 &pjp);
7264
7265 cs_i_conv_flux(iconvp,
7266 thetap,
7267 imasac,
7268 _pvar[ii],
7269 _pvar[jj],
7270 pif,
7271 pif, /* no relaxation */
7272 pjf,
7273 pjf, /* no relaxation */
7274 i_massflux[face_id],
7275 xcpp[ii],
7276 xcpp[jj],
7277 fluxij);
7278
7279 cs_i_diff_flux(idiffp,
7280 thetap,
7281 pip,
7282 pjp,
7283 pip,/* no relaxation */
7284 pjp,/* no relaxation */
7285 i_visc[face_id],
7286 fluxij);
7287
7288 rhs[ii] -= fluxij[0];
7289 rhs[jj] += fluxij[1];
7290
7291 }
7292 }
7293 }
7294
7295 }
7296
7297 /* --> Flux with no slope test or Min/Max Beta limiter
7298 ====================================================*/
7299
7300 } else if (isstpp == 1 || isstpp == 2) {
7301
7302 if (ischcp < 0 || ischcp > 2) {
7303 bft_error(__FILE__, __LINE__, 0,
7304 _("invalid value of ischcv"));
7305 }
7306
7307 /* Steady */
7308 if (idtvar < 0) {
7309
7310 for (int g_id = 0; g_id < n_i_groups; g_id++) {
7311 # pragma omp parallel for
7312 for (int t_id = 0; t_id < n_i_threads; t_id++) {
7313 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
7314 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
7315 face_id++) {
7316
7317 cs_lnum_t ii = i_face_cells[face_id][0];
7318 cs_lnum_t jj = i_face_cells[face_id][1];
7319
7320 cs_real_2_t fluxij = {0.,0.};
7321
7322 cs_real_t pifri, pjfri, pifrj, pjfrj;
7323 cs_real_t pip, pjp, pipr, pjpr;
7324
7325 cs_real_t bldfrp = (cs_real_t) ircflp;
7326 /* Local limitation of the reconstruction */
7327 if (df_limiter != NULL && ircflp > 0)
7328 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
7329
7330 cs_i_cd_steady(bldfrp,
7331 ischcp,
7332 relaxp,
7333 blencp,
7334 weight[face_id],
7335 cell_cen[ii],
7336 cell_cen[jj],
7337 i_face_cog[face_id],
7338 diipf[face_id],
7339 djjpf[face_id],
7340 grad[ii],
7341 grad[jj],
7342 gradup[ii],
7343 gradup[jj],
7344 _pvar[ii],
7345 _pvar[jj],
7346 pvara[ii],
7347 pvara[jj],
7348 &pifri,
7349 &pifrj,
7350 &pjfri,
7351 &pjfrj,
7352 &pip,
7353 &pjp,
7354 &pipr,
7355 &pjpr);
7356
7357 cs_i_conv_flux(iconvp,
7358 1.,
7359 1,
7360 _pvar[ii],
7361 _pvar[jj],
7362 pifri,
7363 pifrj,
7364 pjfri,
7365 pjfrj,
7366 i_massflux[face_id],
7367 xcpp[ii],
7368 xcpp[jj],
7369 fluxij);
7370
7371 cs_i_diff_flux(idiffp,
7372 1.,
7373 pip,
7374 pjp,
7375 pipr,
7376 pjpr,
7377 i_visc[face_id],
7378 fluxij);
7379
7380 rhs[ii] -= fluxij[0];
7381 rhs[jj] += fluxij[1];
7382
7383 }
7384 }
7385 }
7386
7387 /* Unsteady */
7388 } else {
7389
7390 for (int g_id = 0; g_id < n_i_groups; g_id++) {
7391 # pragma omp parallel for
7392 for (int t_id = 0; t_id < n_i_threads; t_id++) {
7393 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
7394 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
7395 face_id++) {
7396
7397 cs_lnum_t ii = i_face_cells[face_id][0];
7398 cs_lnum_t jj = i_face_cells[face_id][1];
7399
7400 cs_real_t beta = blencp;
7401
7402 cs_real_t pif, pjf;
7403 cs_real_t pip, pjp;
7404
7405 /* Beta blending coefficient ensuring the positivity of the scalar */
7406 if (isstpp == 2) {
7407 beta = CS_MAX(CS_MIN(cv_limiter[ii], cv_limiter[jj]), 0.);
7408 }
7409
7410 cs_real_2_t fluxij = {0.,0.};
7411
7412 cs_real_t bldfrp = (cs_real_t) ircflp;
7413 /* Local limitation of the reconstruction */
7414 if (df_limiter != NULL && ircflp > 0)
7415 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
7416
7417 cs_real_t hybrid_coef_ii, hybrid_coef_jj;
7418 if (ischcp == 3) {
7419 hybrid_coef_ii = CS_F_(hybrid_blend)->val[ii];
7420 hybrid_coef_jj = CS_F_(hybrid_blend)->val[jj];
7421
7422 cs_i_cd_unsteady(bldfrp,
7423 ischcp,
7424 beta,
7425 weight[face_id],
7426 cell_cen[ii],
7427 cell_cen[jj],
7428 i_face_cog[face_id],
7429 hybrid_coef_ii,
7430 hybrid_coef_jj,
7431 diipf[face_id],
7432 djjpf[face_id],
7433 grad[ii],
7434 grad[jj],
7435 gradup[ii],
7436 gradup[jj],
7437 _pvar[ii],
7438 _pvar[jj],
7439 &pif,
7440 &pjf,
7441 &pip,
7442 &pjp);
7443
7444 cs_i_conv_flux(iconvp,
7445 thetap,
7446 imasac,
7447 _pvar[ii],
7448 _pvar[jj],
7449 pif,
7450 pif, /* no relaxation */
7451 pjf,
7452 pjf, /* no relaxation */
7453 i_massflux[face_id],
7454 xcpp[ii],
7455 xcpp[jj],
7456 fluxij);
7457 } else if (ischcp == 4) {
7458 /* NVD/TVD family of high accuracy schemes */
7459
7460 cs_lnum_t ic, id;
7461
7462 /* Determine central and downwind sides w.r.t. current face */
7463 cs_central_downwind_cells(ii,
7464 jj,
7465 i_massflux[face_id],
7466 &ic, /* central cell id */
7467 &id); /* downwind cell id */
7468
7469 cs_i_cd_unsteady_nvd(limiter_choice,
7470 beta,
7471 cell_cen[ic],
7472 cell_cen[id],
7473 i_face_normal[face_id],
7474 i_face_cog[face_id],
7475 grad[ic],
7476 _pvar[ic],
7477 _pvar[id],
7478 local_max[ic],
7479 local_min[ic],
7480 -1., /* courant */
7481 &pif,
7482 &pjf);
7483
7484 cs_i_conv_flux(iconvp,
7485 thetap,
7486 imasac,
7487 _pvar[ii],
7488 _pvar[jj],
7489 pif,
7490 pif, /* no relaxation */
7491 pjf,
7492 pjf, /* no relaxation */
7493 i_massflux[face_id],
7494 xcpp[ii],
7495 xcpp[jj],
7496 fluxij);
7497
7498
7499 /* Compute required quantities for diffusive flux */
7500 cs_real_t recoi, recoj;
7501
7502 cs_i_compute_quantities(bldfrp,
7503 diipf[face_id],
7504 djjpf[face_id],
7505 grad[ii],
7506 grad[jj],
7507 _pvar[ii],
7508 _pvar[jj],
7509 &recoi,
7510 &recoj,
7511 &pip,
7512 &pjp);
7513
7514 } else {
7515 hybrid_coef_ii = 0.;
7516 hybrid_coef_jj = 0.;
7517
7518 cs_i_cd_unsteady(bldfrp,
7519 ischcp,
7520 beta,
7521 weight[face_id],
7522 cell_cen[ii],
7523 cell_cen[jj],
7524 i_face_cog[face_id],
7525 hybrid_coef_ii,
7526 hybrid_coef_jj,
7527 diipf[face_id],
7528 djjpf[face_id],
7529 grad[ii],
7530 grad[jj],
7531 gradup[ii],
7532 gradup[jj],
7533 _pvar[ii],
7534 _pvar[jj],
7535 &pif,
7536 &pjf,
7537 &pip,
7538 &pjp);
7539
7540 cs_i_conv_flux(iconvp,
7541 thetap,
7542 imasac,
7543 _pvar[ii],
7544 _pvar[jj],
7545 pif,
7546 pif, /* no relaxation */
7547 pjf,
7548 pjf, /* no relaxation */
7549 i_massflux[face_id],
7550 xcpp[ii],
7551 xcpp[jj],
7552 fluxij);
7553
7554 }
7555
7556 cs_i_diff_flux(idiffp,
7557 thetap,
7558 pip,
7559 pjp,
7560 pip, /* no relaxation */
7561 pjp, /* no relaxation */
7562 i_visc[face_id],
7563 fluxij);
7564
7565 rhs[ii] -= fluxij[0];
7566 rhs[jj] += fluxij[1];
7567
7568 }
7569 }
7570 }
7571
7572 }
7573
7574 /* --> Flux with slope test
7575 ============================================*/
7576
7577 } else {
7578
7579 if (ischcp < 0 || ischcp > 2) {
7580 bft_error(__FILE__, __LINE__, 0,
7581 _("invalid value of ischcv"));
7582 }
7583 if (isstpp != 0) {
7584 bft_error(__FILE__, __LINE__, 0,
7585 _("invalid value of isstpc"));
7586 }
7587
7588 /* Steady */
7589 if (idtvar < 0) {
7590
7591 for (int g_id = 0; g_id < n_i_groups; g_id++) {
7592 # pragma omp parallel for reduction(+:n_upwind)
7593 for (int t_id = 0; t_id < n_i_threads; t_id++) {
7594 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
7595 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
7596 face_id++) {
7597
7598 cs_lnum_t ii = i_face_cells[face_id][0];
7599 cs_lnum_t jj = i_face_cells[face_id][1];
7600
7601 cs_real_2_t fluxij = {0.,0.};
7602
7603 cs_real_t pifri, pjfri, pifrj, pjfrj;
7604 cs_real_t pip, pjp, pipr, pjpr;
7605
7606 bool upwind_switch = false;
7607
7608 cs_real_t bldfrp = (cs_real_t) ircflp;
7609 /* Local limitation of the reconstruction */
7610 if (df_limiter != NULL && ircflp > 0)
7611 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
7612
7613 cs_i_cd_steady_slope_test(&upwind_switch,
7614 iconvp,
7615 bldfrp,
7616 ischcp,
7617 relaxp,
7618 blencp,
7619 blend_st,
7620 weight[face_id],
7621 i_dist[face_id],
7622 i_face_surf[face_id],
7623 cell_cen[ii],
7624 cell_cen[jj],
7625 i_face_normal[face_id],
7626 i_face_cog[face_id],
7627 diipf[face_id],
7628 djjpf[face_id],
7629 i_massflux[face_id],
7630 grad[ii],
7631 grad[jj],
7632 gradup[ii],
7633 gradup[jj],
7634 gradst[ii],
7635 gradst[jj],
7636 _pvar[ii],
7637 _pvar[jj],
7638 pvara[ii],
7639 pvara[jj],
7640 &pifri,
7641 &pifrj,
7642 &pjfri,
7643 &pjfrj,
7644 &pip,
7645 &pjp,
7646 &pipr,
7647 &pjpr);
7648
7649 cs_i_conv_flux(iconvp,
7650 1.,
7651 1,
7652 _pvar[ii],
7653 _pvar[jj],
7654 pifri,
7655 pifrj,
7656 pjfri,
7657 pjfrj,
7658 i_massflux[face_id],
7659 xcpp[ii],
7660 xcpp[jj],
7661 fluxij);
7662
7663 cs_i_diff_flux(idiffp,
7664 1.,
7665 pip,
7666 pjp,
7667 pipr,
7668 pjpr,
7669 i_visc[face_id],
7670 fluxij);
7671
7672 if (upwind_switch) {
7673
7674 /* in parallel, face will be counted by one and only one rank */
7675 if (ii < n_cells)
7676 n_upwind++;
7677 if (v_slope_test != NULL) {
7678 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
7679 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
7680 }
7681
7682 }
7683
7684 rhs[ii] -= fluxij[0];
7685 rhs[jj] += fluxij[1];
7686
7687 }
7688 }
7689 }
7690
7691 /* Unsteady */
7692 } else {
7693
7694 for (int g_id = 0; g_id < n_i_groups; g_id++) {
7695 # pragma omp parallel for reduction(+:n_upwind)
7696 for (int t_id = 0; t_id < n_i_threads; t_id++) {
7697 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
7698 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
7699 face_id++) {
7700
7701 cs_lnum_t ii = i_face_cells[face_id][0];
7702 cs_lnum_t jj = i_face_cells[face_id][1];
7703
7704 cs_real_2_t fluxij = {0.,0.};
7705
7706 bool upwind_switch = false;
7707
7708 cs_real_t pif, pjf;
7709 cs_real_t pip, pjp;
7710
7711 cs_real_t bldfrp = (cs_real_t) ircflp;
7712 /* Local limitation of the reconstruction */
7713 if (df_limiter != NULL && ircflp > 0)
7714 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
7715
7716 cs_i_cd_unsteady_slope_test(&upwind_switch,
7717 iconvp,
7718 bldfrp,
7719 ischcp,
7720 blencp,
7721 blend_st,
7722 weight[face_id],
7723 i_dist[face_id],
7724 i_face_surf[face_id],
7725 cell_cen[ii],
7726 cell_cen[jj],
7727 i_face_normal[face_id],
7728 i_face_cog[face_id],
7729 diipf[face_id],
7730 djjpf[face_id],
7731 i_massflux[face_id],
7732 grad[ii],
7733 grad[jj],
7734 gradup[ii],
7735 gradup[jj],
7736 gradst[ii],
7737 gradst[jj],
7738 _pvar[ii],
7739 _pvar[jj],
7740 &pif,
7741 &pjf,
7742 &pip,
7743 &pjp);
7744
7745 cs_i_conv_flux(iconvp,
7746 thetap,
7747 imasac,
7748 _pvar[ii],
7749 _pvar[jj],
7750 pif,
7751 pif, /* no relaxation */
7752 pjf,
7753 pjf, /* no relaxation */
7754 i_massflux[face_id],
7755 xcpp[ii],
7756 xcpp[jj],
7757 fluxij);
7758
7759 cs_i_diff_flux(idiffp,
7760 thetap,
7761 pip,
7762 pjp,
7763 pip, /* no relaxation */
7764 pjp, /* no relaxation */
7765 i_visc[face_id],
7766 fluxij);
7767
7768 if (upwind_switch) {
7769
7770 /* in parallel, face will be counted by one and only one rank */
7771 if (ii < n_cells)
7772 n_upwind++;
7773 if (v_slope_test != NULL) {
7774 v_slope_test[ii] += fabs(i_massflux[face_id]) / cell_vol[ii];
7775 v_slope_test[jj] += fabs(i_massflux[face_id]) / cell_vol[jj];
7776 }
7777
7778 }
7779
7780 rhs[ii] -= fluxij[0];
7781 rhs[jj] += fluxij[1];
7782
7783 }
7784 }
7785 }
7786
7787 } /* idtvar */
7788
7789 } /* iupwin */
7790
7791
7792 if (iwarnp >= 2 && iconvp == 1) {
7793
7794 /* Sum number of clippings */
7795 cs_parall_counter(&n_upwind, 1);
7796
7797 bft_printf(_(" %s: %llu Faces with upwind on %llu interior faces\n"),
7798 var_name, (unsigned long long)n_upwind,
7799 (unsigned long long)m->n_g_i_c_faces);
7800 }
7801
7802 /* ======================================================================
7803 ---> Contribution from boundary faces
7804 ======================================================================*/
7805
7806 /* Steady */
7807 if (idtvar < 0) {
7808
7809 for (int g_id = 0; g_id < n_b_groups; g_id++) {
7810 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
7811 for (int t_id = 0; t_id < n_b_threads; t_id++) {
7812 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
7813 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
7814 face_id++) {
7815
7816 cs_lnum_t ii = b_face_cells[face_id];
7817
7818 cs_real_t fluxi = 0.;
7819 cs_real_t pir, pipr;
7820
7821 cs_real_t bldfrp = (cs_real_t) ircflp;
7822 /* Local limitation of the reconstruction */
7823 if (df_limiter != NULL && ircflp > 0)
7824 bldfrp = CS_MAX(df_limiter[ii], 0.);
7825
7826 cs_b_cd_steady(bldfrp,
7827 relaxp,
7828 diipb[face_id],
7829 grad[ii],
7830 _pvar[ii],
7831 pvara[ii],
7832 &pir,
7833 &pipr);
7834
7835 cs_b_upwind_flux(iconvp,
7836 1.,
7837 1,
7838 inc,
7839 bc_type[face_id],
7840 _pvar[ii],
7841 pir,
7842 pipr,
7843 coefap[face_id],
7844 coefbp[face_id],
7845 b_massflux[face_id],
7846 xcpp[ii],
7847 &fluxi);
7848
7849 cs_b_diff_flux(idiffp,
7850 1., /* thetap */
7851 inc,
7852 pipr,
7853 cofafp[face_id],
7854 cofbfp[face_id],
7855 b_visc[face_id],
7856 &fluxi);
7857
7858 rhs[ii] -= fluxi;
7859
7860 }
7861 }
7862 }
7863
7864 /* The thermal is internal_coupled and an implicit contribution
7865 * is required */
7866 if (icoupl > 0) {
7867 /* Prepare data for sending */
7868 BFT_MALLOC(pvar_distant, n_distant, cs_real_t);
7869
7870 for (cs_lnum_t ii = 0; ii < n_distant; ii++) {
7871 cs_lnum_t face_id = faces_distant[ii];
7872 cs_lnum_t jj = b_face_cells[face_id];
7873 cs_real_t pip, pipr;
7874
7875 cs_real_t bldfrp = (cs_real_t) ircflp;
7876 /* Local limitation of the reconstruction */
7877 /* Note: to be treated exactly as a internal face, should be a bending
7878 * between the two cells... */
7879 if (df_limiter != NULL && ircflp > 0)
7880 bldfrp = CS_MAX(df_limiter[jj], 0.);
7881
7882 cs_b_cd_steady(bldfrp,
7883 relaxp,
7884 diipb[face_id],
7885 grad[jj],
7886 _pvar[jj],
7887 pvara[jj],
7888 &pip,
7889 &pipr);
7890 pvar_distant[ii] = pipr;
7891 }
7892
7893 /* Receive data */
7894 BFT_MALLOC(pvar_local, n_local, cs_real_t);
7895 cs_internal_coupling_exchange_var(cpl,
7896 1, /* Dimension */
7897 pvar_distant,
7898 pvar_local);
7899 if (df_limiter != NULL) {
7900 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
7901 cs_internal_coupling_exchange_var(cpl,
7902 1, /* Dimension */
7903 df_limiter,
7904 df_limiter_local);
7905 }
7906
7907 /* Flux contribution */
7908 assert(f_id!=-1); // Otherwise the "f" can't be used
7909 cs_real_t *hintp = f->bc_coeffs->hint;
7910 cs_real_t *hextp = f->bc_coeffs->hext;
7911 for (cs_lnum_t ii = 0; ii < n_local; ii++) {
7912 cs_lnum_t face_id = faces_local[ii];
7913 cs_lnum_t jj = b_face_cells[face_id];
7914 cs_real_t pip, pipr, pjpr;
7915 cs_real_t fluxi = 0.;
7916
7917 cs_real_t bldfrp = (cs_real_t) ircflp;
7918 /* Local limitation of the reconstruction */
7919 if (df_limiter != NULL && ircflp > 0)
7920 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
7921
7922 cs_b_cd_steady(bldfrp,
7923 relaxp,
7924 diipb[face_id],
7925 grad[jj],
7926 _pvar[jj],
7927 pvara[jj],
7928 &pip,
7929 &pipr);
7930
7931 pjpr = pvar_local[ii];
7932
7933 cs_real_t hint = hintp[face_id];
7934 cs_real_t hext = hextp[face_id];
7935 cs_real_t heq = _calc_heq(hint, hext);
7936
7937 cs_b_diff_flux_coupling(idiffp,
7938 pipr,
7939 pjpr,
7940 heq,
7941 &fluxi);
7942
7943 rhs[jj] -= thetap * fluxi;
7944 }
7945
7946 BFT_FREE(pvar_local);
7947 /* Sending structures are no longer needed */
7948 BFT_FREE(pvar_distant);
7949 if (df_limiter != NULL)
7950 BFT_FREE(df_limiter_local);
7951
7952 }
7953
7954 /* Unsteady */
7955 } else {
7956
7957 for (int g_id = 0; g_id < n_b_groups; g_id++) {
7958 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
7959 for (int t_id = 0; t_id < n_b_threads; t_id++) {
7960 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
7961 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
7962 face_id++) {
7963
7964 cs_lnum_t ii = b_face_cells[face_id];
7965
7966 cs_real_t fluxi = 0.;
7967 cs_real_t pip;
7968
7969 cs_real_t bldfrp = (cs_real_t) ircflp;
7970 /* Local limitation of the reconstruction */
7971 if (df_limiter != NULL && ircflp > 0)
7972 bldfrp = CS_MAX(df_limiter[ii], 0.);
7973
7974 cs_b_cd_unsteady(bldfrp,
7975 diipb[face_id],
7976 grad[ii],
7977 _pvar[ii],
7978 &pip);
7979
7980 cs_b_upwind_flux(iconvp,
7981 thetap,
7982 imasac,
7983 inc,
7984 bc_type[face_id],
7985 _pvar[ii],
7986 _pvar[ii], /* no relaxation */
7987 pip,
7988 coefap[face_id],
7989 coefbp[face_id],
7990 b_massflux[face_id],
7991 xcpp[ii],
7992 &fluxi);
7993
7994 cs_b_diff_flux(idiffp,
7995 thetap,
7996 inc,
7997 pip,
7998 cofafp[face_id],
7999 cofbfp[face_id],
8000 b_visc[face_id],
8001 &fluxi);
8002
8003 rhs[ii] -= fluxi;
8004
8005 }
8006 }
8007 }
8008
8009 /* The thermal is internal_coupled and an implicit contribution
8010 * is required */
8011 if (icoupl > 0) {
8012 /* Prepare data for sending */
8013 BFT_MALLOC(pvar_distant, n_distant, cs_real_t);
8014
8015 for (cs_lnum_t ii = 0; ii < n_distant; ii++) {
8016 cs_lnum_t face_id = faces_distant[ii];
8017 cs_lnum_t jj = b_face_cells[face_id];
8018 cs_real_t pip;
8019
8020 cs_real_t bldfrp = (cs_real_t) ircflp;
8021 /* Local limitation of the reconstruction */
8022 /* Note: to be treated exactly as a internal face, should be a bending
8023 * between the two cells... */
8024 if (df_limiter != NULL && ircflp > 0)
8025 bldfrp = CS_MAX(df_limiter[jj], 0.);
8026
8027 cs_b_cd_unsteady(bldfrp,
8028 diipb[face_id],
8029 grad[jj],
8030 _pvar[jj],
8031 &pip);
8032 pvar_distant[ii] = pip;
8033 }
8034
8035 /* Receive data */
8036 BFT_MALLOC(pvar_local, n_local, cs_real_t);
8037 cs_internal_coupling_exchange_var(cpl,
8038 1, /* Dimension */
8039 pvar_distant,
8040 pvar_local);
8041 if (df_limiter != NULL) {
8042 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
8043 cs_internal_coupling_exchange_var(cpl,
8044 1, /* Dimension */
8045 df_limiter,
8046 df_limiter_local);
8047 }
8048
8049 /* Flux contribution */
8050 assert(f_id!=-1); // Otherwise the "f" can't be used
8051 cs_real_t *hintp = f->bc_coeffs->hint;
8052 cs_real_t *hextp = f->bc_coeffs->hext;
8053 for (cs_lnum_t ii = 0; ii < n_local; ii++) {
8054 cs_lnum_t face_id = faces_local[ii];
8055 cs_lnum_t jj = b_face_cells[face_id];
8056 cs_real_t pip, pjp;
8057 cs_real_t fluxi = 0.;
8058
8059 cs_real_t bldfrp = (cs_real_t) ircflp;
8060 /* Local limitation of the reconstruction */
8061 if (df_limiter != NULL && ircflp > 0)
8062 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
8063
8064 cs_b_cd_unsteady(bldfrp,
8065 diipb[face_id],
8066 grad[jj],
8067 _pvar[jj],
8068 &pip);
8069
8070 pjp = pvar_local[ii];
8071
8072 cs_real_t hint = hintp[face_id];
8073 cs_real_t hext = hextp[face_id];
8074 cs_real_t heq = _calc_heq(hint, hext);
8075
8076 cs_b_diff_flux_coupling(idiffp,
8077 pip,
8078 pjp,
8079 heq,
8080 &fluxi);
8081
8082 rhs[jj] -= thetap * fluxi;
8083 }
8084
8085 BFT_FREE(pvar_local);
8086 /* Sending structures are no longer needed */
8087 BFT_FREE(pvar_distant);
8088 if (df_limiter != NULL)
8089 BFT_FREE(df_limiter_local);
8090
8091 }
8092
8093 }
8094
8095 /* Free memory */
8096 BFT_FREE(grad);
8097 BFT_FREE(gradup);
8098 BFT_FREE(gradst);
8099 BFT_FREE(local_max);
8100 BFT_FREE(local_min);
8101 }
8102
8103 /*----------------------------------------------------------------------------*/
8104 /*!
8105 * \brief Add the explicit part of the diffusion terms with a symmetric tensor
8106 * diffusivity for a transport equation of a scalar field \f$ \varia \f$.
8107 *
8108 * More precisely, the right hand side \f$ Rhs \f$ is updated as
8109 * follows:
8110 * \f[
8111 * Rhs = Rhs - \sum_{\fij \in \Facei{\celli}} \left(
8112 * - \tens{\mu}_\fij \gradv_\fij \varia \cdot \vect{S}_\ij \right)
8113 * \f]
8114 *
8115 * Warning:
8116 * - \f$ Rhs \f$ has already been initialized before
8117 * calling cs_anisotropic_diffusion_scalar!
8118 * - mind the sign minus
8119 *
8120 * \param[in] idtvar indicator of the temporal scheme
8121 * \param[in] f_id index of the current variable
8122 * \param[in] var_cal_opt variable calculation options
8123 * \param[in] inc indicator
8124 * - 0 when solving an increment
8125 * - 1 otherwise
8126 * \param[in] iccocg indicator
8127 * - 1 re-compute cocg matrix
8128 (for iterativ gradients)
8129 * - 0 otherwise
8130 * \param[in] pvar solved variable (current time step)
8131 * \param[in] pvara solved variable (previous time step)
8132 * \param[in] coefap boundary condition array for the variable
8133 * (explicit part)
8134 * \param[in] coefbp boundary condition array for the variable
8135 * (implicit part)
8136 * \param[in] cofafp boundary condition array for the diffusion
8137 * of the variable (explicit part)
8138 * \param[in] cofbfp boundary condition array for the diffusion
8139 * of the variable (implicit part)
8140 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
8141 * at interior faces for the r.h.s.
8142 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
8143 * at border faces for the r.h.s.
8144 * \param[in] viscel symmetric cell tensor \f$ \tens{\mu}_\celli \f$
8145 * \param[in] weighf internal face weight between cells i j in case
8146 * of tensor diffusion
8147 * \param[in] weighb boundary face weight for cells i in case
8148 * of tensor diffusion
8149 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
8150 */
8151 /*----------------------------------------------------------------------------*/
8152
8153 void
cs_anisotropic_diffusion_scalar(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int inc,int iccocg,cs_real_t * restrict pvar,const cs_real_t * restrict pvara,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_6_t * restrict viscel,const cs_real_2_t weighf[],const cs_real_t weighb[],cs_real_t * restrict rhs)8154 cs_anisotropic_diffusion_scalar(int idtvar,
8155 int f_id,
8156 const cs_var_cal_opt_t var_cal_opt,
8157 int inc,
8158 int iccocg,
8159 cs_real_t *restrict pvar,
8160 const cs_real_t *restrict pvara,
8161 const cs_real_t coefap[],
8162 const cs_real_t coefbp[],
8163 const cs_real_t cofafp[],
8164 const cs_real_t cofbfp[],
8165 const cs_real_t i_visc[],
8166 const cs_real_t b_visc[],
8167 cs_real_6_t *restrict viscel,
8168 const cs_real_2_t weighf[],
8169 const cs_real_t weighb[],
8170 cs_real_t *restrict rhs)
8171 {
8172 const int nswrgp = var_cal_opt.nswrgr;
8173 const int imrgra = var_cal_opt.imrgra;
8174 const int imligp = var_cal_opt.imligr;
8175 const int ircflp = var_cal_opt.ircflu;
8176 const int iwarnp = var_cal_opt.verbosity;
8177 const int icoupl = var_cal_opt.icoupl;
8178 const double epsrgp = var_cal_opt.epsrgr;
8179 const double climgp = var_cal_opt.climgr;
8180 const double relaxp = var_cal_opt.relaxv;
8181 const double thetap = var_cal_opt.thetav;
8182
8183 const cs_mesh_t *m = cs_glob_mesh;
8184 const cs_halo_t *halo = m->halo;
8185 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
8186
8187 const cs_lnum_t n_cells = m->n_cells;
8188 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
8189 const int n_i_groups = m->i_face_numbering->n_groups;
8190 const int n_i_threads = m->i_face_numbering->n_threads;
8191 const int n_b_groups = m->b_face_numbering->n_groups;
8192 const int n_b_threads = m->b_face_numbering->n_threads;
8193 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
8194 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
8195
8196 const cs_lnum_2_t *restrict i_face_cells
8197 = (const cs_lnum_2_t *restrict)m->i_face_cells;
8198 const cs_lnum_t *restrict b_face_cells
8199 = (const cs_lnum_t *restrict)m->b_face_cells;
8200 const cs_real_3_t *restrict cell_cen
8201 = (const cs_real_3_t *restrict)fvq->cell_cen;
8202 const cs_real_3_t *restrict i_face_normal
8203 = (const cs_real_3_t *restrict)fvq->i_face_normal;
8204 const cs_real_3_t *restrict b_face_normal
8205 = (const cs_real_3_t *restrict)fvq->b_face_normal;
8206 const cs_real_3_t *restrict i_face_cog
8207 = (const cs_real_3_t *restrict)fvq->i_face_cog;
8208 const cs_real_3_t *restrict b_face_cog
8209 = (const cs_real_3_t *restrict)fvq->b_face_cog;
8210
8211 /* Local variables */
8212
8213 cs_real_t *df_limiter = NULL;
8214
8215 char var_name[64];
8216
8217 int w_stride = 1;
8218
8219 bool recompute_cocg = (iccocg) ? true : false;
8220
8221 cs_real_6_t *viscce;
8222 cs_real_6_t *w2;
8223 cs_real_3_t *grad;
8224
8225 cs_field_t *f = NULL;
8226
8227 cs_real_t *gweight = NULL;
8228
8229 /* Internal coupling variables */
8230 cs_real_t *pvar_local = NULL;
8231 cs_real_3_t *grad_local = NULL;
8232 cs_real_t *df_limiter_local = NULL;
8233 cs_real_6_t *viscce_local = NULL;
8234 cs_real_t *weighb_local = NULL;
8235 const cs_lnum_t *faces_local = NULL;
8236 cs_lnum_t n_local = 0;
8237 int coupling_id = -1;
8238 cs_internal_coupling_t *cpl = NULL;
8239
8240 /* 1. Initialization */
8241
8242 viscce = NULL;
8243 w2 = NULL;
8244
8245 /* Allocate work arrays */
8246 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
8247
8248 /* Choose gradient type */
8249 cs_halo_type_t halo_type = CS_HALO_STANDARD;
8250 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
8251
8252 cs_gradient_type_by_imrgra(imrgra,
8253 &gradient_type,
8254 &halo_type);
8255
8256 /* Handle cases where only the previous values (already synchronized)
8257 or current values are provided */
8258
8259 if (pvar != NULL)
8260 cs_sync_scalar_halo(m, pvar);
8261 if (pvara == NULL)
8262 pvara = (const cs_real_t *restrict)pvar;
8263
8264 const cs_real_t *restrict _pvar = (pvar != NULL) ? pvar : pvara;
8265
8266 /* Logging */
8267
8268 if (f_id != -1) {
8269 f = cs_field_by_id(f_id);
8270
8271 int df_limiter_id =
8272 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
8273 if (df_limiter_id > -1)
8274 df_limiter = cs_field_by_id(df_limiter_id)->val;
8275
8276 snprintf(var_name, 63, "%s", f->name);
8277 }
8278 else
8279 strncpy(var_name, "[anisotropic diffusion, scalar]", 63);
8280 var_name[63] = '\0';
8281
8282 /* Porosity fields */
8283 cs_field_t *fporo = cs_field_by_name_try("porosity");
8284 cs_field_t *ftporo = cs_field_by_name_try("tensorial_porosity");
8285
8286 cs_real_t *porosi = NULL;
8287 cs_real_6_t *porosf = NULL;
8288
8289 if (cs_glob_porous_model == 1 || cs_glob_porous_model == 2) {
8290 porosi = fporo->val;
8291 if (ftporo != NULL) {
8292 porosf = (cs_real_6_t *)ftporo->val;
8293 }
8294 }
8295
8296 /* Without porosity */
8297 if (porosi == NULL) {
8298 viscce = viscel;
8299
8300 /* With porosity */
8301 } else if (porosi != NULL && porosf == NULL) {
8302 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
8303 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
8304 for (int isou = 0; isou < 6; isou++) {
8305 w2[cell_id][isou] = porosi[cell_id]*viscel[cell_id][isou];
8306 }
8307 }
8308 viscce = w2;
8309
8310 /* With tensorial porosity */
8311 } else if (porosi != NULL && porosf != NULL) {
8312 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
8313 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
8314 cs_math_sym_33_product(porosf[cell_id],
8315 viscel[cell_id],
8316 w2[cell_id]);
8317 }
8318 viscce = w2;
8319 }
8320
8321 /* ---> Periodicity and parallelism treatment of symmetric tensors */
8322 if (halo != NULL) {
8323 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)viscce, 6);
8324 if (m->n_init_perio > 0)
8325 cs_halo_perio_sync_var_sym_tens(halo, halo_type, (cs_real_t *)viscce);
8326 }
8327
8328 if (icoupl > 0) {
8329 assert(f_id != -1);
8330 const int coupling_key_id = cs_field_key_id("coupling_entity");
8331 coupling_id = cs_field_get_key_int(f, coupling_key_id);
8332 cpl = cs_internal_coupling_by_id(coupling_id);
8333 cs_internal_coupling_coupled_faces(cpl,
8334 &n_local,
8335 &faces_local,
8336 NULL,
8337 NULL);
8338 }
8339
8340 /* 2. Compute the diffusive part with reconstruction technics */
8341
8342 /* ======================================================================
8343 ---> Compute the gradient of the current variable if needed
8344 ======================================================================*/
8345
8346 if (ircflp == 1) {
8347
8348 if (f_id != -1) {
8349 /* Get the calculation option from the field */
8350 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
8351 if (var_cal_opt.idifft > 0) {
8352 int key_id = cs_field_key_id("gradient_weighting_id");
8353 int diff_id = cs_field_get_key_int(f, key_id);
8354 if (diff_id > -1) {
8355 cs_field_t *weight_f = cs_field_by_id(diff_id);
8356 gweight = weight_f->val;
8357 w_stride = weight_f->dim;
8358 cs_field_synchronize(weight_f, halo_type);
8359 }
8360 }
8361 }
8362 }
8363
8364 cs_gradient_scalar_synced_input(var_name,
8365 gradient_type,
8366 halo_type,
8367 inc,
8368 recompute_cocg,
8369 nswrgp,
8370 0, /* hyd_p_flag */
8371 w_stride,
8372 iwarnp,
8373 imligp,
8374 epsrgp,
8375 climgp,
8376 NULL, /* f_ext exterior force */
8377 coefap,
8378 coefbp,
8379 _pvar,
8380 gweight, /* Weighted gradient */
8381 cpl, /* internal coupling */
8382 grad);
8383
8384 } else {
8385 # pragma omp parallel for
8386 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
8387 grad[cell_id][0] = 0.;
8388 grad[cell_id][1] = 0.;
8389 grad[cell_id][2] = 0.;
8390 }
8391 }
8392
8393 /* ======================================================================
8394 ---> Contribution from interior faces
8395 ======================================================================*/
8396
8397 if (n_cells_ext > n_cells) {
8398 # pragma omp parallel for if(n_cells_ext - n_cells > CS_THR_MIN)
8399 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
8400 rhs[cell_id] = 0.;
8401 }
8402 }
8403
8404 /* Steady */
8405 if (idtvar < 0) {
8406
8407 for (int g_id = 0; g_id < n_i_groups; g_id++) {
8408 # pragma omp parallel for
8409 for (int t_id = 0; t_id < n_i_threads; t_id++) {
8410 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
8411 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
8412 face_id++) {
8413
8414 cs_lnum_t ii = i_face_cells[face_id][0];
8415 cs_lnum_t jj = i_face_cells[face_id][1];
8416
8417 cs_real_t pi = _pvar[ii];
8418 cs_real_t pj = _pvar[jj];
8419 cs_real_t pia = pvara[ii];
8420 cs_real_t pja = pvara[jj];
8421
8422 cs_real_t bldfrp = (cs_real_t) ircflp;
8423 /* Local limitation of the reconstruction */
8424 if (df_limiter != NULL && ircflp > 0)
8425 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
8426
8427 /* Recompute II" and JJ"
8428 ----------------------*/
8429
8430 cs_real_t visci[3][3], viscj[3][3];
8431
8432 visci[0][0] = viscce[ii][0];
8433 visci[1][1] = viscce[ii][1];
8434 visci[2][2] = viscce[ii][2];
8435 visci[1][0] = viscce[ii][3];
8436 visci[0][1] = viscce[ii][3];
8437 visci[2][1] = viscce[ii][4];
8438 visci[1][2] = viscce[ii][4];
8439 visci[2][0] = viscce[ii][5];
8440 visci[0][2] = viscce[ii][5];
8441
8442 /* IF.Ki.S / ||Ki.S||^2 */
8443 cs_real_t fikdvi = weighf[face_id][0];
8444
8445 cs_real_t diippf[3], djjppf[3];
8446
8447 /* II" = IF + FI" */
8448 for (int i = 0; i < 3; i++) {
8449 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
8450 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
8451 + visci[1][i]*i_face_normal[face_id][1]
8452 + visci[2][i]*i_face_normal[face_id][2] );
8453 }
8454
8455 viscj[0][0] = viscce[jj][0];
8456 viscj[1][1] = viscce[jj][1];
8457 viscj[2][2] = viscce[jj][2];
8458 viscj[1][0] = viscce[jj][3];
8459 viscj[0][1] = viscce[jj][3];
8460 viscj[2][1] = viscce[jj][4];
8461 viscj[1][2] = viscce[jj][4];
8462 viscj[2][0] = viscce[jj][5];
8463 viscj[0][2] = viscce[jj][5];
8464
8465 /* FJ.Kj.S / ||Kj.S||^2 */
8466 cs_real_t fjkdvi = weighf[face_id][1];
8467
8468 /* JJ" = JF + FJ" */
8469 for (int i = 0; i < 3; i++) {
8470 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
8471 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
8472 + viscj[1][i]*i_face_normal[face_id][1]
8473 + viscj[2][i]*i_face_normal[face_id][2] );
8474 }
8475
8476 /* p in I" and J" */
8477 cs_real_t pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
8478 + grad[ii][1]*diippf[1]
8479 + grad[ii][2]*diippf[2]);
8480 cs_real_t pjpp = pj + bldfrp*( grad[jj][0]*djjppf[0]
8481 + grad[jj][1]*djjppf[1]
8482 + grad[jj][2]*djjppf[2]);
8483
8484 cs_real_t pir = pi/relaxp - (1.-relaxp)/relaxp * pia;
8485 cs_real_t pjr = pj/relaxp - (1.-relaxp)/relaxp * pja;
8486
8487 /* pr in I" and J" */
8488 cs_real_t pippr = pir + bldfrp*( grad[ii][0]*diippf[0]
8489 + grad[ii][1]*diippf[1]
8490 + grad[ii][2]*diippf[2]);
8491 cs_real_t pjppr = pjr + bldfrp*( grad[jj][0]*djjppf[0]
8492 + grad[jj][1]*djjppf[1]
8493 + grad[jj][2]*djjppf[2]);
8494
8495
8496 cs_real_t fluxi = i_visc[face_id]*(pippr - pjpp);
8497 cs_real_t fluxj = i_visc[face_id]*(pipp - pjppr);
8498
8499 rhs[ii] -= fluxi;
8500 rhs[jj] += fluxj;
8501
8502 }
8503 }
8504 }
8505
8506 /* Unsteady */
8507 } else {
8508
8509 for (int g_id = 0; g_id < n_i_groups; g_id++) {
8510 # pragma omp parallel for
8511 for (int t_id = 0; t_id < n_i_threads; t_id++) {
8512 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
8513 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
8514 face_id++) {
8515
8516 cs_lnum_t ii = i_face_cells[face_id][0];
8517 cs_lnum_t jj = i_face_cells[face_id][1];
8518
8519 cs_real_t pi = _pvar[ii];
8520 cs_real_t pj = _pvar[jj];
8521
8522 cs_real_t bldfrp = (cs_real_t) ircflp;
8523 /* Local limitation of the reconstruction */
8524 if (df_limiter != NULL && ircflp > 0)
8525 bldfrp = CS_MAX(df_limiter[jj], 0.);
8526
8527 /* Recompute II" and JJ"
8528 ----------------------*/
8529
8530 cs_real_t visci[3][3], viscj[3][3];
8531
8532 visci[0][0] = viscce[ii][0];
8533 visci[1][1] = viscce[ii][1];
8534 visci[2][2] = viscce[ii][2];
8535 visci[1][0] = viscce[ii][3];
8536 visci[0][1] = viscce[ii][3];
8537 visci[2][1] = viscce[ii][4];
8538 visci[1][2] = viscce[ii][4];
8539 visci[2][0] = viscce[ii][5];
8540 visci[0][2] = viscce[ii][5];
8541
8542 /* IF.Ki.S / ||Ki.S||^2 */
8543 cs_real_t fikdvi = weighf[face_id][0];
8544
8545 cs_real_t diippf[3], djjppf[3];
8546
8547 /* II" = IF + FI" */
8548 for (int i = 0; i < 3; i++) {
8549 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
8550 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
8551 + visci[1][i]*i_face_normal[face_id][1]
8552 + visci[2][i]*i_face_normal[face_id][2] );
8553 }
8554
8555 viscj[0][0] = viscce[jj][0];
8556 viscj[1][1] = viscce[jj][1];
8557 viscj[2][2] = viscce[jj][2];
8558 viscj[1][0] = viscce[jj][3];
8559 viscj[0][1] = viscce[jj][3];
8560 viscj[2][1] = viscce[jj][4];
8561 viscj[1][2] = viscce[jj][4];
8562 viscj[2][0] = viscce[jj][5];
8563 viscj[0][2] = viscce[jj][5];
8564
8565 /* FJ.Kj.S / ||Kj.S||^2 */
8566 cs_real_t fjkdvi = weighf[face_id][1];
8567
8568 /* JJ" = JF + FJ" */
8569 for (int i = 0; i < 3; i++) {
8570 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
8571 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
8572 + viscj[1][i]*i_face_normal[face_id][1]
8573 + viscj[2][i]*i_face_normal[face_id][2] );
8574 }
8575
8576 /* p in I" and J" */
8577 cs_real_t pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
8578 + grad[ii][1]*diippf[1]
8579 + grad[ii][2]*diippf[2]);
8580 cs_real_t pjpp = pj + bldfrp*( grad[jj][0]*djjppf[0]
8581 + grad[jj][1]*djjppf[1]
8582 + grad[jj][2]*djjppf[2]);
8583
8584 cs_real_t flux = i_visc[face_id]*(pipp -pjpp);
8585
8586 rhs[ii] -= thetap*flux;
8587 rhs[jj] += thetap*flux;
8588
8589 }
8590 }
8591 }
8592 }
8593
8594 /* ======================================================================
8595 ---> Contribution from boundary faces
8596 ======================================================================*/
8597
8598 /* Steady */
8599 if (idtvar < 0) {
8600
8601 for (int g_id = 0; g_id < n_b_groups; g_id++) {
8602 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
8603 for (int t_id = 0; t_id < n_b_threads; t_id++) {
8604 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
8605 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
8606 face_id++) {
8607
8608 cs_lnum_t ii = b_face_cells[face_id];
8609
8610 cs_real_t pi = _pvar[ii];
8611 cs_real_t pia = pvara[ii];
8612
8613 cs_real_t pir = pi/relaxp - (1.-relaxp)/relaxp*pia;
8614
8615 cs_real_t bldfrp = (cs_real_t) ircflp;
8616 /* Local limitation of the reconstruction */
8617 if (df_limiter != NULL && ircflp > 0)
8618 bldfrp = CS_MAX(df_limiter[ii], 0.);
8619
8620 /* Recompute II"
8621 --------------*/
8622
8623 cs_real_t visci[3][3];
8624
8625 visci[0][0] = viscce[ii][0];
8626 visci[1][1] = viscce[ii][1];
8627 visci[2][2] = viscce[ii][2];
8628 visci[1][0] = viscce[ii][3];
8629 visci[0][1] = viscce[ii][3];
8630 visci[2][1] = viscce[ii][4];
8631 visci[1][2] = viscce[ii][4];
8632 visci[2][0] = viscce[ii][5];
8633 visci[0][2] = viscce[ii][5];
8634
8635 /* IF.Ki.S / ||Ki.S||^2 */
8636 cs_real_t fikdvi = weighb[face_id];
8637
8638 cs_real_t diippf[3];
8639
8640 /* II" = IF + FI" */
8641 for (int i = 0; i < 3; i++) {
8642 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
8643 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
8644 + visci[1][i]*b_face_normal[face_id][1]
8645 + visci[2][i]*b_face_normal[face_id][2] );
8646 }
8647
8648 cs_real_t pippr = pir + bldfrp*( grad[ii][0]*diippf[0]
8649 + grad[ii][1]*diippf[1]
8650 + grad[ii][2]*diippf[2]);
8651
8652 cs_real_t pfacd = inc*cofafp[face_id] + cofbfp[face_id]*pippr;
8653
8654 cs_real_t flux = b_visc[face_id]*pfacd;
8655 rhs[ii] -= flux;
8656
8657 }
8658 }
8659 }
8660
8661 /* Unsteady */
8662 } else {
8663
8664 for (int g_id = 0; g_id < n_b_groups; g_id++) {
8665 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
8666 for (int t_id = 0; t_id < n_b_threads; t_id++) {
8667 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
8668 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
8669 face_id++) {
8670
8671 cs_lnum_t ii = b_face_cells[face_id];
8672
8673 cs_real_t pi = _pvar[ii];
8674
8675 cs_real_t bldfrp = (cs_real_t) ircflp;
8676 /* Local limitation of the reconstruction */
8677 if (df_limiter != NULL && ircflp > 0)
8678 bldfrp = CS_MAX(df_limiter[ii], 0.);
8679
8680 /* Recompute II"
8681 --------------*/
8682
8683 cs_real_t visci[3][3];
8684
8685 visci[0][0] = viscce[ii][0];
8686 visci[1][1] = viscce[ii][1];
8687 visci[2][2] = viscce[ii][2];
8688 visci[1][0] = viscce[ii][3];
8689 visci[0][1] = viscce[ii][3];
8690 visci[2][1] = viscce[ii][4];
8691 visci[1][2] = viscce[ii][4];
8692 visci[2][0] = viscce[ii][5];
8693 visci[0][2] = viscce[ii][5];
8694
8695 /* IF.Ki.S / ||Ki.S||^2 */
8696 cs_real_t fikdvi = weighb[face_id];
8697
8698 cs_real_t diippf[3];
8699
8700 /* II" = IF + FI" */
8701 for (int i = 0; i < 3; i++) {
8702 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
8703 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
8704 + visci[1][i]*b_face_normal[face_id][1]
8705 + visci[2][i]*b_face_normal[face_id][2]);
8706 }
8707
8708 cs_real_t pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
8709 + grad[ii][1]*diippf[1]
8710 + grad[ii][2]*diippf[2]);
8711
8712 cs_real_t pfacd = inc*cofafp[face_id] + cofbfp[face_id]*pipp;
8713
8714 cs_real_t flux = b_visc[face_id]*pfacd;
8715 rhs[ii] -= thetap*flux;
8716
8717 }
8718 }
8719 }
8720
8721 /* The scalar is internal_coupled and an implicit contribution
8722 * is required */
8723 if (icoupl > 0) {
8724
8725 /* Exchange pvar */
8726 BFT_MALLOC(pvar_local, n_local, cs_real_t);
8727 cs_internal_coupling_exchange_by_cell_id(cpl,
8728 1, /* Dimension */
8729 _pvar,
8730 pvar_local);
8731
8732 /* Exchange grad */
8733 BFT_MALLOC(grad_local, n_local, cs_real_3_t);
8734 cs_internal_coupling_exchange_by_cell_id(cpl,
8735 3, /* Dimension */
8736 (const cs_real_t*)grad,
8737 (cs_real_t *)grad_local);
8738
8739 /* Exchange viscce */
8740 BFT_MALLOC(viscce_local, n_local, cs_real_6_t);
8741 cs_internal_coupling_exchange_by_cell_id(cpl,
8742 6, /* Dimension */
8743 (const cs_real_t*)viscce,
8744 (cs_real_t *)viscce_local);
8745
8746 /* Exchange weighb */
8747 BFT_MALLOC(weighb_local, n_local, cs_real_t);
8748 cs_internal_coupling_exchange_by_face_id(cpl,
8749 1, /* Dimension */
8750 (const cs_real_t*)weighb,
8751 (cs_real_t *)weighb_local);
8752
8753 /* Exchange diffusion limiter */
8754 if (df_limiter != NULL) {
8755 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
8756 cs_internal_coupling_exchange_var(cpl,
8757 1, /* Dimension */
8758 df_limiter,
8759 df_limiter_local);
8760 }
8761
8762 /* Flux contribution */
8763 for (cs_lnum_t jj = 0; jj < n_local; jj++) {
8764 cs_lnum_t face_id = faces_local[jj];
8765 cs_lnum_t ii = b_face_cells[face_id];
8766
8767 cs_real_t pi = _pvar[ii];
8768 cs_real_t pj = pvar_local[jj];
8769
8770 cs_real_t bldfrp = (cs_real_t) ircflp;
8771 /* Local limitation of the reconstruction */
8772 if (df_limiter != NULL && ircflp > 0)
8773 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
8774
8775 /* Recompute II" and JJ" */
8776 cs_real_t visci[3][3], viscj[3][3];
8777 cs_real_t diippf[3], djjppf[3];
8778
8779 visci[0][0] = viscce[ii][0];
8780 visci[1][1] = viscce[ii][1];
8781 visci[2][2] = viscce[ii][2];
8782 visci[1][0] = viscce[ii][3];
8783 visci[0][1] = viscce[ii][3];
8784 visci[2][1] = viscce[ii][4];
8785 visci[1][2] = viscce[ii][4];
8786 visci[2][0] = viscce[ii][5];
8787 visci[0][2] = viscce[ii][5];
8788
8789 /* IF.Ki.S / ||Ki.S||^2 */
8790 cs_real_t fikdvi = weighb[face_id];
8791
8792 /* II" = IF + FI" */
8793 for (int i = 0; i < 3; i++) {
8794 diippf[i] = b_face_cog[face_id][i]-cell_cen[ii][i]
8795 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
8796 + visci[1][i]*b_face_normal[face_id][1]
8797 + visci[2][i]*b_face_normal[face_id][2] );
8798 }
8799
8800 viscj[0][0] = viscce_local[jj][0];
8801 viscj[1][1] = viscce_local[jj][1];
8802 viscj[2][2] = viscce_local[jj][2];
8803 viscj[1][0] = viscce_local[jj][3];
8804 viscj[0][1] = viscce_local[jj][3];
8805 viscj[2][1] = viscce_local[jj][4];
8806 viscj[1][2] = viscce_local[jj][4];
8807 viscj[2][0] = viscce_local[jj][5];
8808 viscj[0][2] = viscce_local[jj][5];
8809
8810 /* FJ.Kj.S / ||Kj.S||^2
8811 * weighb_local defined with vector JF and surface -S */
8812 cs_real_t fjkdvi = weighb_local[jj];
8813
8814 /* JJ" = JF + FJ"
8815 * */
8816 for (int i = 0; i < 3; i++) {
8817 djjppf[i] = b_face_cog[face_id][i]-cell_cen[ii][i]-cpl->ci_cj_vect[jj][i]
8818 + fjkdvi*( viscj[0][i]*b_face_normal[face_id][0]
8819 + viscj[1][i]*b_face_normal[face_id][1]
8820 + viscj[2][i]*b_face_normal[face_id][2] );
8821 }
8822
8823 /* p in I" and J" */
8824 cs_real_t pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
8825 + grad[ii][1]*diippf[1]
8826 + grad[ii][2]*diippf[2]);
8827 cs_real_t pjpp = pj + bldfrp*( grad_local[jj][0]*djjppf[0]
8828 + grad_local[jj][1]*djjppf[1]
8829 + grad_local[jj][2]*djjppf[2]);
8830
8831 /* Reproduce multiplication by i_visc[face_id] */
8832 cs_real_t flux = (pipp - pjpp) / (weighb[face_id] + weighb_local[jj]);
8833
8834 rhs[ii] -= thetap*flux;
8835
8836 }
8837
8838 /* Remote data no longer needed */
8839 BFT_FREE(pvar_local);
8840 if (df_limiter != NULL)
8841 BFT_FREE(df_limiter_local);
8842 BFT_FREE(grad_local);
8843 BFT_FREE(viscce_local);
8844 BFT_FREE(weighb_local);
8845 }
8846
8847 }
8848
8849 /* Free memory */
8850 BFT_FREE(grad);
8851 BFT_FREE(w2);
8852 }
8853
8854 /*-----------------------------------------------------------------------------*/
8855 /*!
8856 * \brief Add explicit part of the terms of diffusion by a left-multiplying
8857 * symmetric tensorial diffusivity for a transport equation of a vector field
8858 * \f$ \vect{\varia} \f$.
8859 *
8860 * More precisely, the right hand side \f$ \vect{Rhs} \f$ is updated as
8861 * follows:
8862 * \f[
8863 * \vect{Rhs} = \vect{Rhs} - \sum_{\fij \in \Facei{\celli}} \left(
8864 * - \gradt_\fij \vect{\varia} \tens{\mu}_\fij \cdot \vect{S}_\ij \right)
8865 * \f]
8866 *
8867 * Remark:
8868 * if ivisep = 1, then we also take \f$ \mu \transpose{\gradt\vect{\varia}}
8869 * + \lambda \trace{\gradt\vect{\varia}} \f$, where \f$ \lambda \f$ is
8870 * the secondary viscosity, i.e. usually \f$ -\frac{2}{3} \mu \f$.
8871 *
8872 * Warning:
8873 * - \f$ \vect{Rhs} \f$ has already been initialized before calling the present
8874 * function
8875 * - mind the sign minus
8876 *
8877 * \param[in] idtvar indicator of the temporal scheme
8878 * \param[in] f_id index of the current variable
8879 * \param[in] var_cal_opt variable calculation options
8880 * \param[in] inc indicator
8881 * - 0 when solving an increment
8882 * - 1 otherwise
8883 * \param[in] ivisep indicator to take \f$ \divv
8884 * \left(\mu \gradt \transpose{\vect{a}} \right)
8885 * -2/3 \grad\left( \mu \dive \vect{a} \right)\f$
8886 * - 1 take into account,
8887 * \param[in] pvar solved variable (current time step)
8888 * \param[in] pvara solved variable (previous time step)
8889 * \param[in] coefav boundary condition array for the variable
8890 * (explicit part)
8891 * \param[in] coefbv boundary condition array for the variable
8892 * (implicit part)
8893 * \param[in] cofafv boundary condition array for the diffusion
8894 * of the variable (explicit part)
8895 * \param[in] cofbfv boundary condition array for the diffusion
8896 * of the variable (implicit part)
8897 * \param[in] i_visc \f$ \tens{\mu}_\fij \dfrac{S_\fij}{\ipf\jpf} \f$
8898 * at interior faces for the r.h.s.
8899 * \param[in] b_visc \f$ \dfrac{S_\fib}{\ipf \centf} \f$
8900 * at border faces for the r.h.s.
8901 * \param[in] i_secvis secondary viscosity at interior faces
8902 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
8903 */
8904 /*----------------------------------------------------------------------------*/
8905
8906 void
cs_anisotropic_left_diffusion_vector(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int inc,int ivisep,cs_real_3_t * restrict pvar,const cs_real_3_t * restrict pvara,const cs_real_3_t coefav[],const cs_real_33_t coefbv[],const cs_real_3_t cofafv[],const cs_real_33_t cofbfv[],const cs_real_33_t i_visc[],const cs_real_t b_visc[],const cs_real_t i_secvis[],cs_real_3_t * restrict rhs)8907 cs_anisotropic_left_diffusion_vector(int idtvar,
8908 int f_id,
8909 const cs_var_cal_opt_t var_cal_opt,
8910 int inc,
8911 int ivisep,
8912 cs_real_3_t *restrict pvar,
8913 const cs_real_3_t *restrict pvara,
8914 const cs_real_3_t coefav[],
8915 const cs_real_33_t coefbv[],
8916 const cs_real_3_t cofafv[],
8917 const cs_real_33_t cofbfv[],
8918 const cs_real_33_t i_visc[],
8919 const cs_real_t b_visc[],
8920 const cs_real_t i_secvis[],
8921 cs_real_3_t *restrict rhs)
8922 {
8923 const int nswrgp = var_cal_opt.nswrgr;
8924 const int idiffp = var_cal_opt.idiff;
8925 const int imrgra = var_cal_opt.imrgra;
8926 const int imligp = var_cal_opt.imligr;
8927 const int ircflp = var_cal_opt.ircflu;
8928 const int iwarnp = var_cal_opt.verbosity;
8929 const int icoupl = var_cal_opt.icoupl;
8930 const double epsrgp = var_cal_opt.epsrgr;
8931 const double climgp = var_cal_opt.climgr;
8932 const double relaxp = var_cal_opt.relaxv;
8933 const double thetap = var_cal_opt.thetav;
8934
8935 const cs_mesh_t *m = cs_glob_mesh;
8936 const cs_halo_t *halo = m->halo;
8937 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
8938
8939 const cs_lnum_t n_cells = m->n_cells;
8940 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
8941 const int n_i_groups = m->i_face_numbering->n_groups;
8942 const int n_i_threads = m->i_face_numbering->n_threads;
8943 const int n_b_groups = m->b_face_numbering->n_groups;
8944 const int n_b_threads = m->b_face_numbering->n_threads;
8945 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
8946 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
8947
8948 const cs_lnum_2_t *restrict i_face_cells
8949 = (const cs_lnum_2_t *restrict)m->i_face_cells;
8950 const cs_lnum_t *restrict b_face_cells
8951 = (const cs_lnum_t *restrict)m->b_face_cells;
8952 const cs_real_t *restrict weight = fvq->weight;
8953 const cs_real_3_t *restrict i_f_face_normal
8954 = (const cs_real_3_t *restrict)fvq->i_f_face_normal;
8955 const cs_real_3_t *restrict i_face_normal
8956 = (const cs_real_3_t *restrict)fvq->i_face_normal;
8957 const cs_real_t *restrict i_dist = fvq->i_dist;
8958 const cs_real_3_t *restrict diipf
8959 = (const cs_real_3_t *restrict)fvq->diipf;
8960 const cs_real_3_t *restrict djjpf
8961 = (const cs_real_3_t *restrict)fvq->djjpf;
8962 const cs_real_3_t *restrict diipb
8963 = (const cs_real_3_t *restrict)fvq->diipb;
8964
8965 const int *bc_type = cs_glob_bc_type;
8966
8967 /* Internal coupling variables */
8968 const cs_lnum_t *faces_local = NULL, *faces_distant = NULL;
8969 cs_lnum_t n_local = 0, n_distant = 0;
8970 int coupling_id = -1;
8971 cs_internal_coupling_t *cpl = NULL;
8972
8973 /* Local variables */
8974
8975 cs_real_t *df_limiter = NULL;
8976
8977 char var_name[64];
8978
8979 cs_real_33_t *gradv;
8980 cs_real_t *bndcel;
8981
8982 cs_field_t *f = NULL;
8983
8984 /* 1. Initialization */
8985
8986 /* Allocate work arrays */
8987 BFT_MALLOC(gradv, n_cells_ext, cs_real_33_t);
8988
8989 /* Choose gradient type */
8990
8991 cs_halo_type_t halo_type = CS_HALO_STANDARD;
8992 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
8993
8994 cs_gradient_type_by_imrgra(imrgra,
8995 &gradient_type,
8996 &halo_type);
8997
8998 /* Handle cases where only the previous values (already synchronized)
8999 or current values are provided */
9000
9001 if (pvar != NULL && halo != NULL) {
9002 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)pvar, 3);
9003 if (cs_glob_mesh->n_init_perio > 0)
9004 cs_halo_perio_sync_var_vect(halo, halo_type, (cs_real_t *)pvar, 3);
9005 }
9006 if (pvara == NULL)
9007 pvara = (const cs_real_3_t *restrict)pvar;
9008
9009 const cs_real_3_t *restrict _pvar
9010 = (pvar != NULL) ? (const cs_real_3_t *restrict)pvar : pvara;
9011
9012 /* logging info */
9013
9014 if (f_id != -1) {
9015 f = cs_field_by_id(f_id);
9016
9017 int df_limiter_id =
9018 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
9019 if (df_limiter_id > -1)
9020 df_limiter = cs_field_by_id(df_limiter_id)->val;
9021
9022 snprintf(var_name, 63, "%s", f->name);
9023 }
9024 else
9025 strncpy(var_name, "[anisotropic left diffusion, vector]", 63);
9026 var_name[63] = '\0';
9027
9028 if (icoupl > 0) {
9029 assert(f_id != -1);
9030 const int coupling_key_id = cs_field_key_id("coupling_entity");
9031 coupling_id = cs_field_get_key_int(f, coupling_key_id);
9032 cpl = cs_internal_coupling_by_id(coupling_id);
9033 cs_internal_coupling_coupled_faces(cpl,
9034 &n_local,
9035 &faces_local,
9036 &n_distant,
9037 &faces_distant);
9038 }
9039
9040
9041 /* 2. Compute the diffusive part with reconstruction technics */
9042
9043 /* Compute the gradient of the current variable if needed */
9044
9045 if (ircflp == 1 || ivisep == 1) {
9046
9047 cs_gradient_vector_synced_input(var_name,
9048 gradient_type,
9049 halo_type,
9050 inc,
9051 nswrgp,
9052 iwarnp,
9053 imligp,
9054 epsrgp,
9055 climgp,
9056 coefav,
9057 coefbv,
9058 _pvar,
9059 NULL, /* weighted gradient */
9060 cpl,
9061 gradv);
9062
9063 } else {
9064 # pragma omp parallel for
9065 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
9066 for (int isou = 0; isou < 3; isou++) {
9067 for (int jsou = 0; jsou < 3; jsou++)
9068 gradv[cell_id][isou][jsou] = 0.;
9069 }
9070 }
9071 }
9072
9073 /* ======================================================================
9074 ---> Contribution from interior faces
9075 ======================================================================*/
9076
9077 if (n_cells_ext > n_cells) {
9078 # pragma omp parallel for if(n_cells_ext -n_cells > CS_THR_MIN)
9079 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
9080 for (int isou = 0; isou < 3; isou++) {
9081 rhs[cell_id][isou] = 0.;
9082 }
9083 }
9084 }
9085
9086 /* Steady */
9087 if (idtvar < 0) {
9088
9089 for (int g_id = 0; g_id < n_i_groups; g_id++) {
9090 # pragma omp parallel for
9091 for (int t_id = 0; t_id < n_i_threads; t_id++) {
9092 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
9093 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
9094 face_id++) {
9095
9096 cs_lnum_t ii = i_face_cells[face_id][0];
9097 cs_lnum_t jj = i_face_cells[face_id][1];
9098
9099 cs_real_t pip[3], pjp[3], pipr[3], pjpr[3];
9100
9101 cs_real_t bldfrp = (cs_real_t) ircflp;
9102 /* Local limitation of the reconstruction */
9103 if (df_limiter != NULL && ircflp > 0)
9104 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
9105
9106 /*-----------------
9107 X-Y-Z components, p = u, v, w */
9108 for (int isou = 0; isou < 3; isou++) {
9109
9110 cs_real_t dpvf[3];
9111
9112 for (int jsou = 0; jsou < 3; jsou++) {
9113 dpvf[jsou] = 0.5*(gradv[ii][isou][jsou] + gradv[jj][isou][jsou]);
9114 }
9115
9116 cs_real_t pi = _pvar[ii][isou];
9117 cs_real_t pj = _pvar[jj][isou];
9118
9119 cs_real_t pia = pvara[ii][isou];
9120 cs_real_t pja = pvara[jj][isou];
9121
9122 /* reconstruction only if IRCFLP = 1 */
9123 pip[isou] = pi + bldfrp * (cs_math_3_dot_product(dpvf, diipf[face_id]));
9124 pjp[isou] = pj + bldfrp * (cs_math_3_dot_product(dpvf, djjpf[face_id]));
9125
9126 pipr[isou] = pi /relaxp - (1.-relaxp)/relaxp * pia
9127 + bldfrp * (cs_math_3_dot_product(dpvf, diipf[face_id]));
9128 pjpr[isou] = pj /relaxp - (1.-relaxp)/relaxp * pja
9129 + bldfrp * (cs_math_3_dot_product(dpvf, djjpf[face_id]));
9130
9131 }
9132
9133 for (int isou = 0; isou < 3; isou++) {
9134
9135 cs_real_t fluxi = i_visc[face_id][0][isou]*(pipr[0] - pjp[0])
9136 + i_visc[face_id][1][isou]*(pipr[1] - pjp[1])
9137 + i_visc[face_id][2][isou]*(pipr[2] - pjp[2]);
9138 cs_real_t fluxj = i_visc[face_id][0][isou]*(pip[0] - pjpr[0])
9139 + i_visc[face_id][1][isou]*(pip[1] - pjpr[1])
9140 + i_visc[face_id][2][isou]*(pip[2] - pjpr[2]);
9141
9142 rhs[ii][isou] = rhs[ii][isou] - fluxi;
9143 rhs[jj][isou] = rhs[jj][isou] + fluxj;
9144
9145 }
9146
9147 }
9148 }
9149 }
9150
9151 /* Unsteady */
9152 } else {
9153
9154 for (int g_id = 0; g_id < n_i_groups; g_id++) {
9155 # pragma omp parallel for
9156 for (int t_id = 0; t_id < n_i_threads; t_id++) {
9157 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
9158 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
9159 face_id++) {
9160
9161 cs_lnum_t ii = i_face_cells[face_id][0];
9162 cs_lnum_t jj = i_face_cells[face_id][1];
9163
9164 cs_real_t pip[3], pjp[3];
9165
9166 cs_real_t bldfrp = (cs_real_t) ircflp;
9167 /* Local limitation of the reconstruction */
9168 if (df_limiter != NULL && ircflp > 0)
9169 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
9170
9171 /*-----------------
9172 X-Y-Z components, p = u, v, w */
9173 for (int isou = 0; isou < 3; isou++) {
9174
9175 cs_real_t dpvf[3];
9176
9177 for (int jsou = 0; jsou < 3; jsou++) {
9178 dpvf[jsou] = 0.5*(gradv[ii][isou][jsou] + gradv[jj][isou][jsou]);
9179 }
9180
9181 cs_real_t pi = _pvar[ii][isou];
9182 cs_real_t pj = _pvar[jj][isou];
9183
9184 pip[isou] = pi + bldfrp * (cs_math_3_dot_product(dpvf, diipf[face_id]));
9185 pjp[isou] = pj + bldfrp * (cs_math_3_dot_product(dpvf, djjpf[face_id]));
9186
9187 }
9188
9189 for (int isou = 0; isou < 3; isou++) {
9190
9191 cs_real_t flux = i_visc[face_id][0][isou]*(pip[0] - pjp[0])
9192 + i_visc[face_id][1][isou]*(pip[1] - pjp[1])
9193 + i_visc[face_id][2][isou]*(pip[2] - pjp[2]);
9194
9195 rhs[ii][isou] -= thetap*flux;
9196 rhs[jj][isou] += thetap*flux;
9197
9198 }
9199
9200 }
9201 }
9202 }
9203
9204 }
9205
9206 /* ======================================================================
9207 ---> Contribution from boundary faces
9208 ======================================================================*/
9209
9210 /* Steady */
9211 if (idtvar < 0) {
9212
9213 for (int g_id = 0; g_id < n_b_groups; g_id++) {
9214 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
9215 for (int t_id = 0; t_id < n_b_threads; t_id++) {
9216 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
9217 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
9218 face_id++) {
9219
9220 cs_lnum_t cell_id = b_face_cells[face_id];
9221
9222 cs_real_t bldfrp = (cs_real_t) ircflp;
9223 /* Local limitation of the reconstruction */
9224 if (df_limiter != NULL && ircflp > 0)
9225 bldfrp = CS_MAX(df_limiter[cell_id], 0.);
9226
9227 const cs_real_t *diipbv = diipb[face_id];
9228 cs_real_t pipr[3];
9229
9230 for (int k = 0; k < 3; k++) {
9231 cs_real_t pir = _pvar[cell_id][k]/relaxp
9232 - (1.-relaxp)/relaxp*pvara[cell_id][k];
9233
9234 pipr[k] = pir +bldfrp*( gradv[cell_id][k][0]*diipbv[0]
9235 + gradv[cell_id][k][1]*diipbv[1]
9236 + gradv[cell_id][k][2]*diipbv[2]);
9237
9238 }
9239
9240 /*-----------------
9241 X-Y-Z components, p = u, v, w */
9242 for (int i = 0; i < 3; i++) {
9243
9244 cs_real_t pfacd = inc*cofafv[face_id][i];
9245
9246 /*coefu and cofuf and b_visc are matrices */
9247 for (int j = 0; j < 3; j++) {
9248
9249 pfacd += cofbfv[face_id][i][j]*pipr[j];
9250 }
9251
9252 rhs[cell_id][i] -= b_visc[face_id] * pfacd;
9253
9254 } /* i */
9255
9256 }
9257 }
9258 }
9259
9260 /* Unsteady */
9261 } else {
9262
9263 for (int g_id = 0; g_id < n_b_groups; g_id++) {
9264 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
9265 for (int t_id = 0; t_id < n_b_threads; t_id++) {
9266 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
9267 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
9268 face_id++) {
9269
9270 cs_lnum_t cell_id = b_face_cells[face_id];
9271
9272 cs_real_t bldfrp = (cs_real_t) ircflp;
9273 /* Local limitation of the reconstruction */
9274 if (df_limiter != NULL && ircflp > 0)
9275 bldfrp = CS_MAX(df_limiter[cell_id], 0.);
9276
9277 cs_real_t diipbv[3];
9278
9279 for (int k = 0; k < 3; k++)
9280 diipbv[k] = diipb[face_id][k];
9281
9282 /*-----------------
9283 X-Y-Z components, p = u, v, w */
9284 for (int i = 0; i < 3; i++) {
9285
9286 cs_real_t pfacd = inc*cofafv[face_id][i];
9287
9288 /*coefu and cofuf are matrices */
9289 for (int j = 0; j < 3; j++) {
9290 cs_real_t pir = _pvar[cell_id][j]
9291 + bldfrp*( gradv[cell_id][j][0]*diipbv[0]
9292 + gradv[cell_id][j][1]*diipbv[1]
9293 + gradv[cell_id][j][2]*diipbv[2]);
9294 pfacd += cofbfv[face_id][j][i]*pir;
9295 }
9296
9297 rhs[cell_id][i] -= thetap * b_visc[face_id] * pfacd;
9298
9299 } /* i */
9300
9301 }
9302 }
9303 }
9304
9305 } /* idtvar */
9306
9307 /* 3. Computation of the transpose grad(vel) term and grad(-2/3 div(vel)) */
9308
9309 if (ivisep == 1 && idiffp == 1) {
9310
9311 /* We do not know what condition to put in the inlets and the outlets, so we
9312 assume that there is an equilibrium. Moreover, cells containing a coupled
9313 are removed. */
9314
9315 /* Allocate a temporary array */
9316 BFT_MALLOC(bndcel, n_cells_ext, cs_real_t);
9317
9318 # pragma omp parallel for
9319 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
9320 bndcel[cell_id] = 1.;
9321 }
9322
9323 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
9324 for (cs_lnum_t face_id = 0; face_id < m->n_b_faces; face_id++) {
9325 int ityp = bc_type[face_id];
9326 if ( ityp == CS_OUTLET
9327 || ityp == CS_INLET
9328 || ityp == CS_FREE_INLET
9329 || ityp == CS_CONVECTIVE_INLET
9330 || ityp == CS_COUPLED_FD) {
9331 bndcel[b_face_cells[face_id]] = 0.;
9332 }
9333 }
9334
9335 if (halo != NULL)
9336 cs_halo_sync_var(halo, halo_type, bndcel);
9337
9338 /* ---> Interior faces */
9339
9340 for (int g_id = 0; g_id < n_i_groups; g_id++) {
9341 # pragma omp parallel for
9342 for (int t_id = 0; t_id < n_i_threads; t_id++) {
9343 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
9344 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
9345 face_id++) {
9346
9347 cs_lnum_t ii = i_face_cells[face_id][0];
9348 cs_lnum_t jj = i_face_cells[face_id][1];
9349
9350 cs_real_t pnd = weight[face_id];
9351 cs_real_t secvis = i_secvis[face_id];
9352
9353 cs_real_t grdtrv
9354 = pnd*(gradv[ii][0][0]+gradv[ii][1][1]+gradv[ii][2][2])
9355 + (1.-pnd)*(gradv[jj][0][0]+gradv[jj][1][1]+gradv[jj][2][2]);
9356
9357 cs_real_3_t n, ipjp;
9358 cs_math_3_normalise(i_face_normal[face_id], n);
9359
9360 /* I'J' */
9361 for (int i = 0; i < 3; i++)
9362 ipjp[i] = n[i] * i_dist[face_id];
9363
9364 for (int i = 0; i < 3; i++) {
9365
9366 cs_real_t flux = secvis*grdtrv*i_f_face_normal[face_id][i];
9367
9368 /* We need to compute (K grad(u)^T) .I'J'
9369 which is equal to I'J' . (grad(u) . K^T)
9370 But: (I'J' . (grad(u) . K^T))_i = I'J'_k grad(u)_kj K_ij
9371 */
9372
9373 for (int j = 0; j < 3; j++) {
9374 for (int k = 0; k < 3; k++) {
9375 flux += ipjp[k]
9376 *(pnd*gradv[ii][k][j]+(1-pnd)*gradv[jj][k][j])
9377 *i_visc[face_id][i][j];
9378 }
9379 }
9380
9381 rhs[ii][i] += flux*bndcel[ii];
9382 rhs[jj][i] -= flux*bndcel[jj];
9383
9384 }
9385
9386 }
9387 }
9388 }
9389
9390 /* ---> Boundary FACES
9391 the whole flux term of the stress tensor is already taken into account
9392 (so, no corresponding term in forbr)
9393 TODO in theory we should take the normal component into account (the
9394 tangential one is modeled by the wall law) */
9395
9396 /*Free memory */
9397 BFT_FREE(bndcel);
9398
9399 }
9400
9401 /* Free memory */
9402 BFT_FREE(gradv);
9403 }
9404
9405 /*-----------------------------------------------------------------------------*/
9406 /*!
9407 * \brief Add explicit part of the terms of diffusion by a right-multiplying
9408 * symmetric tensorial diffusivity for a transport equation of a vector field
9409 * \f$ \vect{\varia} \f$.
9410 *
9411 * More precisely, the right hand side \f$ \vect{Rhs} \f$ is updated as
9412 * follows:
9413 * \f[
9414 * \vect{Rhs} = \vect{Rhs} - \sum_{\fij \in \Facei{\celli}} \left(
9415 * - \gradt_\fij \vect{\varia} \tens{\mu}_\fij \cdot \vect{S}_\ij \right)
9416 * \f]
9417 *
9418 * Warning:
9419 * - \f$ \vect{Rhs} \f$ has already been initialized before calling the present
9420 * function
9421 * - mind the sign minus
9422 *
9423 * \param[in] idtvar indicator of the temporal scheme
9424 * \param[in] f_id index of the current variable
9425 * \param[in] var_cal_opt variable calculation options
9426 * \param[in] inc indicator
9427 * - 0 when solving an increment
9428 * - 1 otherwise
9429 * \param[in] pvar solved variable (current time step)
9430 * \param[in] pvara solved variable (previous time step)
9431 * \param[in] coefav boundary condition array for the variable
9432 * (explicit part)
9433 * \param[in] coefbv boundary condition array for the variable
9434 * (implicit part)
9435 * \param[in] cofafv boundary condition array for the diffusion
9436 * of the variable (explicit part)
9437 * \param[in] cofbfv boundary condition array for the diffusion
9438 * of the variable (implicit part)
9439 * \param[in] i_visc \f$ \tens{\mu}_\fij \dfrac{S_\fij}{\ipf\jpf} \f$
9440 * at interior faces for the r.h.s.
9441 * \param[in] b_visc \f$ \dfrac{S_\fib}{\ipf \centf} \f$
9442 * at border faces for the r.h.s.
9443 * \param[in] viscel symmetric cell tensor \f$ \tens{\mu}_\celli \f$
9444 * \param[in] weighf internal face weight between cells i j in case
9445 * of tensor diffusion
9446 * \param[in] weighb boundary face weight for cells i in case
9447 * of tensor diffusion
9448 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
9449 */
9450 /*----------------------------------------------------------------------------*/
9451
9452 void
cs_anisotropic_right_diffusion_vector(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int inc,cs_real_3_t * restrict pvar,const cs_real_3_t * restrict pvara,const cs_real_3_t coefav[],const cs_real_33_t coefbv[],const cs_real_3_t cofafv[],const cs_real_33_t cofbfv[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_6_t * restrict viscel,const cs_real_2_t weighf[],const cs_real_t weighb[],cs_real_3_t * restrict rhs)9453 cs_anisotropic_right_diffusion_vector(int idtvar,
9454 int f_id,
9455 const cs_var_cal_opt_t var_cal_opt,
9456 int inc,
9457 cs_real_3_t *restrict pvar,
9458 const cs_real_3_t *restrict pvara,
9459 const cs_real_3_t coefav[],
9460 const cs_real_33_t coefbv[],
9461 const cs_real_3_t cofafv[],
9462 const cs_real_33_t cofbfv[],
9463 const cs_real_t i_visc[],
9464 const cs_real_t b_visc[],
9465 cs_real_6_t *restrict viscel,
9466 const cs_real_2_t weighf[],
9467 const cs_real_t weighb[],
9468 cs_real_3_t *restrict rhs)
9469 {
9470 const int nswrgp = var_cal_opt.nswrgr;
9471 const int imrgra = var_cal_opt.imrgra;
9472 const int imligp = var_cal_opt.imligr;
9473 const int ircflp = var_cal_opt.ircflu;
9474 const int iwarnp = var_cal_opt.verbosity;
9475 const int icoupl = var_cal_opt.icoupl;
9476 const double epsrgp = var_cal_opt.epsrgr;
9477 const double climgp = var_cal_opt.climgr;
9478 const double relaxp = var_cal_opt.relaxv;
9479 const double thetap = var_cal_opt.thetav;
9480
9481 const cs_mesh_t *m = cs_glob_mesh;
9482 const cs_halo_t *halo = m->halo;
9483 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
9484
9485 const cs_lnum_t n_cells = m->n_cells;
9486 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
9487 const int n_i_groups = m->i_face_numbering->n_groups;
9488 const int n_i_threads = m->i_face_numbering->n_threads;
9489 const int n_b_groups = m->b_face_numbering->n_groups;
9490 const int n_b_threads = m->b_face_numbering->n_threads;
9491 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
9492 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
9493
9494 const cs_lnum_2_t *restrict i_face_cells
9495 = (const cs_lnum_2_t *restrict)m->i_face_cells;
9496 const cs_lnum_t *restrict b_face_cells
9497 = (const cs_lnum_t *restrict)m->b_face_cells;
9498 const cs_real_3_t *restrict cell_cen
9499 = (const cs_real_3_t *restrict)fvq->cell_cen;
9500 const cs_real_3_t *restrict i_face_normal
9501 = (const cs_real_3_t *restrict)fvq->i_face_normal;
9502 const cs_real_3_t *restrict b_face_normal
9503 = (const cs_real_3_t *restrict)fvq->b_face_normal;
9504 const cs_real_3_t *restrict i_face_cog
9505 = (const cs_real_3_t *restrict)fvq->i_face_cog;
9506 const cs_real_3_t *restrict b_face_cog
9507 = (const cs_real_3_t *restrict)fvq->b_face_cog;
9508
9509 /* Internal coupling variables */
9510 cs_real_3_t *pvar_local = NULL;
9511 cs_real_33_t *grad_local = NULL;
9512 cs_real_t *df_limiter_local = NULL;
9513 cs_real_6_t *viscce_local = NULL;
9514 cs_real_t *weighb_local = NULL;
9515 const cs_lnum_t *faces_local = NULL, *faces_distant = NULL;
9516 cs_lnum_t n_local = 0, n_distant = 0;
9517 int coupling_id = -1;
9518 cs_internal_coupling_t *cpl = NULL;
9519
9520 /* Local variables */
9521
9522 cs_real_t *df_limiter = NULL;
9523
9524 char var_name[64];
9525
9526 cs_real_6_t *viscce;
9527 cs_real_33_t *grad;
9528
9529 cs_field_t *f = NULL;
9530
9531 /* 1. Initialization */
9532
9533 viscce = NULL;
9534
9535 /* Allocate work arrays */
9536 BFT_MALLOC(grad, n_cells_ext, cs_real_33_t);
9537
9538 /* Choose gradient type */
9539
9540 cs_halo_type_t halo_type = CS_HALO_STANDARD;
9541 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
9542
9543 cs_gradient_type_by_imrgra(imrgra,
9544 &gradient_type,
9545 &halo_type);
9546
9547 /* Handle cases where only the previous values (already synchronized)
9548 or current values are provided */
9549
9550 if (pvar != NULL && halo != NULL) {
9551 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)pvar, 3);
9552 if (cs_glob_mesh->n_init_perio > 0)
9553 cs_halo_perio_sync_var_vect(halo, halo_type, (cs_real_t *)pvar, 3);
9554 }
9555 if (pvara == NULL)
9556 pvara = (const cs_real_3_t *restrict)pvar;
9557
9558 const cs_real_3_t *restrict _pvar
9559 = (pvar != NULL) ? (const cs_real_3_t *restrict)pvar : pvara;
9560
9561 /* logging info */
9562
9563 if (f_id != -1) {
9564 f = cs_field_by_id(f_id);
9565
9566 int df_limiter_id =
9567 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
9568 if (df_limiter_id > -1)
9569 df_limiter = cs_field_by_id(df_limiter_id)->val;
9570
9571 snprintf(var_name, 63, "%s", f->name);
9572 }
9573 else
9574 strncpy(var_name, "[anisotropic right diffusion, vector]", 63);
9575 var_name[63] = '\0';
9576
9577 viscce = viscel;
9578
9579 if (icoupl > 0) {
9580 assert(f_id != -1);
9581 const int coupling_key_id = cs_field_key_id("coupling_entity");
9582 coupling_id = cs_field_get_key_int(f, coupling_key_id);
9583 cpl = cs_internal_coupling_by_id(coupling_id);
9584 cs_internal_coupling_coupled_faces(cpl,
9585 &n_local,
9586 &faces_local,
9587 &n_distant,
9588 &faces_distant);
9589 }
9590
9591 /* 2. Compute the diffusive part with reconstruction technics */
9592
9593 /* Compute the gradient of the current variable if needed */
9594
9595 if (ircflp == 1) {
9596
9597 cs_gradient_vector_synced_input(var_name,
9598 gradient_type,
9599 halo_type,
9600 inc,
9601 nswrgp,
9602 iwarnp,
9603 imligp,
9604 epsrgp,
9605 climgp,
9606 coefav,
9607 coefbv,
9608 _pvar,
9609 NULL, /* weighted gradient */
9610 cpl,
9611 grad);
9612
9613 } else {
9614 # pragma omp parallel for
9615 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
9616 for (int isou = 0; isou < 3; isou++) {
9617 for (int jsou = 0; jsou < 3; jsou++)
9618 grad[cell_id][isou][jsou] = 0.;
9619 }
9620 }
9621 }
9622
9623 /* ======================================================================
9624 ---> Contribution from interior faces
9625 ======================================================================*/
9626
9627 if (n_cells_ext > n_cells) {
9628 # pragma omp parallel for if(n_cells_ext -n_cells > CS_THR_MIN)
9629 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
9630 for (int isou = 0; isou < 3; isou++) {
9631 rhs[cell_id][isou] = 0.;
9632 }
9633 }
9634 }
9635
9636 /* Steady */
9637 if (idtvar < 0) {
9638
9639 for (int g_id = 0; g_id < n_i_groups; g_id++) {
9640 # pragma omp parallel for
9641 for (int t_id = 0; t_id < n_i_threads; t_id++) {
9642 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
9643 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
9644 face_id++) {
9645
9646 cs_lnum_t ii = i_face_cells[face_id][0];
9647 cs_lnum_t jj = i_face_cells[face_id][1];
9648
9649 cs_real_t visci[3][3], viscj[3][3];
9650 cs_real_t diippf[3], djjppf[3], pipp[3], pjpp[3];
9651 cs_real_t pir[3], pjr[3], pippr[3], pjppr[3];
9652 cs_real_t pi[3], pj[3], pia[3], pja[3];
9653
9654 for (int isou = 0; isou < 3; isou++) {
9655 pi[isou] = _pvar[ii][isou];
9656 pj[isou] = _pvar[jj][isou];
9657 pia[isou] = pvara[ii][isou];
9658 pja[isou] = pvara[jj][isou];
9659 }
9660
9661 cs_real_t bldfrp = (cs_real_t) ircflp;
9662 /* Local limitation of the reconstruction */
9663 if (df_limiter != NULL && ircflp > 0)
9664 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
9665
9666 /* Recompute II' and JJ' at this level */
9667
9668 visci[0][0] = viscce[ii][0];
9669 visci[1][1] = viscce[ii][1];
9670 visci[2][2] = viscce[ii][2];
9671 visci[1][0] = viscce[ii][3];
9672 visci[0][1] = viscce[ii][3];
9673 visci[2][1] = viscce[ii][4];
9674 visci[1][2] = viscce[ii][4];
9675 visci[2][0] = viscce[ii][5];
9676 visci[0][2] = viscce[ii][5];
9677
9678 /* IF.Ki.S / ||Ki.S||^2 */
9679 cs_real_t fikdvi = weighf[face_id][0];
9680
9681 /* II" = IF + FI" */
9682 for (int i = 0; i < 3; i++) {
9683 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
9684 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
9685 + visci[1][i]*i_face_normal[face_id][1]
9686 + visci[2][i]*i_face_normal[face_id][2] );
9687 }
9688
9689 viscj[0][0] = viscce[jj][0];
9690 viscj[1][1] = viscce[jj][1];
9691 viscj[2][2] = viscce[jj][2];
9692 viscj[1][0] = viscce[jj][3];
9693 viscj[0][1] = viscce[jj][3];
9694 viscj[2][1] = viscce[jj][4];
9695 viscj[1][2] = viscce[jj][4];
9696 viscj[2][0] = viscce[jj][5];
9697 viscj[0][2] = viscce[jj][5];
9698
9699 /* FJ.Kj.S / ||Kj.S||^2 */
9700 cs_real_t fjkdvi = weighf[face_id][1];
9701
9702 /* JJ" = JF + FJ" */
9703 for (int i = 0; i < 3; i++) {
9704 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
9705 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
9706 + viscj[1][i]*i_face_normal[face_id][1]
9707 + viscj[2][i]*i_face_normal[face_id][2] );
9708 }
9709
9710 for (int isou = 0; isou < 3; isou++) {
9711 /* p in I" and J" */
9712 pipp[isou] = pi[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
9713 + grad[ii][isou][1]*diippf[1]
9714 + grad[ii][isou][2]*diippf[2]);
9715 pjpp[isou] = pj[isou] + bldfrp*( grad[jj][isou][0]*djjppf[0]
9716 + grad[jj][isou][1]*djjppf[1]
9717 + grad[jj][isou][2]*djjppf[2]);
9718
9719 pir[isou] = pi[isou]/relaxp - (1.-relaxp)/relaxp * pia[isou];
9720 pjr[isou] = pj[isou]/relaxp - (1.-relaxp)/relaxp * pja[isou];
9721
9722
9723 /* pr in I" and J" */
9724 pippr[isou] = pir[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
9725 + grad[ii][isou][1]*diippf[1]
9726 + grad[ii][isou][2]*diippf[2]);
9727 pjppr[isou] = pjr[isou] + bldfrp*( grad[jj][isou][0]*djjppf[0]
9728 + grad[jj][isou][1]*djjppf[1]
9729 + grad[jj][isou][2]*djjppf[2]);
9730
9731 cs_real_t fluxi = i_visc[face_id]*(pippr[isou] - pjpp[isou]);
9732 cs_real_t fluxj = i_visc[face_id]*(pipp[isou] - pjppr[isou]);
9733
9734 rhs[ii][isou] -= fluxi;
9735 rhs[jj][isou] += fluxj;
9736 }
9737 }
9738 }
9739 }
9740
9741 /* Unsteady */
9742 } else {
9743
9744 for (int g_id = 0; g_id < n_i_groups; g_id++) {
9745 # pragma omp parallel for
9746 for (int t_id = 0; t_id < n_i_threads; t_id++) {
9747 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
9748 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
9749 face_id++) {
9750
9751 cs_lnum_t ii = i_face_cells[face_id][0];
9752 cs_lnum_t jj = i_face_cells[face_id][1];
9753
9754 cs_real_t visci[3][3], viscj[3][3];
9755 cs_real_t diippf[3], djjppf[3], pipp[3], pjpp[3];
9756 cs_real_t pi[3], pj[3];
9757
9758 for (int isou = 0; isou < 3; isou++) {
9759 pi[isou] = _pvar[ii][isou];
9760 pj[isou] = _pvar[jj][isou];
9761 }
9762
9763 cs_real_t bldfrp = (cs_real_t) ircflp;
9764 /* Local limitation of the reconstruction */
9765 if (df_limiter != NULL && ircflp > 0)
9766 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
9767
9768 /* Recompute II' and JJ' at this level */
9769
9770 visci[0][0] = viscce[ii][0];
9771 visci[1][1] = viscce[ii][1];
9772 visci[2][2] = viscce[ii][2];
9773 visci[1][0] = viscce[ii][3];
9774 visci[0][1] = viscce[ii][3];
9775 visci[2][1] = viscce[ii][4];
9776 visci[1][2] = viscce[ii][4];
9777 visci[2][0] = viscce[ii][5];
9778 visci[0][2] = viscce[ii][5];
9779
9780 /* IF.Ki.S / ||Ki.S||^2 */
9781 cs_real_t fikdvi = weighf[face_id][0];
9782
9783 /* II" = IF + FI" */
9784 for (int i = 0; i < 3; i++) {
9785 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
9786 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
9787 + visci[1][i]*i_face_normal[face_id][1]
9788 + visci[2][i]*i_face_normal[face_id][2] );
9789 }
9790
9791 viscj[0][0] = viscce[jj][0];
9792 viscj[1][1] = viscce[jj][1];
9793 viscj[2][2] = viscce[jj][2];
9794 viscj[1][0] = viscce[jj][3];
9795 viscj[0][1] = viscce[jj][3];
9796 viscj[2][1] = viscce[jj][4];
9797 viscj[1][2] = viscce[jj][4];
9798 viscj[2][0] = viscce[jj][5];
9799 viscj[0][2] = viscce[jj][5];
9800
9801 /* FJ.Kj.S / ||Kj.S||^2 */
9802 cs_real_t fjkdvi = weighf[face_id][1];
9803
9804 /* JJ" = JF + FJ" */
9805 for (int i = 0; i < 3; i++) {
9806 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
9807 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
9808 + viscj[1][i]*i_face_normal[face_id][1]
9809 + viscj[2][i]*i_face_normal[face_id][2] );
9810 }
9811
9812 for (int isou = 0; isou < 3; isou++) {
9813 /* p in I" and J" */
9814 pipp[isou] = pi[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
9815 + grad[ii][isou][1]*diippf[1]
9816 + grad[ii][isou][2]*diippf[2]);
9817 pjpp[isou] = pj[isou] + bldfrp*( grad[jj][isou][0]*djjppf[0]
9818 + grad[jj][isou][1]*djjppf[1]
9819 + grad[jj][isou][2]*djjppf[2]);
9820
9821 cs_real_t flux = i_visc[face_id]*(pipp[isou] -pjpp[isou]);
9822
9823 rhs[ii][isou] -= thetap*flux;
9824 rhs[jj][isou] += thetap*flux;
9825
9826 }
9827
9828 }
9829 }
9830 }
9831
9832 }
9833
9834 /* ======================================================================
9835 ---> Contribution from boundary faces
9836 ======================================================================*/
9837
9838 /* Steady */
9839 if (idtvar < 0) {
9840
9841 for (int g_id = 0; g_id < n_b_groups; g_id++) {
9842 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
9843 for (int t_id = 0; t_id < n_b_threads; t_id++) {
9844 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
9845 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
9846 face_id++) {
9847
9848 cs_lnum_t ii = b_face_cells[face_id];
9849
9850 cs_real_t pi[3], pia[3], pir[3], pippr[3];
9851 cs_real_t visci[3][3];
9852 cs_real_t diippf[3];
9853
9854 for (int isou = 0; isou < 3; isou++) {
9855 pi[isou] = pvar[ii][isou];
9856 pia[isou] = pvara[ii][isou];
9857 pir[isou] = pi[isou]/relaxp - (1.-relaxp)/relaxp*pia[isou];
9858 }
9859
9860 cs_real_t bldfrp = (cs_real_t) ircflp;
9861 /* Local limitation of the reconstruction */
9862 if (df_limiter != NULL && ircflp > 0)
9863 bldfrp = CS_MAX(df_limiter[ii], 0.);
9864
9865 /* Recompute II"
9866 --------------*/
9867
9868 visci[0][0] = viscce[ii][0];
9869 visci[1][1] = viscce[ii][1];
9870 visci[2][2] = viscce[ii][2];
9871 visci[1][0] = viscce[ii][3];
9872 visci[0][1] = viscce[ii][3];
9873 visci[2][1] = viscce[ii][4];
9874 visci[1][2] = viscce[ii][4];
9875 visci[2][0] = viscce[ii][5];
9876 visci[0][2] = viscce[ii][5];
9877
9878 /* IF.Ki.S / ||Ki.S||^2 */
9879 cs_real_t fikdvi = weighb[face_id];
9880
9881 /* II" = IF + FI" */
9882 for (int i = 0; i < 3; i++) {
9883 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
9884 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
9885 + visci[1][i]*b_face_normal[face_id][1]
9886 + visci[2][i]*b_face_normal[face_id][2] );
9887 }
9888 for (int isou = 0; isou < 3; isou++) {
9889 pippr[isou] = pir[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
9890 + grad[ii][isou][1]*diippf[1]
9891 + grad[ii][isou][2]*diippf[2]);
9892 }
9893 for (int isou = 0; isou < 3; isou++) {
9894 cs_real_t pfacd = inc*cofafv[face_id][isou];
9895 for (int jsou = 0; jsou < 3; jsou++) {
9896 pfacd += cofbfv[face_id][isou][jsou]*pippr[jsou];
9897 }
9898
9899 cs_real_t flux = b_visc[face_id]*pfacd;
9900 rhs[ii][isou] -= flux;
9901
9902 } /* isou */
9903
9904 }
9905 }
9906 }
9907
9908 /* Unsteady */
9909 } else {
9910
9911 for (int g_id = 0; g_id < n_b_groups; g_id++) {
9912 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
9913 for (int t_id = 0; t_id < n_b_threads; t_id++) {
9914 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
9915 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
9916 face_id++) {
9917
9918 cs_lnum_t ii = b_face_cells[face_id];
9919
9920 cs_real_t visci[3][3];
9921 cs_real_t diippf[3], pi[3], pipp[3];
9922
9923 for (int isou = 0; isou < 3; isou++) {
9924 pi[isou] = pvar[ii][isou];
9925 }
9926
9927 cs_real_t bldfrp = (cs_real_t) ircflp;
9928 /* Local limitation of the reconstruction */
9929 if (df_limiter != NULL && ircflp > 0)
9930 bldfrp = CS_MAX(df_limiter[ii], 0.);
9931
9932 /* Recompute II"
9933 --------------*/
9934
9935 visci[0][0] = viscce[ii][0];
9936 visci[1][1] = viscce[ii][1];
9937 visci[2][2] = viscce[ii][2];
9938 visci[1][0] = viscce[ii][3];
9939 visci[0][1] = viscce[ii][3];
9940 visci[2][1] = viscce[ii][4];
9941 visci[1][2] = viscce[ii][4];
9942 visci[2][0] = viscce[ii][5];
9943 visci[0][2] = viscce[ii][5];
9944
9945 /* IF.Ki.S / ||Ki.S||^2 */
9946 cs_real_t fikdvi = weighb[face_id];
9947
9948 /* II" = IF + FI" */
9949 for (int i = 0; i < 3; i++) {
9950 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
9951 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
9952 + visci[1][i]*b_face_normal[face_id][1]
9953 + visci[2][i]*b_face_normal[face_id][2]);
9954 }
9955 for (int isou = 0; isou < 3; isou++) {
9956 pipp[isou] = pi[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
9957 + grad[ii][isou][1]*diippf[1]
9958 + grad[ii][isou][2]*diippf[2]);
9959 }
9960 for (int isou = 0; isou < 3; isou++) {
9961 cs_real_t pfacd = inc*cofafv[face_id][isou];
9962 for (int jsou = 0; jsou < 3; jsou++) {
9963 pfacd += cofbfv[face_id][isou][jsou]*pipp[jsou];
9964 }
9965
9966 cs_real_t flux = b_visc[face_id]*pfacd;
9967 rhs[ii][isou] -= thetap * flux;
9968
9969 } /* isou */
9970
9971 }
9972 }
9973 }
9974
9975 /* The vector is internal_coupled and an implicit contribution
9976 * is required */
9977 if (icoupl > 0) {
9978
9979 /* Exchange pvar */
9980 BFT_MALLOC(pvar_local, n_local, cs_real_3_t);
9981 cs_internal_coupling_exchange_by_cell_id(cpl,
9982 3, /* Dimension */
9983 (const cs_real_t*)_pvar,
9984 (cs_real_t *)pvar_local);
9985
9986 /* Exchange grad */
9987 BFT_MALLOC(grad_local, n_local, cs_real_33_t);
9988 cs_internal_coupling_exchange_by_cell_id(cpl,
9989 9, /* Dimension */
9990 (const cs_real_t*)grad,
9991 (cs_real_t *)grad_local);
9992
9993 /* Exchange viscce */
9994 BFT_MALLOC(viscce_local, n_local, cs_real_6_t);
9995 cs_internal_coupling_exchange_by_cell_id(cpl,
9996 6, /* Dimension */
9997 (const cs_real_t*)viscce,
9998 (cs_real_t *)viscce_local);
9999
10000 /* Exchange weighb */
10001 BFT_MALLOC(weighb_local, n_local, cs_real_t);
10002 cs_internal_coupling_exchange_by_face_id(cpl,
10003 1, /* Dimension */
10004 (const cs_real_t*)weighb,
10005 (cs_real_t *)weighb_local);
10006
10007 /* Exchange diffusion limiter */
10008 if (df_limiter != NULL) {
10009 BFT_MALLOC(df_limiter_local, n_local, cs_real_t);
10010 cs_internal_coupling_exchange_var(cpl,
10011 1, /* Dimension */
10012 df_limiter,
10013 df_limiter_local);
10014 }
10015
10016 /* Flux contribution */
10017 for (cs_lnum_t jj = 0; jj < n_local; jj++) {
10018 cs_lnum_t face_id = faces_local[jj];
10019 cs_lnum_t ii = b_face_cells[face_id];
10020
10021 cs_real_t pipp[3], pjpp[3];
10022 cs_real_t pi[3], pj[3];
10023
10024 for (int isou = 0; isou < 3; isou++) {
10025 pi[isou] = _pvar[ii][isou];
10026 pj[isou] = pvar_local[jj][isou];
10027 }
10028
10029 cs_real_t bldfrp = (cs_real_t) ircflp;
10030 /* Local limitation of the reconstruction */
10031 if (df_limiter != NULL && ircflp > 0)
10032 bldfrp = CS_MAX(CS_MIN(df_limiter_local[ii], df_limiter[jj]), 0.);
10033
10034 /* Recompute II" and JJ" */
10035 cs_real_t visci[3][3], viscj[3][3];
10036 cs_real_t diippf[3], djjppf[3];
10037
10038 visci[0][0] = viscce[ii][0];
10039 visci[1][1] = viscce[ii][1];
10040 visci[2][2] = viscce[ii][2];
10041 visci[1][0] = viscce[ii][3];
10042 visci[0][1] = viscce[ii][3];
10043 visci[2][1] = viscce[ii][4];
10044 visci[1][2] = viscce[ii][4];
10045 visci[2][0] = viscce[ii][5];
10046 visci[0][2] = viscce[ii][5];
10047
10048 /* IF.Ki.S / ||Ki.S||^2 */
10049 cs_real_t fikdvi = weighb[face_id];
10050
10051 /* II" = IF + FI" */
10052 for (int i = 0; i < 3; i++) {
10053 diippf[i] = b_face_cog[face_id][i]-cell_cen[ii][i]
10054 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
10055 + visci[1][i]*b_face_normal[face_id][1]
10056 + visci[2][i]*b_face_normal[face_id][2] );
10057 }
10058
10059 viscj[0][0] = viscce_local[jj][0];
10060 viscj[1][1] = viscce_local[jj][1];
10061 viscj[2][2] = viscce_local[jj][2];
10062 viscj[1][0] = viscce_local[jj][3];
10063 viscj[0][1] = viscce_local[jj][3];
10064 viscj[2][1] = viscce_local[jj][4];
10065 viscj[1][2] = viscce_local[jj][4];
10066 viscj[2][0] = viscce_local[jj][5];
10067 viscj[0][2] = viscce_local[jj][5];
10068
10069 /* FJ.Kj.S / ||Kj.S||^2
10070 * weighb_local defined with vector JF and surface -S */
10071 cs_real_t fjkdvi = weighb_local[jj];
10072
10073 /* JJ" = JF + FJ"
10074 * */
10075 for (int i = 0; i < 3; i++) {
10076 djjppf[i] = b_face_cog[face_id][i]-cell_cen[ii][i]-cpl->ci_cj_vect[jj][i]
10077 + fjkdvi*( viscj[0][i]*b_face_normal[face_id][0]
10078 + viscj[1][i]*b_face_normal[face_id][1]
10079 + viscj[2][i]*b_face_normal[face_id][2] );
10080 }
10081
10082 for (int isou = 0; isou < 3; isou++) {
10083 /* p in I" and J" */
10084 pipp[isou] = pi[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
10085 + grad[ii][isou][1]*diippf[1]
10086 + grad[ii][isou][2]*diippf[2]);
10087 pjpp[isou] = pj[isou] + bldfrp*( grad_local[jj][isou][0]*djjppf[0]
10088 + grad_local[jj][isou][1]*djjppf[1]
10089 + grad_local[jj][isou][2]*djjppf[2]);
10090
10091 /* Reproduce multiplication by i_visc[face_id] */
10092 cs_real_t flux = (pipp[isou] - pjpp[isou])
10093 / (weighb[face_id] + weighb_local[jj]);
10094
10095 rhs[ii][isou] -= thetap*flux;
10096 }
10097
10098 }
10099
10100 /* Remote data no longer needed */
10101 BFT_FREE(pvar_local);
10102 if (df_limiter != NULL)
10103 BFT_FREE(df_limiter_local);
10104 BFT_FREE(grad_local);
10105 BFT_FREE(viscce_local);
10106 BFT_FREE(weighb_local);
10107
10108 }
10109
10110
10111 } /* idtvar */
10112
10113 /* Free memory */
10114 BFT_FREE(grad);
10115 }
10116
10117 /*----------------------------------------------------------------------------*/
10118 /*!
10119 * \brief Add the explicit part of the diffusion terms with a symmetric tensor
10120 * diffusivity for a transport equation of a scalar field \f$ \varia \f$.
10121 *
10122 * More precisely, the right hand side \f$ Rhs \f$ is updated as
10123 * follows:
10124 * \f[
10125 * Rhs = Rhs - \sum_{\fij \in \Facei{\celli}} \left(
10126 * - \tens{\mu}_\fij \gradv_\fij \varia \cdot \vect{S}_\ij \right)
10127 * \f]
10128 *
10129 * Warning:
10130 * - \f$ Rhs \f$ has already been initialized before
10131 * calling cs_anisotropic_diffusion_scalar!
10132 * - mind the sign minus
10133 *
10134 * \param[in] idtvar indicator of the temporal scheme
10135 * \param[in] f_id index of the current variable
10136 * \param[in] var_cal_opt variable calculation options
10137 * \param[in] inc indicator
10138 * - 0 when solving an increment
10139 * - 1 otherwise
10140 * \param[in] pvar solved variable (current time step)
10141 * \param[in] pvara solved variable (previous time step)
10142 * \param[in] coefa boundary condition array for the variable
10143 * (explicit part)
10144 * \param[in] coefb boundary condition array for the variable
10145 * (implicit part)
10146 * \param[in] cofaf boundary condition array for the diffusion
10147 * of the variable (explicit part)
10148 * \param[in] cofbf boundary condition array for the diffusion
10149 * of the variable (implicit part)
10150 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
10151 * at interior faces for the r.h.s.
10152 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
10153 * at border faces for the r.h.s.
10154 * \param[in] viscel symmetric cell tensor \f$ \tens{\mu}_\celli \f$
10155 * \param[in] weighf internal face weight between cells i j in case
10156 * of tensor diffusion
10157 * \param[in] weighb boundary face weight for cells i in case
10158 * of tensor diffusion
10159 * \param[in,out] rhs right hand side \f$ \vect{Rhs} \f$
10160 */
10161 /*----------------------------------------------------------------------------*/
10162
10163 void
cs_anisotropic_diffusion_tensor(int idtvar,int f_id,const cs_var_cal_opt_t var_cal_opt,int inc,cs_real_6_t * restrict pvar,const cs_real_6_t * restrict pvara,const cs_real_6_t coefa[],const cs_real_66_t coefb[],const cs_real_6_t cofaf[],const cs_real_66_t cofbf[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_6_t * restrict viscel,const cs_real_2_t weighf[],const cs_real_t weighb[],cs_real_6_t * restrict rhs)10164 cs_anisotropic_diffusion_tensor(int idtvar,
10165 int f_id,
10166 const cs_var_cal_opt_t var_cal_opt,
10167 int inc,
10168 cs_real_6_t *restrict pvar,
10169 const cs_real_6_t *restrict pvara,
10170 const cs_real_6_t coefa[],
10171 const cs_real_66_t coefb[],
10172 const cs_real_6_t cofaf[],
10173 const cs_real_66_t cofbf[],
10174 const cs_real_t i_visc[],
10175 const cs_real_t b_visc[],
10176 cs_real_6_t *restrict viscel,
10177 const cs_real_2_t weighf[],
10178 const cs_real_t weighb[],
10179 cs_real_6_t *restrict rhs)
10180 {
10181 const int nswrgp = var_cal_opt.nswrgr;
10182 const int imrgra = var_cal_opt.imrgra;
10183 const int imligp = var_cal_opt.imligr;
10184 const int ircflp = var_cal_opt.ircflu;
10185 const int iwarnp = var_cal_opt.verbosity;
10186 const double epsrgp = var_cal_opt.epsrgr;
10187 const double climgp = var_cal_opt.climgr;
10188 const double relaxp = var_cal_opt.relaxv;
10189 const double thetap = var_cal_opt.thetav;
10190
10191 const cs_mesh_t *m = cs_glob_mesh;
10192 const cs_halo_t *halo = m->halo;
10193 cs_mesh_quantities_t *fvq = cs_glob_mesh_quantities;
10194
10195 const cs_lnum_t n_cells = m->n_cells;
10196 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
10197 const int n_i_groups = m->i_face_numbering->n_groups;
10198 const int n_i_threads = m->i_face_numbering->n_threads;
10199 const int n_b_groups = m->b_face_numbering->n_groups;
10200 const int n_b_threads = m->b_face_numbering->n_threads;
10201 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
10202 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
10203
10204 const cs_lnum_2_t *restrict i_face_cells
10205 = (const cs_lnum_2_t *restrict)m->i_face_cells;
10206 const cs_lnum_t *restrict b_face_cells
10207 = (const cs_lnum_t *restrict)m->b_face_cells;
10208 const cs_real_3_t *restrict cell_cen
10209 = (const cs_real_3_t *restrict)fvq->cell_cen;
10210 const cs_real_3_t *restrict i_face_normal
10211 = (const cs_real_3_t *restrict)fvq->i_face_normal;
10212 const cs_real_3_t *restrict b_face_normal
10213 = (const cs_real_3_t *restrict)fvq->b_face_normal;
10214 const cs_real_3_t *restrict i_face_cog
10215 = (const cs_real_3_t *restrict)fvq->i_face_cog;
10216 const cs_real_3_t *restrict b_face_cog
10217 = (const cs_real_3_t *restrict)fvq->b_face_cog;
10218
10219 /* Local variables */
10220
10221 cs_real_t *df_limiter = NULL;
10222
10223 char var_name[64];
10224
10225 cs_real_6_t *viscce;
10226 cs_real_6_t *w2;
10227 cs_real_63_t *grad;
10228
10229 cs_field_t *f;
10230
10231 /* 1. Initialization */
10232
10233 viscce = NULL;
10234 w2 = NULL;
10235
10236 /* Allocate work arrays */
10237 BFT_MALLOC(grad, n_cells_ext, cs_real_63_t);
10238
10239 /* Choose gradient type */
10240 cs_halo_type_t halo_type = CS_HALO_STANDARD;
10241 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
10242
10243 cs_gradient_type_by_imrgra(imrgra,
10244 &gradient_type,
10245 &halo_type);
10246
10247 /* Handle cases where only the previous values (already synchronized)
10248 or current values are provided */
10249
10250 if (pvar != NULL && m->halo != NULL) {
10251 cs_halo_sync_var_strided(m->halo, halo_type, (cs_real_t *)pvar, 6);
10252 if (cs_glob_mesh->n_init_perio > 0)
10253 cs_halo_perio_sync_var_sym_tens(m->halo, halo_type, (cs_real_t *)pvar);
10254 }
10255 if (pvara == NULL)
10256 pvara = (const cs_real_6_t *restrict)pvar;
10257
10258 const cs_real_6_t *restrict _pvar
10259 = (pvar != NULL) ? (const cs_real_6_t *restrict)pvar : pvara;
10260
10261 /* Logging info */
10262
10263 if (f_id != -1) {
10264 f = cs_field_by_id(f_id);
10265
10266 int df_limiter_id
10267 = cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
10268 if (df_limiter_id > -1)
10269 df_limiter = cs_field_by_id(df_limiter_id)->val;
10270
10271 snprintf(var_name, 63, "%s", f->name);
10272 }
10273 else
10274 strncpy(var_name, "[anisotropic diffusion, tensor]", 63);
10275 var_name[63] = '\0';
10276
10277 /* Porosity fields */
10278 cs_field_t *fporo = cs_field_by_name_try("porosity");
10279 cs_field_t *ftporo = cs_field_by_name_try("tensorial_porosity");
10280
10281 cs_real_t *porosi = NULL;
10282 cs_real_6_t *porosf = NULL;
10283
10284 if (cs_glob_porous_model == 1 || cs_glob_porous_model == 2) {
10285 porosi = fporo->val;
10286 if (ftporo != NULL) {
10287 porosf = (cs_real_6_t *)ftporo->val;
10288 }
10289 }
10290
10291 /* Without porosity */
10292 if (porosi == NULL) {
10293 viscce = viscel;
10294
10295 /* With porosity */
10296 } else if (porosi != NULL && porosf == NULL) {
10297 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
10298 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
10299 for (int isou = 0; isou < 6; isou++) {
10300 w2[cell_id][isou] = porosi[cell_id]*viscel[cell_id][isou];
10301 }
10302 }
10303 viscce = w2;
10304
10305 /* With tensorial porosity */
10306 } else if (porosi != NULL && porosf != NULL) {
10307 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
10308 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
10309 cs_math_sym_33_product(porosf[cell_id],
10310 viscel[cell_id],
10311 w2[cell_id]);
10312 }
10313 viscce = w2;
10314 }
10315
10316 /* ---> Periodicity and parallelism treatment of symmetric tensors */
10317 if (halo != NULL) {
10318 cs_halo_sync_var_strided(halo, halo_type, (cs_real_t *)viscce, 6);
10319 if (m->n_init_perio > 0)
10320 cs_halo_perio_sync_var_sym_tens(halo, halo_type, (cs_real_t *)viscce);
10321 }
10322
10323 /* 2. Compute the diffusive part with reconstruction technics */
10324
10325 /* ======================================================================
10326 ---> Compute the gradient of the current variable if needed
10327 ======================================================================*/
10328
10329 if (ircflp == 1) {
10330
10331 cs_gradient_tensor_synced_input(var_name,
10332 gradient_type,
10333 halo_type,
10334 inc,
10335 nswrgp,
10336 iwarnp,
10337 imligp,
10338 epsrgp,
10339 climgp,
10340 coefa,
10341 coefb,
10342 _pvar,
10343 grad);
10344
10345 } else {
10346 # pragma omp parallel for
10347 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++) {
10348 for (int isou = 0; isou < 6; isou++) {
10349 for (int jsou = 0; jsou < 3; jsou++)
10350 grad[cell_id][isou][jsou] = 0.;
10351 }
10352 }
10353 }
10354
10355 /* ======================================================================
10356 ---> Contribution from interior faces
10357 ======================================================================*/
10358
10359 if (n_cells_ext > n_cells) {
10360 # pragma omp parallel for if(n_cells_ext -n_cells > CS_THR_MIN)
10361 for (cs_lnum_t cell_id = n_cells; cell_id < n_cells_ext; cell_id++) {
10362 for (int isou = 0; isou < 6; isou++) {
10363 rhs[cell_id][isou] = 0.;
10364 }
10365 }
10366 }
10367
10368 /* Steady */
10369 if (idtvar < 0) {
10370
10371 for (int g_id = 0; g_id < n_i_groups; g_id++) {
10372 # pragma omp parallel for
10373 for (int t_id = 0; t_id < n_i_threads; t_id++) {
10374 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
10375 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
10376 face_id++) {
10377
10378 cs_lnum_t ii = i_face_cells[face_id][0];
10379 cs_lnum_t jj = i_face_cells[face_id][1];
10380
10381 cs_real_t visci[3][3], viscj[3][3];
10382 cs_real_t diippf[3], djjppf[3], pipp[6], pjpp[6];
10383 cs_real_t pir[6], pjr[6], pippr[6], pjppr[6];
10384 cs_real_t pi[6], pj[6], pia[6], pja[6];
10385
10386 for (int isou = 0; isou < 6; isou++) {
10387 pi[isou] = _pvar[ii][isou];
10388 pj[isou] = _pvar[jj][isou];
10389 pia[isou] = pvara[ii][isou];
10390 pja[isou] = pvara[jj][isou];
10391 }
10392
10393 cs_real_t bldfrp = (cs_real_t) ircflp;
10394 /* Local limitation of the reconstruction */
10395 if (df_limiter != NULL && ircflp > 0)
10396 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
10397
10398
10399 /* Recompute II" and JJ"
10400 ----------------------*/
10401
10402 visci[0][0] = viscce[ii][0];
10403 visci[1][1] = viscce[ii][1];
10404 visci[2][2] = viscce[ii][2];
10405 visci[1][0] = viscce[ii][3];
10406 visci[0][1] = viscce[ii][3];
10407 visci[2][1] = viscce[ii][4];
10408 visci[1][2] = viscce[ii][4];
10409 visci[2][0] = viscce[ii][5];
10410 visci[0][2] = viscce[ii][5];
10411
10412 /* IF.Ki.S / ||Ki.S||^2 */
10413 cs_real_t fikdvi = weighf[face_id][0];
10414
10415 /* II" = IF + FI" */
10416 for (int i = 0; i < 3; i++) {
10417 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
10418 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
10419 + visci[1][i]*i_face_normal[face_id][1]
10420 + visci[2][i]*i_face_normal[face_id][2] );
10421 }
10422
10423 viscj[0][0] = viscce[jj][0];
10424 viscj[1][1] = viscce[jj][1];
10425 viscj[2][2] = viscce[jj][2];
10426 viscj[1][0] = viscce[jj][3];
10427 viscj[0][1] = viscce[jj][3];
10428 viscj[2][1] = viscce[jj][4];
10429 viscj[1][2] = viscce[jj][4];
10430 viscj[2][0] = viscce[jj][5];
10431 viscj[0][2] = viscce[jj][5];
10432
10433 /* FJ.Kj.S / ||Kj.S||^2 */
10434 cs_real_t fjkdvi = weighf[face_id][1];
10435
10436 /* JJ" = JF + FJ" */
10437 for (int i = 0; i < 3; i++) {
10438 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
10439 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
10440 + viscj[1][i]*i_face_normal[face_id][1]
10441 + viscj[2][i]*i_face_normal[face_id][2] );
10442 }
10443
10444 for (int isou = 0; isou < 6; isou++) {
10445 /* p in I" and J" */
10446 pipp[isou] = pi[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
10447 + grad[ii][isou][1]*diippf[1]
10448 + grad[ii][isou][2]*diippf[2]);
10449 pjpp[isou] = pj[isou] + bldfrp*( grad[jj][isou][0]*djjppf[0]
10450 + grad[jj][isou][1]*djjppf[1]
10451 + grad[jj][isou][2]*djjppf[2]);
10452
10453 pir[isou] = pi[isou]/relaxp - (1.-relaxp)/relaxp * pia[isou];
10454 pjr[isou] = pj[isou]/relaxp - (1.-relaxp)/relaxp * pja[isou];
10455
10456
10457 /* pr in I" and J" */
10458 pippr[isou] = pir[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
10459 + grad[ii][isou][1]*diippf[1]
10460 + grad[ii][isou][2]*diippf[2]);
10461 pjppr[isou] = pjr[isou] + bldfrp*( grad[jj][isou][0]*djjppf[0]
10462 + grad[jj][isou][1]*djjppf[1]
10463 + grad[jj][isou][2]*djjppf[2]);
10464
10465
10466 cs_real_t fluxi = i_visc[face_id]*(pippr[isou] - pjpp[isou]);
10467 cs_real_t fluxj = i_visc[face_id]*(pipp[isou] - pjppr[isou]);
10468
10469 rhs[ii][isou] -= fluxi;
10470 rhs[jj][isou] += fluxj;
10471 } // loop on isou
10472 }
10473 }
10474 }
10475
10476 /* Unsteady */
10477 } else {
10478
10479 for (int g_id = 0; g_id < n_i_groups; g_id++) {
10480 # pragma omp parallel for
10481 for (int t_id = 0; t_id < n_i_threads; t_id++) {
10482 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
10483 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
10484 face_id++) {
10485
10486 cs_lnum_t ii = i_face_cells[face_id][0];
10487 cs_lnum_t jj = i_face_cells[face_id][1];
10488
10489 cs_real_t visci[3][3], viscj[3][3];
10490 cs_real_t diippf[3], djjppf[3], pipp[6], pjpp[6];
10491 cs_real_t pi[6], pj[6];
10492
10493 for (int isou = 0; isou < 6; isou++) {
10494 pi[isou] = _pvar[ii][isou];
10495 pj[isou] = _pvar[jj][isou];
10496 }
10497
10498 cs_real_t bldfrp = (cs_real_t) ircflp;
10499 /* Local limitation of the reconstruction */
10500 if (df_limiter != NULL && ircflp > 0)
10501 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
10502
10503 /* Recompute II" and JJ"
10504 ----------------------*/
10505
10506 visci[0][0] = viscce[ii][0];
10507 visci[1][1] = viscce[ii][1];
10508 visci[2][2] = viscce[ii][2];
10509 visci[1][0] = viscce[ii][3];
10510 visci[0][1] = viscce[ii][3];
10511 visci[2][1] = viscce[ii][4];
10512 visci[1][2] = viscce[ii][4];
10513 visci[2][0] = viscce[ii][5];
10514 visci[0][2] = viscce[ii][5];
10515
10516 /* IF.Ki.S / ||Ki.S||^2 */
10517 cs_real_t fikdvi = weighf[face_id][0];
10518
10519 /* II" = IF + FI" */
10520 for (int i = 0; i < 3; i++) {
10521 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
10522 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
10523 + visci[1][i]*i_face_normal[face_id][1]
10524 + visci[2][i]*i_face_normal[face_id][2] );
10525 }
10526
10527 viscj[0][0] = viscce[jj][0];
10528 viscj[1][1] = viscce[jj][1];
10529 viscj[2][2] = viscce[jj][2];
10530 viscj[1][0] = viscce[jj][3];
10531 viscj[0][1] = viscce[jj][3];
10532 viscj[2][1] = viscce[jj][4];
10533 viscj[1][2] = viscce[jj][4];
10534 viscj[2][0] = viscce[jj][5];
10535 viscj[0][2] = viscce[jj][5];
10536
10537 /* FJ.Kj.S / ||Kj.S||^2 */
10538 cs_real_t fjkdvi = weighf[face_id][1];
10539
10540 /* JJ" = JF + FJ" */
10541 for (int i = 0; i < 3; i++) {
10542 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
10543 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
10544 + viscj[1][i]*i_face_normal[face_id][1]
10545 + viscj[2][i]*i_face_normal[face_id][2] );
10546 }
10547
10548 for (int isou = 0; isou < 6; isou++) {
10549 /* p in I" and J" */
10550 pipp[isou] = pi[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
10551 + grad[ii][isou][1]*diippf[1]
10552 + grad[ii][isou][2]*diippf[2]);
10553 pjpp[isou] = pj[isou] + bldfrp*( grad[jj][isou][0]*djjppf[0]
10554 + grad[jj][isou][1]*djjppf[1]
10555 + grad[jj][isou][2]*djjppf[2]);
10556
10557 cs_real_t flux = i_visc[face_id]*(pipp[isou] -pjpp[isou]);
10558
10559 rhs[ii][isou] -= thetap*flux;
10560 rhs[jj][isou] += thetap*flux;
10561 }
10562 }
10563 }
10564 }
10565 }
10566
10567 /* ======================================================================
10568 ---> Contribution from boundary faces
10569 ======================================================================*/
10570
10571 /* Steady */
10572 if (idtvar < 0) {
10573
10574 for (int g_id = 0; g_id < n_b_groups; g_id++) {
10575 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
10576 for (int t_id = 0; t_id < n_b_threads; t_id++) {
10577 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
10578 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
10579 face_id++) {
10580
10581 cs_lnum_t ii = b_face_cells[face_id];
10582
10583 cs_real_t pi[6], pia[6], pir[6], pippr[6];
10584 cs_real_t visci[3][3];
10585 cs_real_t diippf[3];
10586
10587 for (int isou = 0; isou < 6; isou++) {
10588 pi[isou] = _pvar[ii][isou];
10589 pia[isou] = pvara[ii][isou];
10590 pir[isou] = pi[isou]/relaxp - (1.-relaxp)/relaxp*pia[isou];
10591 }
10592
10593 cs_real_t bldfrp = (cs_real_t) ircflp;
10594 /* Local limitation of the reconstruction */
10595 if (df_limiter != NULL && ircflp > 0)
10596 bldfrp = CS_MAX(df_limiter[ii], 0.);
10597
10598 /* Recompute II"
10599 --------------*/
10600
10601 visci[0][0] = viscce[ii][0];
10602 visci[1][1] = viscce[ii][1];
10603 visci[2][2] = viscce[ii][2];
10604 visci[1][0] = viscce[ii][3];
10605 visci[0][1] = viscce[ii][3];
10606 visci[2][1] = viscce[ii][4];
10607 visci[1][2] = viscce[ii][4];
10608 visci[2][0] = viscce[ii][5];
10609 visci[0][2] = viscce[ii][5];
10610
10611 /* IF.Ki.S / ||Ki.S||^2 */
10612 cs_real_t fikdvi = weighb[face_id];
10613
10614 /* II" = IF + FI" */
10615 for (int i = 0; i < 3; i++) {
10616 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
10617 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
10618 + visci[1][i]*b_face_normal[face_id][1]
10619 + visci[2][i]*b_face_normal[face_id][2] );
10620 }
10621 for (int isou = 0; isou < 6; isou++) {
10622 pippr[isou] = pir[isou] + bldfrp*( grad[ii][isou][0]*diippf[0]
10623 + grad[ii][isou][1]*diippf[1]
10624 + grad[ii][isou][2]*diippf[2]);
10625 }
10626 for (int isou = 0; isou < 6; isou++) {
10627 cs_real_t pfacd = inc*cofaf[face_id][isou];
10628 for (int jsou = 0; jsou < 6; jsou++) {
10629 pfacd += cofbf[face_id][isou][jsou]*pippr[jsou];
10630 }
10631
10632 cs_real_t flux = b_visc[face_id]*pfacd;
10633 rhs[ii][isou] -= flux;
10634 }
10635 }
10636 }
10637 }
10638
10639 /* Unsteady */
10640 } else {
10641
10642 for (int g_id = 0; g_id < n_b_groups; g_id++) {
10643 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
10644 for (int t_id = 0; t_id < n_b_threads; t_id++) {
10645 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
10646 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
10647 face_id++) {
10648
10649 cs_lnum_t ii = b_face_cells[face_id];
10650
10651 cs_real_t visci[3][3];
10652 cs_real_t diippf[3], pi[6], pipp[6];
10653
10654 for (int isou = 0; isou < 6; isou++) {
10655 pi[isou] = _pvar[ii][isou];
10656 }
10657
10658 cs_real_t bldfrp = (cs_real_t) ircflp;
10659 /* Local limitation of the reconstruction */
10660 if (df_limiter != NULL && ircflp > 0)
10661 bldfrp = CS_MAX(df_limiter[ii], 0.);
10662
10663
10664 /* Recompute II"
10665 --------------*/
10666
10667 visci[0][0] = viscce[ii][0];
10668 visci[1][1] = viscce[ii][1];
10669 visci[2][2] = viscce[ii][2];
10670 visci[1][0] = viscce[ii][3];
10671 visci[0][1] = viscce[ii][3];
10672 visci[2][1] = viscce[ii][4];
10673 visci[1][2] = viscce[ii][4];
10674 visci[2][0] = viscce[ii][5];
10675 visci[0][2] = viscce[ii][5];
10676
10677 /* IF.Ki.S / ||Ki.S||^2 */
10678 cs_real_t fikdvi = weighb[face_id];
10679
10680 /* II" = IF + FI" */
10681 for (int i = 0; i < 3; i++) {
10682 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
10683 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
10684 + visci[1][i]*b_face_normal[face_id][1]
10685 + visci[2][i]*b_face_normal[face_id][2]);
10686 }
10687 for (int isou = 0; isou < 6; isou++) {
10688 pipp[isou] = pi[isou] + bldfrp * ( grad[ii][isou][0]*diippf[0]
10689 + grad[ii][isou][1]*diippf[1]
10690 + grad[ii][isou][2]*diippf[2]);
10691 }
10692 for (int isou = 0; isou < 6; isou++) {
10693 cs_real_t pfacd = inc*cofaf[face_id][isou];
10694 for (int jsou = 0; jsou < 6; jsou++) {
10695 pfacd += cofbf[face_id][isou][jsou]*pipp[jsou];
10696 }
10697
10698 cs_real_t flux = b_visc[face_id]*pfacd;
10699 rhs[ii][isou] -= thetap*flux;
10700 }
10701
10702 }
10703 }
10704 }
10705
10706 }
10707
10708 /* Free memory */
10709 BFT_FREE(grad);
10710 BFT_FREE(w2);
10711 }
10712
10713 /*----------------------------------------------------------------------------*/
10714 /*!
10715 * \brief Update the face mass flux with the face pressure (or pressure
10716 * increment, or pressure double increment) gradient.
10717 *
10718 * <a name="itrmas"></a>
10719 *
10720 * \f[
10721 * \dot{m}_\ij = \dot{m}_\ij
10722 * - \Delta t \grad_\fij \delta p \cdot \vect{S}_\ij
10723 * \f]
10724 *
10725 * Please refer to the
10726 * <a href="../../theory.pdf#itrmas"><b>itrmas/itrgrp</b></a> section of the
10727 * theory guide for more information.
10728 *
10729 * \param[in] f_id field id (or -1)
10730 * \param[in] m pointer to mesh
10731 * \param[in] fvq pointer to finite volume quantities
10732 * \param[in] init indicator
10733 * - 1 initialize the mass flux to 0
10734 * - 0 otherwise
10735 * \param[in] inc indicator
10736 * - 0 when solving an increment
10737 * - 1 otherwise
10738 * \param[in] imrgra indicator
10739 * - 0 iterative gradient
10740 * - 1 least squares gradient
10741 * \param[in] iccocg indicator
10742 * - 1 re-compute cocg matrix
10743 * (for iterative gradients)
10744 * - 0 otherwise
10745 * \param[in] nswrgp number of reconstruction sweeps for the
10746 * gradients
10747 * \param[in] imligp clipping gradient method
10748 * - < 0 no clipping
10749 * - = 0 thank to neighbooring gradients
10750 * - = 1 thank to the mean gradient
10751 * \param[in] iphydp hydrostatic pressure indicator
10752 * \param[in] iwgrp indicator
10753 * - 1 weight gradient by vicosity*porosity
10754 * - weighting determined by field options
10755 * \param[in] iwarnp verbosity
10756 * \param[in] epsrgp relative precision for the gradient
10757 * reconstruction
10758 * \param[in] climgp clipping coeffecient for the computation of
10759 * the gradient
10760 * \param[in] frcxt body force creating the hydrostatic pressure
10761 * \param[in] pvar solved variable (current time step)
10762 * \param[in] coefap boundary condition array for the variable
10763 * (explicit part)
10764 * \param[in] coefbp boundary condition array for the variable
10765 * (implicit part)
10766 * \param[in] cofafp boundary condition array for the diffusion
10767 * of the variable (explicit part)
10768 * \param[in] cofbfp boundary condition array for the diffusion
10769 * of the variable (implicit part)
10770 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
10771 * at interior faces for the r.h.s.
10772 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
10773 * at border faces for the r.h.s.
10774 * \param[in] visel viscosity by cell
10775 * \param[in,out] i_massflux mass flux at interior faces
10776 * \param[in,out] b_massflux mass flux at boundary faces
10777 */
10778 /*----------------------------------------------------------------------------*/
10779
10780 void
cs_face_diffusion_potential(const int f_id,const cs_mesh_t * m,cs_mesh_quantities_t * fvq,int init,int inc,int imrgra,int iccocg,int nswrgp,int imligp,int iphydp,int iwgrp,int iwarnp,double epsrgp,double climgp,cs_real_3_t * restrict frcxt,cs_real_t * restrict pvar,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_t * restrict visel,cs_real_t * restrict i_massflux,cs_real_t * restrict b_massflux)10781 cs_face_diffusion_potential(const int f_id,
10782 const cs_mesh_t *m,
10783 cs_mesh_quantities_t *fvq,
10784 int init,
10785 int inc,
10786 int imrgra,
10787 int iccocg,
10788 int nswrgp,
10789 int imligp,
10790 int iphydp,
10791 int iwgrp,
10792 int iwarnp,
10793 double epsrgp,
10794 double climgp,
10795 cs_real_3_t *restrict frcxt,
10796 cs_real_t *restrict pvar,
10797 const cs_real_t coefap[],
10798 const cs_real_t coefbp[],
10799 const cs_real_t cofafp[],
10800 const cs_real_t cofbfp[],
10801 const cs_real_t i_visc[],
10802 const cs_real_t b_visc[],
10803 cs_real_t *restrict visel,
10804 cs_real_t *restrict i_massflux,
10805 cs_real_t *restrict b_massflux)
10806 {
10807 const cs_halo_t *halo = m->halo;
10808
10809 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
10810 const int n_i_groups = m->i_face_numbering->n_groups;
10811 const int n_i_threads = m->i_face_numbering->n_threads;
10812 const int n_b_groups = m->b_face_numbering->n_groups;
10813 const int n_b_threads = m->b_face_numbering->n_threads;
10814 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
10815 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
10816 const cs_lnum_2_t *restrict i_face_cells
10817 = (const cs_lnum_2_t *restrict)m->i_face_cells;
10818 const cs_lnum_t *restrict b_face_cells
10819 = (const cs_lnum_t *restrict)m->b_face_cells;
10820 const cs_real_t *restrict i_dist = fvq->i_dist;
10821 const cs_real_t *restrict i_f_face_surf = fvq->i_f_face_surf;
10822 const cs_real_3_t *restrict diipf
10823 = (const cs_real_3_t *restrict)fvq->diipf;
10824 const cs_real_3_t *restrict djjpf
10825 = (const cs_real_3_t *restrict)fvq->djjpf;
10826 const cs_real_3_t *restrict diipb
10827 = (const cs_real_3_t *restrict)fvq->diipb;
10828
10829 /* Local variables */
10830
10831 char var_name[64];
10832 int w_stride = 1;
10833
10834 bool recompute_cocg = (iccocg) ? true : false;
10835
10836 cs_real_3_t *grad;
10837 cs_field_t *f;
10838
10839 cs_real_t *gweight = NULL;
10840
10841 /*==========================================================================*/
10842
10843 /* i_visc and carry similar information */
10844
10845 /*============================================================================
10846 1. Initialization
10847 ==========================================================================*/
10848
10849 if (init >= 1) {
10850 # pragma omp parallel for
10851 for (cs_lnum_t face_id = 0; face_id < m->n_i_faces; face_id++) {
10852 i_massflux[face_id] = 0.;
10853 }
10854 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
10855 for (cs_lnum_t face_id = 0; face_id < m->n_b_faces; face_id++) {
10856 b_massflux[face_id] = 0.;
10857 }
10858 } else if (init != 0) {
10859 bft_error(__FILE__, __LINE__, 0,
10860 _("invalid value of init"));
10861 }
10862
10863 /* Use iterative gradient */
10864
10865 cs_halo_type_t halo_type = CS_HALO_STANDARD;
10866 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
10867
10868 if (imrgra < 0)
10869 imrgra = 0;
10870
10871 cs_gradient_type_by_imrgra(imrgra,
10872 &gradient_type,
10873 &halo_type);
10874
10875 if (f_id > -1) {
10876 f = cs_field_by_id(f_id);
10877 snprintf(var_name, 63, "%s", f->name);
10878 }
10879 else
10880 strncpy(var_name, "[face mass flux update]", 63);
10881 var_name[63] = '\0';
10882
10883 /* Handle parallelism and periodicity */
10884
10885 if (halo != NULL)
10886 cs_halo_sync_var(halo, halo_type, pvar);
10887
10888 /*==========================================================================
10889 2. Update mass flux without reconstruction technics
10890 ==========================================================================*/
10891
10892 if (nswrgp <= 1) {
10893
10894 /* Mass flow through interior faces */
10895
10896 for (int g_id = 0; g_id < n_i_groups; g_id++) {
10897 # pragma omp parallel for
10898 for (int t_id = 0; t_id < n_i_threads; t_id++) {
10899 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
10900 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
10901 face_id++) {
10902
10903 cs_lnum_t ii = i_face_cells[face_id][0];
10904 cs_lnum_t jj = i_face_cells[face_id][1];
10905
10906 i_massflux[face_id] += i_visc[face_id]*(pvar[ii] - pvar[jj]);
10907
10908 }
10909 }
10910 }
10911
10912 /* Mass flow through boundary faces */
10913
10914 for (int g_id = 0; g_id < n_b_groups; g_id++) {
10915 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
10916 for (int t_id = 0; t_id < n_b_threads; t_id++) {
10917 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
10918 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
10919 face_id++) {
10920
10921 cs_lnum_t ii = b_face_cells[face_id];
10922 double pfac = inc*cofafp[face_id] + cofbfp[face_id]*pvar[ii];
10923
10924 b_massflux[face_id] += b_visc[face_id]*pfac;
10925
10926 }
10927 }
10928 }
10929
10930 }
10931
10932 /*==========================================================================
10933 3. Update mass flux with reconstruction technique if the mesh is non
10934 orthogonal
10935 ==========================================================================*/
10936
10937 if (nswrgp > 1) {
10938
10939 /* Allocate a work array for the gradient calculation */
10940 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
10941
10942 /* Compute gradient */
10943 if (iwgrp > 0) {
10944 gweight = visel;
10945 if (halo != NULL)
10946 cs_halo_sync_var(halo, halo_type, gweight);
10947 }
10948
10949 else if (f_id > -1) {
10950 /* Get the calculation option from the field */
10951 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
10952 cs_var_cal_opt_t var_cal_opt;
10953 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
10954 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
10955 if (var_cal_opt.idiff > 0) {
10956 int key_id = cs_field_key_id("gradient_weighting_id");
10957 int diff_id = cs_field_get_key_int(f, key_id);
10958 if (diff_id > -1) {
10959 cs_field_t *weight_f = cs_field_by_id(diff_id);
10960 gweight = weight_f->val;
10961 w_stride = weight_f->dim;
10962 cs_field_synchronize(weight_f, halo_type);
10963 }
10964 }
10965 }
10966 }
10967
10968 cs_gradient_scalar_synced_input(var_name,
10969 gradient_type,
10970 halo_type,
10971 inc,
10972 recompute_cocg,
10973 nswrgp,
10974 iphydp,
10975 w_stride,
10976 iwarnp,
10977 imligp,
10978 epsrgp,
10979 climgp,
10980 frcxt,
10981 coefap,
10982 coefbp,
10983 (const cs_real_t *)pvar,
10984 gweight, /* Weighted gradient */
10985 NULL, /* internal coupling */
10986 grad);
10987
10988 /* Handle parallelism and periodicity */
10989
10990 if (halo != NULL)
10991 cs_halo_sync_var(halo, halo_type, visel);
10992
10993 /* Mass flow through interior faces */
10994
10995 for (int g_id = 0; g_id < n_i_groups; g_id++) {
10996 # pragma omp parallel for
10997 for (int t_id = 0; t_id < n_i_threads; t_id++) {
10998 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
10999 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
11000 face_id++) {
11001
11002 cs_lnum_t ii = i_face_cells[face_id][0];
11003 cs_lnum_t jj = i_face_cells[face_id][1];
11004
11005 double dpxf = 0.5*( visel[ii]*grad[ii][0]
11006 + visel[jj]*grad[jj][0]);
11007 double dpyf = 0.5*( visel[ii]*grad[ii][1]
11008 + visel[jj]*grad[jj][1]);
11009 double dpzf = 0.5*( visel[ii]*grad[ii][2]
11010 + visel[jj]*grad[jj][2]);
11011
11012 /*---> Dij = IJ - (IJ.N) N = II' - JJ' */
11013 double dijx = diipf[face_id][0] - djjpf[face_id][0];
11014 double dijy = diipf[face_id][1] - djjpf[face_id][1];
11015 double dijz = diipf[face_id][2] - djjpf[face_id][2];
11016
11017 i_massflux[face_id] = i_massflux[face_id]
11018 + i_visc[face_id]*(pvar[ii] - pvar[jj])
11019 + (dpxf *dijx + dpyf*dijy + dpzf*dijz)
11020 * i_f_face_surf[face_id]/i_dist[face_id];
11021
11022 }
11023 }
11024 }
11025
11026 /* Mass flow through boundary faces */
11027
11028 for (int g_id = 0; g_id < n_b_groups; g_id++) {
11029 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
11030 for (int t_id = 0; t_id < n_b_threads; t_id++) {
11031 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
11032 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
11033 face_id++) {
11034
11035 cs_lnum_t ii = b_face_cells[face_id];
11036
11037 double diipbx = diipb[face_id][0];
11038 double diipby = diipb[face_id][1];
11039 double diipbz = diipb[face_id][2];
11040
11041 double pip = pvar[ii] + grad[ii][0]*diipbx
11042 + grad[ii][1]*diipby
11043 + grad[ii][2]*diipbz;
11044 double pfac = inc*cofafp[face_id] + cofbfp[face_id]*pip;
11045
11046 b_massflux[face_id] += b_visc[face_id]*pfac;
11047
11048 }
11049 }
11050 }
11051
11052 /* Free memory */
11053 BFT_FREE(grad);
11054 }
11055 }
11056
11057 /*----------------------------------------------------------------------------*/
11058 /*!
11059 * \brief Add the explicit part of the pressure gradient term to the mass flux
11060 * in case of anisotropic diffusion of the pressure field \f$ P \f$.
11061 *
11062 * More precisely, the mass flux side \f$ \dot{m}_\fij \f$ is updated as
11063 * follows:
11064 * \f[
11065 * \dot{m}_\fij = \dot{m}_\fij -
11066 * \left( \tens{\mu}_\fij \gradv_\fij P \cdot \vect{S}_\ij \right)
11067 * \f]
11068 *
11069 * \param[in] f_id field id (or -1)
11070 * \param[in] m pointer to mesh
11071 * \param[in] fvq pointer to finite volume quantities
11072 * \param[in] init indicator
11073 * - 1 initialize the mass flux to 0
11074 * - 0 otherwise
11075 * \param[in] inc indicator
11076 * - 0 when solving an increment
11077 * - 1 otherwise
11078 * \param[in] imrgra indicator
11079 * - 0 iterative gradient
11080 * - 1 least squares gradient
11081 * \param[in] iccocg indicator
11082 * - 1 re-compute cocg matrix
11083 (for iterativ gradients)
11084 * - 0 otherwise
11085 * \param[in] nswrgp number of reconstruction sweeps for the
11086 * gradients
11087 * \param[in] imligp clipping gradient method
11088 * - < 0 no clipping
11089 * - = 0 thank to neighbooring gradients
11090 * - = 1 thank to the mean gradient
11091 * \param[in] ircflp indicator
11092 * - 1 flux reconstruction,
11093 * - 0 otherwise
11094 * \param[in] iphydp indicator
11095 * - 1 hydrostatic pressure taken into account
11096 * - 0 otherwise
11097 * \param[in] iwgrp indicator
11098 * - 1 weight gradient by vicosity*porosity
11099 * - weighting determined by field options
11100 * \param[in] iwarnp verbosity
11101 * \param[in] epsrgp relative precision for the gradient
11102 * reconstruction
11103 * \param[in] climgp clipping coeffecient for the computation of
11104 * the gradient
11105 * \param[in] frcxt body force creating the hydrostatic pressure
11106 * \param[in] pvar solved variable (pressure)
11107 * \param[in] coefap boundary condition array for the variable
11108 * (explicit part)
11109 * \param[in] coefbp boundary condition array for the variable
11110 * (implicit part)
11111 * \param[in] cofafp boundary condition array for the diffusion
11112 * of the variable (explicit part)
11113 * \param[in] cofbfp boundary condition array for the diffusion
11114 * of the variable (implicit part)
11115 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
11116 * at interior faces for the r.h.s.
11117 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
11118 * at border faces for the r.h.s.
11119 * \param[in] viscel symmetric cell tensor \f$ \tens{\mu}_\celli \f$
11120 * \param[in] weighf internal face weight between cells i j in case
11121 * of tensor diffusion
11122 * \param[in] weighb boundary face weight for cells i in case
11123 * of tensor diffusion
11124 * \param[in,out] i_massflux mass flux at interior faces
11125 * \param[in,out] b_massflux mass flux at boundary faces
11126 */
11127 /*----------------------------------------------------------------------------*/
11128
11129 void
cs_face_anisotropic_diffusion_potential(const int f_id,const cs_mesh_t * m,cs_mesh_quantities_t * fvq,int init,int inc,int imrgra,int iccocg,int nswrgp,int imligp,int ircflp,int iphydp,int iwgrp,int iwarnp,double epsrgp,double climgp,cs_real_3_t * restrict frcxt,cs_real_t * restrict pvar,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_6_t * restrict viscel,const cs_real_2_t weighf[],const cs_real_t weighb[],cs_real_t * restrict i_massflux,cs_real_t * restrict b_massflux)11130 cs_face_anisotropic_diffusion_potential(const int f_id,
11131 const cs_mesh_t *m,
11132 cs_mesh_quantities_t *fvq,
11133 int init,
11134 int inc,
11135 int imrgra,
11136 int iccocg,
11137 int nswrgp,
11138 int imligp,
11139 int ircflp,
11140 int iphydp,
11141 int iwgrp,
11142 int iwarnp,
11143 double epsrgp,
11144 double climgp,
11145 cs_real_3_t *restrict frcxt,
11146 cs_real_t *restrict pvar,
11147 const cs_real_t coefap[],
11148 const cs_real_t coefbp[],
11149 const cs_real_t cofafp[],
11150 const cs_real_t cofbfp[],
11151 const cs_real_t i_visc[],
11152 const cs_real_t b_visc[],
11153 cs_real_6_t *restrict viscel,
11154 const cs_real_2_t weighf[],
11155 const cs_real_t weighb[],
11156 cs_real_t *restrict i_massflux,
11157 cs_real_t *restrict b_massflux)
11158 {
11159 const cs_halo_t *halo = m->halo;
11160
11161 const cs_lnum_t n_cells = m->n_cells;
11162 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
11163
11164 const int n_i_groups = m->i_face_numbering->n_groups;
11165 const int n_i_threads = m->i_face_numbering->n_threads;
11166 const int n_b_groups = m->b_face_numbering->n_groups;
11167 const int n_b_threads = m->b_face_numbering->n_threads;
11168 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
11169 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
11170
11171 const cs_lnum_2_t *restrict i_face_cells
11172 = (const cs_lnum_2_t *restrict)m->i_face_cells;
11173 const cs_lnum_t *restrict b_face_cells
11174 = (const cs_lnum_t *restrict)m->b_face_cells;
11175 const cs_real_3_t *restrict cell_cen
11176 = (const cs_real_3_t *restrict)fvq->cell_cen;
11177 const cs_real_3_t *restrict i_face_normal
11178 = (const cs_real_3_t *restrict)fvq->i_face_normal;
11179 const cs_real_3_t *restrict b_face_normal
11180 = (const cs_real_3_t *restrict)fvq->b_face_normal;
11181 const cs_real_3_t *restrict i_face_cog
11182 = (const cs_real_3_t *restrict)fvq->i_face_cog;
11183 const cs_real_3_t *restrict b_face_cog
11184 = (const cs_real_3_t *restrict)fvq->b_face_cog;
11185
11186 /* Local variables */
11187
11188 cs_real_t *df_limiter = NULL;
11189
11190 char var_name[64];
11191 int w_stride = 6;
11192
11193 bool recompute_cocg = (iccocg) ? true : false;
11194
11195 cs_real_6_t *viscce;
11196 cs_real_6_t *w2;
11197 cs_real_3_t *grad;
11198 cs_field_t *f = NULL;
11199
11200 cs_real_t *gweight = NULL;
11201
11202 /*==========================================================================
11203 1. Initialization
11204 ==========================================================================*/
11205
11206 if (init >= 1) {
11207 #pragma omp parallel for
11208 for (cs_lnum_t face_id = 0; face_id < m->n_i_faces; face_id++) {
11209 i_massflux[face_id] = 0.;
11210 }
11211 for (cs_lnum_t face_id = 0; face_id < m->n_b_faces; face_id++) {
11212 b_massflux[face_id] = 0.;
11213 }
11214 } else if (init != 0) {
11215 bft_error(__FILE__, __LINE__, 0,
11216 _("invalid value of init"));
11217 }
11218
11219 /* Use iterative gradient */
11220
11221 cs_halo_type_t halo_type = CS_HALO_STANDARD;
11222 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
11223
11224 if (imrgra < 0)
11225 imrgra = 0;
11226
11227 cs_gradient_type_by_imrgra(imrgra,
11228 &gradient_type,
11229 &halo_type);
11230
11231 if (f_id > -1) {
11232 f = cs_field_by_id(f_id);
11233
11234 int df_limiter_id =
11235 cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
11236 if (df_limiter_id > -1)
11237 df_limiter = cs_field_by_id(df_limiter_id)->val;
11238
11239 snprintf(var_name, 63, "%s", f->name);
11240 }
11241 else
11242 strncpy(var_name, "[face mass flux update]", 63);
11243 var_name[63] = '\0';
11244
11245 /* Porosity fields */
11246 cs_field_t *fporo = cs_field_by_name_try("porosity");
11247 cs_field_t *ftporo = cs_field_by_name_try("tensorial_porosity");
11248
11249 cs_real_t *porosi = NULL;
11250 cs_real_6_t *porosf = NULL;
11251
11252 if (cs_glob_porous_model == 1 || cs_glob_porous_model == 2) {
11253 porosi = fporo->val;
11254 if (ftporo != NULL) {
11255 porosf = (cs_real_6_t *)ftporo->val;
11256 }
11257 }
11258
11259 /* Handle parallelism and periodicity */
11260
11261 if (halo != NULL)
11262 cs_halo_sync_var(halo, halo_type, pvar);
11263
11264 /*==========================================================================
11265 2. Update mass flux without reconstruction technique
11266 ==========================================================================*/
11267
11268 if (nswrgp <= 1) {
11269
11270 /* ---> Contribution from interior faces */
11271
11272 for (int g_id = 0; g_id < n_i_groups; g_id++) {
11273 # pragma omp parallel for
11274 for (int t_id = 0; t_id < n_i_threads; t_id++) {
11275 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
11276 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
11277 face_id++) {
11278
11279 cs_lnum_t ii = i_face_cells[face_id][0];
11280 cs_lnum_t jj = i_face_cells[face_id][1];
11281
11282 i_massflux[face_id] += i_visc[face_id]*(pvar[ii] - pvar[jj]);
11283
11284 }
11285 }
11286 }
11287
11288 /* ---> Contribution from boundary faces */
11289
11290 for (int g_id = 0; g_id < n_b_groups; g_id++) {
11291 # pragma omp parallel for
11292 for (int t_id = 0; t_id < n_b_threads; t_id++) {
11293 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
11294 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
11295 face_id++) {
11296
11297 cs_lnum_t ii = b_face_cells[face_id];
11298 double pfac = inc*cofafp[face_id] + cofbfp[face_id]*pvar[ii];
11299
11300 b_massflux[face_id] += b_visc[face_id]*pfac;
11301
11302 }
11303 }
11304 }
11305
11306 }
11307
11308 /*==========================================================================
11309 3. Update mass flux with reconstruction technique
11310 ==========================================================================*/
11311
11312 if (nswrgp > 1) {
11313
11314 viscce = NULL;
11315 w2 = NULL;
11316
11317 /* Without porosity */
11318 if (porosi == NULL) {
11319 viscce = viscel;
11320
11321 /* With porosity */
11322 } else if (porosi != NULL && porosf == NULL) {
11323 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
11324 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
11325 for (int isou = 0; isou < 6; isou++) {
11326 w2[cell_id][isou] = porosi[cell_id]*viscel[cell_id][isou];
11327 }
11328 }
11329 viscce = w2;
11330
11331 /* With tensorial porosity */
11332 } else if (porosi != NULL && porosf != NULL) {
11333 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
11334 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
11335 cs_math_sym_33_product(porosf[cell_id],
11336 viscel[cell_id],
11337 w2[cell_id]);
11338 }
11339 viscce = w2;
11340 }
11341
11342 /* ---> Periodicity and parallelism treatment of symmetric tensors */
11343
11344 if (halo != NULL) {
11345 cs_halo_sync_var_strided(halo, CS_HALO_STANDARD, (cs_real_t *)viscce, 6);
11346
11347 if (m->n_init_perio > 0)
11348 cs_halo_perio_sync_var_sym_tens(halo,
11349 CS_HALO_STANDARD,
11350 (cs_real_t *)viscce);
11351 }
11352
11353 /* Allocate a work array for the gradient calculation */
11354 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
11355
11356 /* Compute gradient */
11357 if (iwgrp > 0) {
11358 gweight = (cs_real_t *)viscce;
11359 if (halo != NULL) {
11360 cs_halo_sync_var_strided(halo, halo_type, gweight, 6);
11361 if (cs_glob_mesh->n_init_perio > 0)
11362 cs_halo_perio_sync_var_sym_tens(halo, halo_type, gweight);
11363 }
11364 }
11365
11366 else if (f_id > -1) {
11367 /* Get the calculation option from the field */
11368 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
11369 cs_var_cal_opt_t var_cal_opt;
11370 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
11371 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
11372 if (var_cal_opt.idifft > 0) {
11373 int key_id = cs_field_key_id("gradient_weighting_id");
11374 int diff_id = cs_field_get_key_int(f, key_id);
11375 if (diff_id > -1) {
11376 cs_field_t *weight_f = cs_field_by_id(diff_id);
11377 gweight = weight_f->val;
11378 w_stride = weight_f->dim;
11379 cs_field_synchronize(weight_f, halo_type);
11380 }
11381 }
11382 }
11383 }
11384
11385 /* Compute gradient */
11386 cs_gradient_scalar_synced_input(var_name,
11387 gradient_type,
11388 halo_type,
11389 inc,
11390 recompute_cocg,
11391 nswrgp,
11392 iphydp,
11393 w_stride,
11394 iwarnp,
11395 imligp,
11396 epsrgp,
11397 climgp,
11398 frcxt,
11399 coefap,
11400 coefbp,
11401 pvar,
11402 gweight, /* Weighted gradient */
11403 NULL, /* internal coupling */
11404 grad);
11405
11406 /* Mass flow through interior faces */
11407
11408 for (int g_id = 0; g_id < n_i_groups; g_id++) {
11409 # pragma omp parallel for
11410 for (int t_id = 0; t_id < n_i_threads; t_id++) {
11411 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
11412 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
11413 face_id++) {
11414
11415 cs_lnum_t ii = i_face_cells[face_id][0];
11416 cs_lnum_t jj = i_face_cells[face_id][1];
11417
11418 double pi = pvar[ii];
11419 double pj = pvar[jj];
11420
11421 /* Recompute II" and JJ"
11422 ----------------------*/
11423
11424 cs_real_t visci[3][3], viscj[3][3];
11425 cs_real_t diippf[3], djjppf[3];
11426
11427 visci[0][0] = viscce[ii][0];
11428 visci[1][1] = viscce[ii][1];
11429 visci[2][2] = viscce[ii][2];
11430 visci[1][0] = viscce[ii][3];
11431 visci[0][1] = viscce[ii][3];
11432 visci[2][1] = viscce[ii][4];
11433 visci[1][2] = viscce[ii][4];
11434 visci[2][0] = viscce[ii][5];
11435 visci[0][2] = viscce[ii][5];
11436
11437 cs_real_t bldfrp = (cs_real_t) ircflp;
11438 /* Local limitation of the reconstruction */
11439 if (df_limiter != NULL && ircflp > 0)
11440 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
11441
11442
11443 /* IF.Ki.S / ||Ki.S||^2 */
11444 cs_real_t fikdvi = weighf[face_id][0];
11445
11446 /* II" = IF + FI" */
11447 for (int i = 0; i < 3; i++) {
11448 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
11449 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
11450 + visci[1][i]*i_face_normal[face_id][1]
11451 + visci[2][i]*i_face_normal[face_id][2] );
11452 }
11453
11454 viscj[0][0] = viscce[jj][0];
11455 viscj[1][1] = viscce[jj][1];
11456 viscj[2][2] = viscce[jj][2];
11457 viscj[1][0] = viscce[jj][3];
11458 viscj[0][1] = viscce[jj][3];
11459 viscj[2][1] = viscce[jj][4];
11460 viscj[1][2] = viscce[jj][4];
11461 viscj[2][0] = viscce[jj][5];
11462 viscj[0][2] = viscce[jj][5];
11463
11464 /* FJ.Kj.S / ||Kj.S||^2 */
11465 double fjkdvi = weighf[face_id][1];
11466
11467 /* JJ" = JF + FJ" */
11468 for (int i = 0; i < 3; i++) {
11469 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
11470 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
11471 + viscj[1][i]*i_face_normal[face_id][1]
11472 + viscj[2][i]*i_face_normal[face_id][2] );
11473 }
11474
11475 /* p in I" and J" */
11476 double pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
11477 + grad[ii][1]*diippf[1]
11478 + grad[ii][2]*diippf[2]);
11479 double pjpp = pj + bldfrp*( grad[jj][0]*djjppf[0]
11480 + grad[jj][1]*djjppf[1]
11481 + grad[jj][2]*djjppf[2]);
11482
11483 i_massflux[face_id] += i_visc[face_id]*(pipp - pjpp);
11484
11485 }
11486 }
11487 }
11488
11489 /* ---> Contribution from boundary faces */
11490
11491 for (int g_id = 0; g_id < n_b_groups; g_id++) {
11492 # pragma omp parallel for
11493 for (int t_id = 0; t_id < n_b_threads; t_id++) {
11494 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
11495 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
11496 face_id++) {
11497
11498 cs_lnum_t ii = b_face_cells[face_id];
11499
11500 double pi = pvar[ii];
11501
11502 cs_real_t bldfrp = (cs_real_t) ircflp;
11503 /* Local limitation of the reconstruction */
11504 if (df_limiter != NULL && ircflp > 0)
11505 bldfrp = CS_MAX(df_limiter[ii], 0.);
11506
11507 /* Recompute II"
11508 --------------*/
11509
11510 cs_real_t visci[3][3];
11511 cs_real_t diippf[3];
11512
11513 visci[0][0] = viscce[ii][0];
11514 visci[1][1] = viscce[ii][1];
11515 visci[2][2] = viscce[ii][2];
11516 visci[1][0] = viscce[ii][3];
11517 visci[0][1] = viscce[ii][3];
11518 visci[2][1] = viscce[ii][4];
11519 visci[1][2] = viscce[ii][4];
11520 visci[2][0] = viscce[ii][5];
11521 visci[0][2] = viscce[ii][5];
11522
11523 /* IF.Ki.S / ||Ki.S||^2 */
11524 cs_real_t fikdvi = weighb[face_id];
11525
11526 /* II" = IF + FI" */
11527 for (int i = 0; i < 3; i++) {
11528 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
11529 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
11530 + visci[1][i]*b_face_normal[face_id][1]
11531 + visci[2][i]*b_face_normal[face_id][2] );
11532 }
11533
11534 double pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
11535 + grad[ii][1]*diippf[1]
11536 + grad[ii][2]*diippf[2]);
11537
11538
11539 double pfac = inc*cofafp[face_id] + cofbfp[face_id]*pipp;
11540
11541 b_massflux[face_id] += b_visc[face_id]*pfac;
11542
11543 }
11544 }
11545 }
11546
11547 /* Free memory */
11548 BFT_FREE(grad);
11549 BFT_FREE(w2);
11550
11551 }
11552 }
11553
11554 /*----------------------------------------------------------------------------*/
11555 /*!
11556 * \brief Update the cell mass flux divergence with the face pressure (or
11557 * pressure increment, or pressure double increment) gradient.
11558 *
11559 * \f[
11560 * \dot{m}_\ij = \dot{m}_\ij
11561 * - \sum_j \Delta t \grad_\fij p \cdot \vect{S}_\ij
11562 * \f]
11563 *
11564 * \param[in] f_id field id (or -1)
11565 * \param[in] m pointer to mesh
11566 * \param[in] fvq pointer to finite volume quantities
11567 * \param[in] init indicator
11568 * - 1 initialize the mass flux to 0
11569 * - 0 otherwise
11570 * \param[in] inc indicator
11571 * - 0 when solving an increment
11572 * - 1 otherwise
11573 * \param[in] imrgra indicator
11574 * - 0 iterative gradient
11575 * - 1 least squares gradient
11576 * \param[in] iccocg indicator
11577 * - 1 re-compute cocg matrix
11578 * (for iterative gradients)
11579 * - 0 otherwise
11580 * \param[in] nswrgp number of reconstruction sweeps for the
11581 * gradients
11582 * \param[in] imligp clipping gradient method
11583 * - < 0 no clipping
11584 * - = 0 thank to neighbooring gradients
11585 * - = 1 thank to the mean gradient
11586 * \param[in] iphydp hydrostatic pressure indicator
11587 * \param[in] iwarnp verbosity
11588 * \param[in] iwgrp indicator
11589 * - 1 weight gradient by vicosity*porosity
11590 * - weighting determined by field options
11591 * \param[in] epsrgp relative precision for the gradient
11592 * reconstruction
11593 * \param[in] climgp clipping coeffecient for the computation of
11594 * the gradient
11595 * \param[in] frcxt body force creating the hydrostatic pressure
11596 * \param[in] pvar solved variable (current time step)
11597 * \param[in] coefap boundary condition array for the variable
11598 * (explicit part)
11599 * \param[in] coefbp boundary condition array for the variable
11600 * (implicit part)
11601 * \param[in] cofafp boundary condition array for the diffusion
11602 * of the variable (explicit part)
11603 * \param[in] cofbfp boundary condition array for the diffusion
11604 * of the variable (implicit part)
11605 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
11606 * at interior faces for the r.h.s.
11607 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
11608 * at border faces for the r.h.s.
11609 * \param[in] visel viscosity by cell
11610 * \param[in,out] diverg mass flux divergence
11611 */
11612 /*----------------------------------------------------------------------------*/
11613
11614 void
cs_diffusion_potential(const int f_id,const cs_mesh_t * m,cs_mesh_quantities_t * fvq,int init,int inc,int imrgra,int iccocg,int nswrgp,int imligp,int iphydp,int iwgrp,int iwarnp,double epsrgp,double climgp,cs_real_3_t * restrict frcxt,cs_real_t * restrict pvar,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_t visel[],cs_real_t * restrict diverg)11615 cs_diffusion_potential(const int f_id,
11616 const cs_mesh_t *m,
11617 cs_mesh_quantities_t *fvq,
11618 int init,
11619 int inc,
11620 int imrgra,
11621 int iccocg,
11622 int nswrgp,
11623 int imligp,
11624 int iphydp,
11625 int iwgrp,
11626 int iwarnp,
11627 double epsrgp,
11628 double climgp,
11629 cs_real_3_t *restrict frcxt,
11630 cs_real_t *restrict pvar,
11631 const cs_real_t coefap[],
11632 const cs_real_t coefbp[],
11633 const cs_real_t cofafp[],
11634 const cs_real_t cofbfp[],
11635 const cs_real_t i_visc[],
11636 const cs_real_t b_visc[],
11637 cs_real_t visel[],
11638 cs_real_t *restrict diverg)
11639 {
11640 const cs_halo_t *halo = m->halo;
11641
11642 const cs_lnum_t n_cells = m->n_cells;
11643 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
11644 const int n_i_groups = m->i_face_numbering->n_groups;
11645 const int n_i_threads = m->i_face_numbering->n_threads;
11646 const int n_b_groups = m->b_face_numbering->n_groups;
11647 const int n_b_threads = m->b_face_numbering->n_threads;
11648 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
11649 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
11650
11651 const cs_lnum_2_t *restrict i_face_cells
11652 = (const cs_lnum_2_t *restrict)m->i_face_cells;
11653 const cs_lnum_t *restrict b_face_cells
11654 = (const cs_lnum_t *restrict)m->b_face_cells;
11655 const cs_real_t *restrict i_dist = fvq->i_dist;
11656 const cs_real_t *restrict i_f_face_surf = fvq->i_f_face_surf;
11657 const cs_real_3_t *restrict diipf
11658 = (const cs_real_3_t *restrict)fvq->diipf;
11659 const cs_real_3_t *restrict djjpf
11660 = (const cs_real_3_t *restrict)fvq->djjpf;
11661 const cs_real_3_t *restrict diipb
11662 = (const cs_real_3_t *restrict)fvq->diipb;
11663
11664 /* Local variables */
11665
11666 char var_name[64];
11667 int mass_flux_rec_type = cs_glob_velocity_pressure_param->irecmf;
11668 int w_stride = 1;
11669
11670 bool recompute_cocg = (iccocg) ? true : false;
11671
11672 cs_real_3_t *grad;
11673 cs_field_t *f;
11674
11675 cs_real_t *gweight = NULL;
11676
11677 /*==========================================================================*/
11678
11679 /*==========================================================================
11680 1. Initialization
11681 ==========================================================================*/
11682
11683 if (init >= 1) {
11684 # pragma omp parallel for
11685 for (cs_lnum_t ii = 0; ii < n_cells_ext; ii++) {
11686 diverg[ii] = 0.;
11687 }
11688 } else if (init == 0 && n_cells_ext > n_cells) {
11689 # pragma omp parallel for if(n_cells_ext - n_cells > CS_THR_MIN)
11690 for (cs_lnum_t ii = n_cells; ii < n_cells_ext; ii++) {
11691 diverg[ii] = 0.;
11692 }
11693 } else if (init != 0) {
11694 bft_error(__FILE__, __LINE__, 0,
11695 _("invalid value of init"));
11696 }
11697
11698 /* Use iterative gradient */
11699
11700 cs_halo_type_t halo_type = CS_HALO_STANDARD;
11701 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
11702
11703 if (imrgra < 0)
11704 imrgra = 0;
11705
11706 cs_gradient_type_by_imrgra(imrgra,
11707 &gradient_type,
11708 &halo_type);
11709 if (f_id != -1) {
11710 f = cs_field_by_id(f_id);
11711 snprintf(var_name, 63, "%s", f->name);
11712 }
11713 else
11714 strncpy(var_name, "[cell mass flux divergence update]", 63);
11715 var_name[63] = '\0';
11716
11717 /* Handle parallelism and periodicity */
11718
11719 if (halo != NULL)
11720 cs_halo_sync_var(halo, halo_type, pvar);
11721
11722 /*==========================================================================
11723 2. Update mass flux without reconstruction technics
11724 ==========================================================================*/
11725
11726 if (nswrgp <= 1) {
11727
11728 /* Mass flow through interior faces */
11729
11730 for (int g_id = 0; g_id < n_i_groups; g_id++) {
11731 # pragma omp parallel for
11732 for (int t_id = 0; t_id < n_i_threads; t_id++) {
11733 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
11734 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
11735 face_id++) {
11736
11737 cs_lnum_t ii = i_face_cells[face_id][0];
11738 cs_lnum_t jj = i_face_cells[face_id][1];
11739
11740 double i_massflux = i_visc[face_id]*(pvar[ii] - pvar[jj]);
11741 diverg[ii] += i_massflux;
11742 diverg[jj] -= i_massflux;
11743
11744 }
11745 }
11746 }
11747
11748 /* Mass flow through boundary faces */
11749
11750 for (int g_id = 0; g_id < n_b_groups; g_id++) {
11751 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
11752 for (int t_id = 0; t_id < n_b_threads; t_id++) {
11753 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
11754 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
11755 face_id++) {
11756
11757 cs_lnum_t ii = b_face_cells[face_id];
11758 double pfac = inc*cofafp[face_id] +cofbfp[face_id]*pvar[ii];
11759
11760 double b_massflux = b_visc[face_id]*pfac;
11761 diverg[ii] += b_massflux;
11762
11763 }
11764 }
11765 }
11766
11767 }
11768
11769 /*==========================================================================
11770 3. Update mass flux with reconstruction if the mesh is non-orthogonal
11771 ==========================================================================*/
11772
11773 if (nswrgp > 1) {
11774
11775 /* Allocate a work array for the gradient calculation */
11776 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
11777
11778 /* Compute gradient */
11779 if (iwgrp > 0) {
11780 gweight = visel;
11781 if (halo != NULL)
11782 cs_halo_sync_var(halo, halo_type, gweight);
11783 }
11784
11785 else if (f_id > -1) {
11786 /* Get the calculation option from the field */
11787 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
11788 cs_var_cal_opt_t var_cal_opt;
11789 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
11790 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
11791 if (var_cal_opt.idiff > 0) {
11792 int key_id = cs_field_key_id("gradient_weighting_id");
11793 int diff_id = cs_field_get_key_int(f, key_id);
11794 if (diff_id > -1) {
11795 cs_field_t *weight_f = cs_field_by_id(diff_id);
11796 gweight = weight_f->val;
11797 w_stride = weight_f->dim;
11798 cs_field_synchronize(weight_f, halo_type);
11799 }
11800 }
11801 }
11802 }
11803
11804 cs_real_t *_pvar = pvar;
11805
11806 if (cs_glob_mesh_quantities_flag & CS_BAD_CELLS_REGULARISATION) {
11807 BFT_MALLOC(_pvar, n_cells_ext, cs_real_t);
11808
11809 for (cs_lnum_t cell_id = 0; cell_id < n_cells_ext; cell_id++)
11810 _pvar[cell_id] = pvar[cell_id];
11811
11812 cs_bad_cells_regularisation_scalar(_pvar);
11813 }
11814
11815 cs_gradient_scalar_synced_input(var_name,
11816 gradient_type,
11817 halo_type,
11818 inc,
11819 recompute_cocg,
11820 nswrgp,
11821 iphydp,
11822 w_stride,
11823 iwarnp,
11824 imligp,
11825 epsrgp,
11826 climgp,
11827 frcxt,
11828 coefap,
11829 coefbp,
11830 _pvar,
11831 gweight, /* Weighted gradient */
11832 NULL, /* internal coupling */
11833 grad);
11834
11835 if (_pvar != pvar)
11836 BFT_FREE(_pvar);
11837
11838 /* Handle parallelism and periodicity */
11839
11840 if (halo != NULL)
11841 cs_halo_sync_var(halo, halo_type, visel);
11842
11843 /* Mass flow through interior faces */
11844
11845 for (int g_id = 0; g_id < n_i_groups; g_id++) {
11846 # pragma omp parallel for
11847 for (int t_id = 0; t_id < n_i_threads; t_id++) {
11848 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
11849 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
11850 face_id++) {
11851
11852 cs_lnum_t ii = i_face_cells[face_id][0];
11853 cs_lnum_t jj = i_face_cells[face_id][1];
11854
11855 double i_massflux = i_visc[face_id]*(pvar[ii] - pvar[jj]);
11856
11857 if (mass_flux_rec_type == 0) {
11858
11859 /*---> Dij = IJ - (IJ.N) N = II' - JJ' */
11860 double dijx = diipf[face_id][0] - djjpf[face_id][0];
11861 double dijy = diipf[face_id][1] - djjpf[face_id][1];
11862 double dijz = diipf[face_id][2] - djjpf[face_id][2];
11863
11864 double dpxf = 0.5*( visel[ii]*grad[ii][0]
11865 + visel[jj]*grad[jj][0]);
11866 double dpyf = 0.5*( visel[ii]*grad[ii][1]
11867 + visel[jj]*grad[jj][1]);
11868 double dpzf = 0.5*( visel[ii]*grad[ii][2]
11869 + visel[jj]*grad[jj][2]);
11870
11871 i_massflux += (dpxf*dijx + dpyf*dijy + dpzf*dijz)
11872 *i_f_face_surf[face_id]/i_dist[face_id];
11873 }
11874 else {
11875 i_massflux += i_visc[face_id]*
11876 ( cs_math_3_dot_product(grad[ii], diipf[face_id])
11877 - cs_math_3_dot_product(grad[jj], djjpf[face_id]));
11878 }
11879
11880 diverg[ii] += i_massflux;
11881 diverg[jj] -= i_massflux;
11882
11883 }
11884 }
11885 }
11886
11887 /* Mass flow through boundary faces */
11888
11889 for (int g_id = 0; g_id < n_b_groups; g_id++) {
11890 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
11891 for (int t_id = 0; t_id < n_b_threads; t_id++) {
11892 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
11893 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
11894 face_id++) {
11895
11896 cs_lnum_t ii = b_face_cells[face_id];
11897
11898 double diipbx = diipb[face_id][0];
11899 double diipby = diipb[face_id][1];
11900 double diipbz = diipb[face_id][2];
11901
11902 double pip = pvar[ii] + grad[ii][0]*diipbx
11903 + grad[ii][1]*diipby
11904 + grad[ii][2]*diipbz;
11905 double pfac = inc*cofafp[face_id] +cofbfp[face_id]*pip;
11906
11907 double b_massflux = b_visc[face_id]*pfac;
11908 diverg[ii] += b_massflux;
11909
11910 }
11911 }
11912 }
11913
11914 /* Free memory */
11915 BFT_FREE(grad);
11916 }
11917 }
11918
11919 /*----------------------------------------------------------------------------*/
11920 /*!
11921 * \brief Add the explicit part of the divergence of the mass flux due to the
11922 * pressure gradient (routine analog to diften).
11923 *
11924 * More precisely, the divergence of the mass flux side
11925 * \f$ \sum_{\fij \in \Facei{\celli}} \dot{m}_\fij \f$ is updated as follows:
11926 * \f[
11927 * \sum_{\fij \in \Facei{\celli}} \dot{m}_\fij
11928 * = \sum_{\fij \in \Facei{\celli}} \dot{m}_\fij
11929 * - \sum_{\fij \in \Facei{\celli}}
11930 * \left( \tens{\mu}_\fij \gradv_\fij P \cdot \vect{S}_\ij \right)
11931 * \f]
11932 *
11933 * \param[in] f_id field id (or -1)
11934 * \param[in] m pointer to mesh
11935 * \param[in] fvq pointer to finite volume quantities
11936 * \param[in] init indicator
11937 * - 1 initialize the mass flux to 0
11938 * - 0 otherwise
11939 * \param[in] inc indicator
11940 * - 0 when solving an increment
11941 * - 1 otherwise
11942 * \param[in] imrgra indicator
11943 * - 0 iterative gradient
11944 * - 1 least squares gradient
11945 * \param[in] iccocg indicator
11946 * - 1 re-compute cocg matrix
11947 (for iterative gradients)
11948 * - 0 otherwise
11949 * \param[in] nswrgp number of reconstruction sweeps for the
11950 * gradients
11951 * \param[in] imligp clipping gradient method
11952 * - < 0 no clipping
11953 * - = 0 thank to neighbooring gradients
11954 * - = 1 thank to the mean gradient
11955 * \param[in] ircflp indicator
11956 * - 1 flux reconstruction,
11957 * - 0 otherwise
11958 * \param[in] iphydp indicator
11959 * - 1 hydrostatic pressure taken into account
11960 * - 0 otherwise
11961 * \param[in] iwgrp indicator
11962 * - 1 weight gradient by vicosity*porosity
11963 * - weighting determined by field options
11964 * \param[in] iwarnp verbosity
11965 * \param[in] epsrgp relative precision for the gradient
11966 * reconstruction
11967 * \param[in] climgp clipping coeffecient for the computation of
11968 * the gradient
11969 * \param[in] frcxt body force creating the hydrostatic pressure
11970 * \param[in] pvar solved variable (pressure)
11971 * \param[in] coefap boundary condition array for the variable
11972 * (explicit part)
11973 * \param[in] coefbp boundary condition array for the variable
11974 * (implicit part)
11975 * \param[in] cofafp boundary condition array for the diffusion
11976 * of the variable (explicit part)
11977 * \param[in] cofbfp boundary condition array for the diffusion
11978 * of the variable (implicit part)
11979 * \param[in] i_visc \f$ \mu_\fij \dfrac{S_\fij}{\ipf \jpf} \f$
11980 * at interior faces for the r.h.s.
11981 * \param[in] b_visc \f$ \mu_\fib \dfrac{S_\fib}{\ipf \centf} \f$
11982 * at border faces for the r.h.s.
11983 * \param[in] viscel symmetric cell tensor \f$ \tens{\mu}_\celli \f$
11984 * \param[in] weighf internal face weight between cells i j in case
11985 * of tensor diffusion
11986 * \param[in] weighb boundary face weight for cells i in case
11987 * of tensor diffusion
11988 * \param[in,out] diverg divergence of the mass flux
11989 */
11990 /*----------------------------------------------------------------------------*/
11991
11992 void
cs_anisotropic_diffusion_potential(const int f_id,const cs_mesh_t * m,cs_mesh_quantities_t * fvq,int init,int inc,int imrgra,int iccocg,int nswrgp,int imligp,int ircflp,int iphydp,int iwgrp,int iwarnp,double epsrgp,double climgp,cs_real_3_t * restrict frcxt,cs_real_t * restrict pvar,const cs_real_t coefap[],const cs_real_t coefbp[],const cs_real_t cofafp[],const cs_real_t cofbfp[],const cs_real_t i_visc[],const cs_real_t b_visc[],cs_real_6_t * restrict viscel,const cs_real_2_t weighf[],const cs_real_t weighb[],cs_real_t * restrict diverg)11993 cs_anisotropic_diffusion_potential(const int f_id,
11994 const cs_mesh_t *m,
11995 cs_mesh_quantities_t *fvq,
11996 int init,
11997 int inc,
11998 int imrgra,
11999 int iccocg,
12000 int nswrgp,
12001 int imligp,
12002 int ircflp,
12003 int iphydp,
12004 int iwgrp,
12005 int iwarnp,
12006 double epsrgp,
12007 double climgp,
12008 cs_real_3_t *restrict frcxt,
12009 cs_real_t *restrict pvar,
12010 const cs_real_t coefap[],
12011 const cs_real_t coefbp[],
12012 const cs_real_t cofafp[],
12013 const cs_real_t cofbfp[],
12014 const cs_real_t i_visc[],
12015 const cs_real_t b_visc[],
12016 cs_real_6_t *restrict viscel,
12017 const cs_real_2_t weighf[],
12018 const cs_real_t weighb[],
12019 cs_real_t *restrict diverg)
12020 {
12021 const cs_halo_t *halo = m->halo;
12022
12023 const cs_lnum_t n_cells = m->n_cells;
12024 const cs_lnum_t n_cells_ext = m->n_cells_with_ghosts;
12025 const int n_i_groups = m->i_face_numbering->n_groups;
12026 const int n_i_threads = m->i_face_numbering->n_threads;
12027 const int n_b_groups = m->b_face_numbering->n_groups;
12028 const int n_b_threads = m->b_face_numbering->n_threads;
12029 const cs_lnum_t *restrict i_group_index = m->i_face_numbering->group_index;
12030 const cs_lnum_t *restrict b_group_index = m->b_face_numbering->group_index;
12031
12032 const cs_lnum_2_t *restrict i_face_cells
12033 = (const cs_lnum_2_t *restrict)m->i_face_cells;
12034 const cs_lnum_t *restrict b_face_cells
12035 = (const cs_lnum_t *restrict)m->b_face_cells;
12036 const cs_real_3_t *restrict cell_cen
12037 = (const cs_real_3_t *restrict)fvq->cell_cen;
12038 const cs_real_3_t *restrict i_face_normal
12039 = (const cs_real_3_t *restrict)fvq->i_face_normal;
12040 const cs_real_3_t *restrict b_face_normal
12041 = (const cs_real_3_t *restrict)fvq->b_face_normal;
12042 const cs_real_3_t *restrict i_face_cog
12043 = (const cs_real_3_t *restrict)fvq->i_face_cog;
12044 const cs_real_3_t *restrict b_face_cog
12045 = (const cs_real_3_t *restrict)fvq->b_face_cog;
12046
12047 /* Local variables */
12048
12049 cs_real_t *df_limiter = NULL;
12050
12051 char var_name[64];
12052 int w_stride = 6;
12053
12054 bool recompute_cocg = (iccocg) ? true : false;
12055
12056 cs_real_6_t *viscce = NULL;
12057 cs_real_6_t *w2 = NULL;
12058 cs_real_3_t *grad = NULL;
12059 cs_field_t *f = NULL;
12060
12061 cs_real_t *gweight = NULL;
12062
12063 /*==========================================================================
12064 1. Initialization
12065 ==========================================================================*/
12066
12067 if (init >= 1) {
12068 # pragma omp parallel for
12069 for (cs_lnum_t ii = 0; ii < n_cells_ext; ii++) {
12070 diverg[ii] = 0.;
12071 }
12072 } else if (init == 0 && n_cells_ext > n_cells) {
12073 # pragma omp parallel for if(n_cells_ext - n_cells > CS_THR_MIN)
12074 for (cs_lnum_t ii = n_cells+0; ii < n_cells_ext; ii++) {
12075 diverg[ii] = 0.;
12076 }
12077 } else if (init != 0) {
12078 bft_error(__FILE__, __LINE__, 0,
12079 _("invalid value of init"));
12080 }
12081
12082 /* Use iterative gradient */
12083
12084 cs_halo_type_t halo_type = CS_HALO_STANDARD;
12085 cs_gradient_type_t gradient_type = CS_GRADIENT_GREEN_ITER;
12086
12087 if (imrgra < 0)
12088 imrgra = 0;
12089
12090 cs_gradient_type_by_imrgra(imrgra,
12091 &gradient_type,
12092 &halo_type);
12093
12094 if (f_id != -1) {
12095 f = cs_field_by_id(f_id);
12096
12097 int df_limiter_id
12098 = cs_field_get_key_int(f, cs_field_key_id("diffusion_limiter_id"));
12099 if (df_limiter_id > -1)
12100 df_limiter = cs_field_by_id(df_limiter_id)->val;
12101
12102
12103 snprintf(var_name, 63, "%s", f->name);
12104 }
12105 else
12106 strncpy(var_name, "[cell mass flux divergence update]", 63);
12107 var_name[63] = '\0';
12108
12109 /* Porosity fields */
12110 cs_field_t *fporo = cs_field_by_name_try("porosity");
12111 cs_field_t *ftporo = cs_field_by_name_try("tensorial_porosity");
12112
12113 cs_real_t *porosi = NULL;
12114 cs_real_6_t *porosf = NULL;
12115
12116 if (cs_glob_porous_model == 1 || cs_glob_porous_model == 2) {
12117 porosi = fporo->val;
12118 if (ftporo != NULL) {
12119 porosf = (cs_real_6_t *)ftporo->val;
12120 }
12121 }
12122
12123 /* Handle parallelism and periodicity */
12124
12125 if (halo != NULL)
12126 cs_halo_sync_var(halo, halo_type, pvar);
12127
12128 /*==========================================================================
12129 2. Update mass flux without reconstruction technics
12130 ==========================================================================*/
12131
12132 if (nswrgp <= 1) {
12133
12134 /* Mass flow through interior faces */
12135
12136 for (int g_id = 0; g_id < n_i_groups; g_id++) {
12137 # pragma omp parallel for
12138 for (int t_id = 0; t_id < n_i_threads; t_id++) {
12139 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
12140 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
12141 face_id++) {
12142
12143 cs_lnum_t ii = i_face_cells[face_id][0];
12144 cs_lnum_t jj = i_face_cells[face_id][1];
12145
12146 double flux = i_visc[face_id]*(pvar[ii] - pvar[jj]);
12147 diverg[ii] += flux;
12148 diverg[jj] -= flux;
12149
12150 }
12151 }
12152 }
12153
12154 /* Mass flow though boundary faces */
12155
12156 for (int g_id = 0; g_id < n_b_groups; g_id++) {
12157 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
12158 for (int t_id = 0; t_id < n_b_threads; t_id++) {
12159 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
12160 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
12161 face_id++) {
12162
12163 cs_lnum_t ii = b_face_cells[face_id];
12164 double pfac = inc*cofafp[face_id] + cofbfp[face_id]*pvar[ii];
12165
12166 double flux = b_visc[face_id]*pfac;
12167 diverg[ii] += flux;
12168
12169 }
12170 }
12171 }
12172
12173 }
12174
12175 /*==========================================================================
12176 3. Update mass flux with reconstruction technics
12177 ==========================================================================*/
12178
12179 if (nswrgp > 1) {
12180
12181 viscce = NULL;
12182 w2 = NULL;
12183
12184 /* Without porosity */
12185 if (porosi == NULL) {
12186 viscce = viscel;
12187
12188 /* With porosity */
12189 } else if (porosi != NULL && porosf == NULL) {
12190 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
12191 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
12192 for (int isou = 0; isou < 6; isou++) {
12193 w2[cell_id][isou] = porosi[cell_id]*viscel[cell_id][isou];
12194 }
12195 }
12196 viscce = w2;
12197
12198 /* With tensorial porosity */
12199 } else if (porosi != NULL && porosf != NULL) {
12200 BFT_MALLOC(w2, n_cells_ext, cs_real_6_t);
12201 for (cs_lnum_t cell_id = 0; cell_id < n_cells; cell_id++) {
12202 cs_math_sym_33_product(porosf[cell_id],
12203 viscel[cell_id],
12204 w2[cell_id]);
12205 }
12206 viscce = w2;
12207 }
12208
12209 /* ---> Periodicity and parallelism treatment of symmetric tensors */
12210
12211 if (halo != NULL) {
12212 cs_halo_sync_var_strided(halo, CS_HALO_STANDARD, (cs_real_t *)viscce, 6);
12213
12214 if (m->n_init_perio > 0)
12215 cs_halo_perio_sync_var_sym_tens(halo,
12216 CS_HALO_STANDARD,
12217 (cs_real_t *)viscce);
12218 }
12219
12220 /* Allocate a work array for the gradient calculation */
12221 BFT_MALLOC(grad, n_cells_ext, cs_real_3_t);
12222
12223 /* Compute gradient */
12224 if (iwgrp > 0) {
12225 gweight = (cs_real_t *)viscce;
12226 if (halo != NULL) {
12227 cs_halo_sync_var_strided(halo, halo_type, gweight, 6);
12228 if (cs_glob_mesh->n_init_perio > 0)
12229 cs_halo_perio_sync_var_sym_tens(halo, halo_type, gweight);
12230 }
12231 }
12232
12233 else if (f_id > -1) {
12234 /* Get the calculation option from the field */
12235 int key_cal_opt_id = cs_field_key_id("var_cal_opt");
12236 cs_var_cal_opt_t var_cal_opt;
12237 cs_field_get_key_struct(f, key_cal_opt_id, &var_cal_opt);
12238 if (f->type & CS_FIELD_VARIABLE && var_cal_opt.iwgrec == 1) {
12239 if (var_cal_opt.idifft > 0) {
12240 int key_id = cs_field_key_id("gradient_weighting_id");
12241 int diff_id = cs_field_get_key_int(f, key_id);
12242 if (diff_id > -1) {
12243 cs_field_t *weight_f = cs_field_by_id(diff_id);
12244 gweight = weight_f->val;
12245 w_stride = weight_f->dim;
12246 cs_field_synchronize(weight_f, halo_type);
12247 }
12248 }
12249 }
12250 }
12251
12252 /* Compute gradient */
12253 cs_gradient_scalar_synced_input(var_name,
12254 gradient_type,
12255 halo_type,
12256 inc,
12257 recompute_cocg,
12258 nswrgp,
12259 iphydp,
12260 w_stride,
12261 iwarnp,
12262 imligp,
12263 epsrgp,
12264 climgp,
12265 frcxt,
12266 coefap,
12267 coefbp,
12268 pvar,
12269 gweight, /* Weighted gradient */
12270 NULL, /* internal coupling */
12271 grad);
12272
12273 /* Mass flow through interior faces */
12274
12275 for (int g_id = 0; g_id < n_i_groups; g_id++) {
12276 # pragma omp parallel for
12277 for (int t_id = 0; t_id < n_i_threads; t_id++) {
12278 for (cs_lnum_t face_id = i_group_index[(t_id*n_i_groups + g_id)*2];
12279 face_id < i_group_index[(t_id*n_i_groups + g_id)*2 + 1];
12280 face_id++) {
12281
12282 cs_lnum_t ii = i_face_cells[face_id][0];
12283 cs_lnum_t jj = i_face_cells[face_id][1];
12284
12285 double pi = pvar[ii];
12286 double pj = pvar[jj];
12287
12288 cs_real_t bldfrp = (cs_real_t) ircflp;
12289 /* Local limitation of the reconstruction */
12290 if (df_limiter != NULL && ircflp > 0)
12291 bldfrp = CS_MAX(CS_MIN(df_limiter[ii], df_limiter[jj]), 0.);
12292
12293
12294 /* Recompute II" and JJ"
12295 ----------------------*/
12296
12297 cs_real_t visci[3][3], viscj[3][3];
12298
12299 visci[0][0] = viscce[ii][0];
12300 visci[1][1] = viscce[ii][1];
12301 visci[2][2] = viscce[ii][2];
12302 visci[1][0] = viscce[ii][3];
12303 visci[0][1] = viscce[ii][3];
12304 visci[2][1] = viscce[ii][4];
12305 visci[1][2] = viscce[ii][4];
12306 visci[2][0] = viscce[ii][5];
12307 visci[0][2] = viscce[ii][5];
12308
12309 /* IF.Ki.S / ||Ki.S||^2 */
12310 cs_real_t fikdvi = weighf[face_id][0];
12311
12312 /* II" = IF + FI" */
12313
12314 double diippf[3], djjppf[3];
12315
12316 for (int i = 0; i < 3; i++) {
12317 diippf[i] = i_face_cog[face_id][i]-cell_cen[ii][i]
12318 - fikdvi*( visci[0][i]*i_face_normal[face_id][0]
12319 + visci[1][i]*i_face_normal[face_id][1]
12320 + visci[2][i]*i_face_normal[face_id][2] );
12321 }
12322
12323 viscj[0][0] = viscce[jj][0];
12324 viscj[1][1] = viscce[jj][1];
12325 viscj[2][2] = viscce[jj][2];
12326 viscj[1][0] = viscce[jj][3];
12327 viscj[0][1] = viscce[jj][3];
12328 viscj[2][1] = viscce[jj][4];
12329 viscj[1][2] = viscce[jj][4];
12330 viscj[2][0] = viscce[jj][5];
12331 viscj[0][2] = viscce[jj][5];
12332
12333 /* FJ.Kj.S / ||Kj.S||^2 */
12334 double fjkdvi = weighf[face_id][1];
12335
12336 /* JJ" = JF + FJ" */
12337 for (int i = 0; i < 3; i++) {
12338 djjppf[i] = i_face_cog[face_id][i]-cell_cen[jj][i]
12339 + fjkdvi*( viscj[0][i]*i_face_normal[face_id][0]
12340 + viscj[1][i]*i_face_normal[face_id][1]
12341 + viscj[2][i]*i_face_normal[face_id][2] );
12342 }
12343
12344 /* p in I" and J" */
12345 double pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
12346 + grad[ii][1]*diippf[1]
12347 + grad[ii][2]*diippf[2]);
12348 double pjpp = pj + bldfrp*( grad[jj][0]*djjppf[0]
12349 + grad[jj][1]*djjppf[1]
12350 + grad[jj][2]*djjppf[2]);
12351
12352 double flux = i_visc[face_id]*(pipp - pjpp);
12353
12354 diverg[ii] += flux;
12355 diverg[jj] -= flux;
12356
12357 }
12358 }
12359 }
12360
12361 /* Mass flow though boundary faces */
12362
12363 for (int g_id = 0; g_id < n_b_groups; g_id++) {
12364 # pragma omp parallel for if(m->n_b_faces > CS_THR_MIN)
12365 for (int t_id = 0; t_id < n_b_threads; t_id++) {
12366 for (cs_lnum_t face_id = b_group_index[(t_id*n_b_groups + g_id)*2];
12367 face_id < b_group_index[(t_id*n_b_groups + g_id)*2 + 1];
12368 face_id++) {
12369
12370 cs_lnum_t ii = b_face_cells[face_id];
12371
12372 double pi = pvar[ii];
12373
12374 cs_real_t bldfrp = (cs_real_t) ircflp;
12375 /* Local limitation of the reconstruction */
12376 if (df_limiter != NULL && ircflp > 0)
12377 bldfrp = CS_MAX(df_limiter[ii], 0.);
12378
12379 /* Recompute II"
12380 --------------*/
12381
12382 cs_real_t visci[3][3];
12383
12384 visci[0][0] = viscce[ii][0];
12385 visci[1][1] = viscce[ii][1];
12386 visci[2][2] = viscce[ii][2];
12387 visci[1][0] = viscce[ii][3];
12388 visci[0][1] = viscce[ii][3];
12389 visci[2][1] = viscce[ii][4];
12390 visci[1][2] = viscce[ii][4];
12391 visci[2][0] = viscce[ii][5];
12392 visci[0][2] = viscce[ii][5];
12393
12394 /* IF.Ki.S / ||Ki.S||^2 */
12395 double fikdvi = weighb[face_id];
12396
12397 double diippf[3];
12398
12399 /* II" = IF + FI" */
12400 for (int i = 0; i < 3; i++) {
12401 diippf[i] = b_face_cog[face_id][i] - cell_cen[ii][i]
12402 - fikdvi*( visci[0][i]*b_face_normal[face_id][0]
12403 + visci[1][i]*b_face_normal[face_id][1]
12404 + visci[2][i]*b_face_normal[face_id][2] );
12405 }
12406
12407 double pipp = pi + bldfrp*( grad[ii][0]*diippf[0]
12408 + grad[ii][1]*diippf[1]
12409 + grad[ii][2]*diippf[2]);
12410
12411
12412 double pfac = inc*cofafp[face_id] + cofbfp[face_id]*pipp;
12413
12414 double flux = b_visc[face_id]*pfac;
12415 diverg[ii] += flux;
12416
12417 }
12418 }
12419 }
12420
12421 /* Free memory */
12422 BFT_FREE(grad);
12423 BFT_FREE(w2);
12424
12425 }
12426
12427 }
12428
12429 /*----------------------------------------------------------------------------*/
12430
12431 END_C_DECLS
12432