1 /*============================================================================
2  * Manage the low-level structure dedicated to boundary conditions
3  *============================================================================*/
4 
5 /*
6   This file is part of Code_Saturne, a general-purpose CFD tool.
7 
8   Copyright (C) 1998-2021 EDF S.A.
9 
10   This program is free software; you can redistribute it and/or modify it under
11   the terms of the GNU General Public License as published by the Free Software
12   Foundation; either version 2 of the License, or (at your option) any later
13   version.
14 
15   This program is distributed in the hope that it will be useful, but WITHOUT
16   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18   details.
19 
20   You should have received a copy of the GNU General Public License along with
21   this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22   Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24 
25 /*----------------------------------------------------------------------------*/
26 
27 #include "cs_defs.h"
28 
29 /*----------------------------------------------------------------------------
30  * Standard C library headers
31  *----------------------------------------------------------------------------*/
32 
33 #include <errno.h>
34 #include <locale.h>
35 #include <assert.h>
36 
37 /*----------------------------------------------------------------------------
38  *  Local headers
39  *----------------------------------------------------------------------------*/
40 
41 #include "bft_mem.h"
42 
43 #include "cs_boundary_zone.h"
44 #include "cs_mesh_location.h"
45 
46 /*----------------------------------------------------------------------------
47  *  Header for the current file
48  *----------------------------------------------------------------------------*/
49 
50 #include "cs_cdo_bc.h"
51 
52 /*----------------------------------------------------------------------------*/
53 
54 BEGIN_C_DECLS
55 
56 /*============================================================================
57  * Global variables
58  *============================================================================*/
59 
60 /*=============================================================================
61  * Local Macro definitions
62  *============================================================================*/
63 
64 /*============================================================================
65  * Private function prototypes
66  *============================================================================*/
67 
68 /*----------------------------------------------------------------------------*/
69 /*!
70  * \brief   Create a cs_cdo_bc_face_t structure
71  *
72  * \param[in] is_steady   true or false
73  * \param[in] n_b_faces   number of boundary faces
74  *
75  * \return  a new allocated pointer to a cs_cdo_bc_face_t structure
76  */
77 /*----------------------------------------------------------------------------*/
78 
79 static cs_cdo_bc_face_t *
_cdo_bc_face_create(bool is_steady,cs_lnum_t n_b_faces)80 _cdo_bc_face_create(bool       is_steady,
81                     cs_lnum_t  n_b_faces)
82 {
83   cs_cdo_bc_face_t  *bc = NULL;
84 
85   BFT_MALLOC(bc, 1, cs_cdo_bc_face_t);
86 
87   bc->is_steady = is_steady;
88   bc->n_b_faces = n_b_faces;
89 
90   /* Default initialization */
91   bc->flag = NULL;
92   BFT_MALLOC(bc->flag, n_b_faces, cs_flag_t);
93   memset(bc->flag, 0, n_b_faces*sizeof(cs_flag_t));
94 
95   /* Default initialization */
96   bc->def_ids = NULL;
97   BFT_MALLOC(bc->def_ids, n_b_faces, short int);
98   for (cs_lnum_t i = 0; i < n_b_faces; i++)
99     bc->def_ids[i] = CS_CDO_BC_DEFAULT_DEF;
100 
101   /* Other lists of faces */
102   bc->n_hmg_dir_faces = 0;
103   bc->hmg_dir_ids = NULL;
104   bc->n_nhmg_dir_faces = 0;
105   bc->nhmg_dir_ids = NULL;
106 
107   bc->n_hmg_neu_faces = 0;
108   bc->hmg_neu_ids = NULL;
109   bc->n_nhmg_neu_faces = 0;
110   bc->nhmg_neu_ids = NULL;
111 
112   bc->n_robin_faces = 0;
113   bc->robin_ids = NULL;
114 
115   bc->n_sliding_faces = 0;
116   bc->sliding_ids = NULL;
117 
118   bc->n_circulation_faces = 0;
119   bc->circulation_ids = NULL;
120 
121   return bc;
122 }
123 
124 /*============================================================================
125  * Public function prototypes
126  *============================================================================*/
127 
128 /*----------------------------------------------------------------------------*/
129 /*!
130  * \brief  Define the structure which translates the BC definitions from the
131  *         user viewpoint into a ready-to-use structure for setting the arrays
132  *         keeping the values of the boundary condition to set.
133  *
134  * \param[in] default_bc   type of boundary condition to set by default
135  * \param[in] is_steady    modification or not of the BC selection in time
136  * \param[in] dim          dimension of the related equation
137  * \param[in] n_defs       number of boundary definitions
138  * \param[in] defs         list of boundary condition definition
139  * \param[in] n_b_faces    number of border faces
140  *
141  * \return a pointer to a new allocated cs_cdo_bc_face_t structure
142  */
143 /*----------------------------------------------------------------------------*/
144 
145 cs_cdo_bc_face_t *
cs_cdo_bc_face_define(cs_param_bc_type_t default_bc,bool is_steady,int dim,int n_defs,cs_xdef_t ** defs,cs_lnum_t n_b_faces)146 cs_cdo_bc_face_define(cs_param_bc_type_t    default_bc,
147                       bool                  is_steady,
148                       int                   dim,
149                       int                   n_defs,
150                       cs_xdef_t           **defs,
151                       cs_lnum_t             n_b_faces)
152 {
153   CS_UNUSED(dim); /* Only in debug */
154 
155   /* Set the default flag */
156   cs_flag_t  default_flag = cs_cdo_bc_get_flag(default_bc);
157 
158   if (!(default_flag & CS_CDO_BC_HMG_DIRICHLET) &&
159       !(default_flag & CS_CDO_BC_HMG_NEUMANN) &&
160       !(default_flag & CS_CDO_BC_SLIDING))
161     bft_error(__FILE__, __LINE__, 0,
162               _(" %s: Incompatible type of boundary condition by default.\n"
163                 " Please modify your settings.\n"), __func__);
164 
165   cs_cdo_bc_face_t  *bc = _cdo_bc_face_create(is_steady, n_b_faces);
166 
167   if (n_b_faces == 0) /* In parallel run this situation may occur */
168     return  bc;
169 
170   /* Loop on the definition of each boundary condition */
171   for (int ii = 0; ii < n_defs; ii++) {
172 
173     const cs_xdef_t  *d = defs[ii];
174     const cs_zone_t  *z = cs_boundary_zone_by_id(d->z_id);
175 
176     switch (d->meta) {
177 
178     case CS_CDO_BC_DIRICHLET:
179       bc->n_nhmg_dir_faces += z->n_elts;
180       break;
181     case CS_CDO_BC_HMG_DIRICHLET:
182       bc->n_hmg_dir_faces += z->n_elts;
183       break;
184     case CS_CDO_BC_NEUMANN:
185       bc->n_nhmg_neu_faces += z->n_elts;
186       break;
187     case CS_CDO_BC_HMG_NEUMANN:
188       bc->n_hmg_neu_faces += z->n_elts;
189       break;
190     case CS_CDO_BC_ROBIN:
191       bc->n_robin_faces += z->n_elts;
192       break;
193 
194       /* For vector-valued equations only */
195     case CS_CDO_BC_SLIDING:
196       assert(dim > 1);
197       bc->n_sliding_faces += z->n_elts;
198       break;
199 
200       /* For vector-valued equations only */
201     case CS_CDO_BC_TANGENTIAL_DIRICHLET:
202       assert(dim > 1);
203       bc->n_circulation_faces += z->n_elts;
204       break;
205 
206     default:
207       bft_error(__FILE__, __LINE__, 0,
208                 " %s: This type of boundary condition is not handled.",
209                 __func__);
210     } /* End of switch */
211 
212     for (cs_lnum_t i = 0; i < z->n_elts; i++) {
213 
214       const cs_lnum_t bf_id = z->elt_ids[i];
215 
216       assert(bc->flag[bf_id] < 1);                         /* Not already set */
217       assert(bc->def_ids[bf_id] == CS_CDO_BC_DEFAULT_DEF); /* Not already set */
218       bc->flag[bf_id] = d->meta;
219       bc->def_ids[bf_id] = ii;  /* definition id */
220 
221     } /* Loop on faces associated to this definition */
222 
223   } /* Loop on definitions of boundary conditions */
224 
225   /* Set the default flag for all remaining unset faces */
226   for (cs_lnum_t i = 0; i < n_b_faces; i++) {
227     if (bc->flag[i] == 0) { /* Not set yet --> apply the default settings */
228 
229       assert(bc->def_ids[i] == CS_CDO_BC_DEFAULT_DEF);
230       bc->flag[i] = default_flag;
231       if (default_flag & CS_CDO_BC_HMG_DIRICHLET)
232         bc->n_hmg_dir_faces++;
233       else if (default_flag & CS_CDO_BC_HMG_NEUMANN)
234         bc->n_hmg_neu_faces++;
235       else if (default_flag & CS_CDO_BC_SLIDING)
236         bc->n_sliding_faces++;
237       else
238         bft_error(__FILE__, __LINE__, 0,
239                   "%s: Invalid type of default boundary condition", __func__);
240 
241     } /* Unset face */
242   } /* Loop on border faces */
243 
244 #if defined(DEBUG) && !defined(NDEBUG)
245   /* Sanity check (there is no multiple definition or faces whitout settings */
246   cs_lnum_t n_set_faces =
247     bc->n_hmg_neu_faces + bc->n_nhmg_neu_faces +
248     bc->n_hmg_dir_faces + bc->n_nhmg_dir_faces +
249     bc->n_robin_faces + bc->n_sliding_faces + bc->n_circulation_faces;
250   if (n_set_faces != bc->n_b_faces)
251     bft_error(__FILE__, __LINE__, 0,
252               " %s: There are %ld faces without boundary conditions.\n"
253               " Please check your settings.",
254               __func__, (long)(bc->n_b_faces - n_set_faces));
255 #endif
256 
257   /* Allocate list of border faces by type of boundary conditions */
258   BFT_MALLOC(bc->hmg_dir_ids, bc->n_hmg_dir_faces, cs_lnum_t);
259   BFT_MALLOC(bc->nhmg_dir_ids, bc->n_nhmg_dir_faces, cs_lnum_t);
260   BFT_MALLOC(bc->hmg_neu_ids, bc->n_hmg_neu_faces, cs_lnum_t);
261   BFT_MALLOC(bc->nhmg_neu_ids, bc->n_nhmg_neu_faces, cs_lnum_t);
262   BFT_MALLOC(bc->robin_ids, bc->n_robin_faces, cs_lnum_t);
263   BFT_MALLOC(bc->sliding_ids, bc->n_sliding_faces, cs_lnum_t);
264   BFT_MALLOC(bc->circulation_ids, bc->n_circulation_faces, cs_lnum_t);
265 
266   /* Fill the allocated lists */
267   cs_lnum_t  shift[CS_PARAM_N_BC_TYPES];
268   for (int ii = 0; ii < CS_PARAM_N_BC_TYPES; ii++)
269     shift[ii] = 0;
270 
271   /* Loop on the border faces and append lists */
272   for (cs_lnum_t i = 0; i < n_b_faces; i++) {
273 
274     switch (bc->flag[i]) {
275 
276     case CS_CDO_BC_DIRICHLET:
277       bc->nhmg_dir_ids[shift[CS_PARAM_BC_DIRICHLET]] = i;
278       shift[CS_PARAM_BC_DIRICHLET] += 1;
279       break;
280     case CS_CDO_BC_HMG_DIRICHLET:
281       bc->hmg_dir_ids[shift[CS_PARAM_BC_HMG_DIRICHLET]] = i;
282       shift[CS_PARAM_BC_HMG_DIRICHLET] += 1;
283       break;
284     case CS_CDO_BC_NEUMANN:
285       /* TODO: check if we must add CS_CDO_BC_NEUMANN_FULL
286          to map to parameters 1 to 1 */
287       bc->nhmg_neu_ids[shift[CS_PARAM_BC_NEUMANN_FULL]] = i;
288       shift[CS_PARAM_BC_NEUMANN_FULL] += 1;
289     break;
290     case CS_CDO_BC_HMG_NEUMANN:
291       bc->hmg_neu_ids[shift[CS_PARAM_BC_HMG_NEUMANN]] = i;
292       shift[CS_PARAM_BC_HMG_NEUMANN] += 1;
293       break;
294     case CS_CDO_BC_ROBIN:
295       bc->robin_ids[shift[CS_PARAM_BC_ROBIN]] = i;
296       shift[CS_PARAM_BC_ROBIN] += 1;
297       break;
298 
299       /* For vector-valued equations only */
300     case CS_CDO_BC_SLIDING:
301       bc->sliding_ids[shift[CS_PARAM_BC_SLIDING]] = i;
302       shift[CS_PARAM_BC_SLIDING] += 1;
303       break;
304 
305       /* For vector-valued equations only */
306     case CS_CDO_BC_TANGENTIAL_DIRICHLET:
307       bc->circulation_ids[shift[CS_PARAM_BC_CIRCULATION]] = i;
308       shift[CS_PARAM_BC_CIRCULATION] += 1;
309       break;
310 
311     default:
312       bft_error(__FILE__, __LINE__, 0,
313                 " %s: This type of boundary condition is not handled.",
314                 __func__);
315 
316     } /* End of switch */
317 
318   } /* Loop on boundary faces */
319 
320   return bc;
321 }
322 
323 /*----------------------------------------------------------------------------*/
324 /*!
325  * \brief  Free a cs_cdo_bc_face_t structure
326  *
327  * \param[in, out]  face_bc   pointer to a cs_cdo_bc_face_t structure
328  *
329  * \return a NULL pointer
330  */
331 /*----------------------------------------------------------------------------*/
332 
333 cs_cdo_bc_face_t *
cs_cdo_bc_free(cs_cdo_bc_face_t * face_bc)334 cs_cdo_bc_free(cs_cdo_bc_face_t   *face_bc)
335 {
336   if (face_bc == NULL)
337     return face_bc;
338 
339   BFT_FREE(face_bc->flag);
340   BFT_FREE(face_bc->def_ids);
341 
342   BFT_FREE(face_bc->hmg_dir_ids);
343   BFT_FREE(face_bc->nhmg_dir_ids);
344   BFT_FREE(face_bc->hmg_neu_ids);
345   BFT_FREE(face_bc->nhmg_neu_ids);
346   BFT_FREE(face_bc->robin_ids);
347   BFT_FREE(face_bc->sliding_ids);
348   BFT_FREE(face_bc->circulation_ids);
349 
350   BFT_FREE(face_bc);
351 
352   return NULL;
353 }
354 
355 /*----------------------------------------------------------------------------*/
356 
357 END_C_DECLS
358