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