1 /*============================================================================
2 * Manage the enforcement of values at interior degrees of freedom (DoFs) and
3 * associated helper functions
4 *============================================================================*/
5
6 /*
7 This file is part of Code_Saturne, a general-purpose CFD tool.
8
9 Copyright (C) 1998-2021 EDF S.A.
10
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free Software
13 Foundation; either version 2 of the License, or (at your option) any later
14 version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
23 Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 */
25
26 /*----------------------------------------------------------------------------*/
27
28 #include "cs_defs.h"
29
30 /*----------------------------------------------------------------------------
31 * Standard C library headers
32 *----------------------------------------------------------------------------*/
33
34 #include <assert.h>
35 #include <string.h>
36 #include <float.h>
37
38 /*----------------------------------------------------------------------------
39 * Local headers
40 *----------------------------------------------------------------------------*/
41
42 #include <bft_mem.h>
43
44 #include "cs_cdo_bc.h"
45 #include "cs_parall.h"
46
47 /*----------------------------------------------------------------------------
48 * Header for the current file
49 *----------------------------------------------------------------------------*/
50
51 #include "cs_enforcement.h"
52
53 /*----------------------------------------------------------------------------*/
54
55 BEGIN_C_DECLS
56
57 /*=============================================================================
58 * Additional doxygen documentation
59 *============================================================================*/
60
61 /*!
62 \file cs_enforcement.c
63
64 \brief Structure and functions handling the way to enforce interior degrees
65 of freedom.
66 */
67
68 /*=============================================================================
69 * Local macro definitions
70 *============================================================================*/
71
72 #define CS_ENFORCEMENT_DBG 0
73
74 /*============================================================================
75 * Type definitions
76 *============================================================================*/
77
78 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
79
80 /*============================================================================
81 * Static variables
82 *============================================================================*/
83
84 /*============================================================================
85 * Private function prototypes
86 *============================================================================*/
87
88 /*============================================================================
89 * Public function prototypes
90 *============================================================================*/
91
92 /*----------------------------------------------------------------------------*/
93 /*!
94 * \brief Create and define a cs_enforcement_param_t structure
95 *
96 * \param[in] sel_type type of elements which have been selected
97 * \param[in] type way to set values for the selected elements
98 * \param[in] stride number of values to enforce by element
99 * \param[in] n_elts number of selected elements locally
100 * \param[in] elt_ids list of element ids
101 * \param[in] values array of values to enforce
102 *
103 * \return a pointer to a cs_enforcement_param_t structure
104 */
105 /*----------------------------------------------------------------------------*/
106
107 cs_enforcement_param_t *
cs_enforcement_param_create(cs_enforcement_selection_t sel_type,cs_enforcement_type_t type,int stride,cs_lnum_t n_elts,const cs_lnum_t * elt_ids,const cs_real_t * values)108 cs_enforcement_param_create(cs_enforcement_selection_t sel_type,
109 cs_enforcement_type_t type,
110 int stride,
111 cs_lnum_t n_elts,
112 const cs_lnum_t *elt_ids,
113 const cs_real_t *values)
114 {
115 cs_enforcement_param_t *efp = NULL;
116
117 BFT_MALLOC(efp, 1, cs_enforcement_param_t);
118
119 efp->selection_type = sel_type;
120 efp->type = type;
121 efp->stride = stride;
122 efp->n_elts = n_elts;
123
124 if (n_elts > 0 && values == NULL)
125 bft_error(__FILE__, __LINE__, 0,
126 "%s: No value for the enforcement\n", __func__);
127
128 BFT_MALLOC(efp->elt_ids, n_elts, cs_lnum_t);
129 memcpy(efp->elt_ids, elt_ids, n_elts*sizeof(cs_lnum_t));
130
131 switch (type) {
132
133 case CS_ENFORCEMENT_BY_CONSTANT:
134 BFT_MALLOC(efp->values, efp->stride, cs_real_t);
135 for (int k = 0; k < stride; k++)
136 efp->values[k] = values[k];
137 break;
138
139 case CS_ENFORCEMENT_BY_DOF_VALUES:
140 BFT_MALLOC(efp->values, stride*n_elts, cs_real_t);
141 memcpy(efp->values, values, stride*n_elts*sizeof(cs_real_t));
142 break;
143
144 default:
145 bft_error(__FILE__, __LINE__, 0,
146 "%s: Undefined way to enforce values for interior DoFs\n",
147 __func__);
148
149 }
150
151 return efp;
152 }
153
154 /*----------------------------------------------------------------------------*/
155 /*!
156 * \brief Copy a cs_enforcement_param_t structure
157 *
158 * \param[in] ref reference structure to copy
159 *
160 * \return a pointer to a cs_enforcement_param_t structure
161 */
162 /*----------------------------------------------------------------------------*/
163
164 cs_enforcement_param_t *
cs_enforcement_param_copy(const cs_enforcement_param_t * ref)165 cs_enforcement_param_copy(const cs_enforcement_param_t *ref)
166 {
167 cs_enforcement_param_t *dst = NULL;
168
169 if (ref == NULL)
170 return dst;
171
172 dst = cs_enforcement_param_create(ref->selection_type,
173 ref->type,
174 ref->stride,
175 ref->n_elts,
176 ref->elt_ids,
177 ref->values);
178
179 return dst;
180 }
181
182 /*----------------------------------------------------------------------------*/
183 /*!
184 * \brief Free a cs_enforcement_param_t structure
185 *
186 * \param[in, out] p_efp double pointer to the structure to free
187 */
188 /*----------------------------------------------------------------------------*/
189
190 void
cs_enforcement_param_free(cs_enforcement_param_t ** p_efp)191 cs_enforcement_param_free(cs_enforcement_param_t **p_efp)
192 {
193 if (p_efp == NULL)
194 return;
195
196 cs_enforcement_param_t *efp = *p_efp;
197
198 if (efp == NULL)
199 return;
200
201 BFT_FREE(efp->elt_ids);
202 BFT_FREE(efp->values);
203
204 BFT_FREE(efp);
205 *p_efp = NULL;
206 }
207
208 /*----------------------------------------------------------------------------*/
209 /*!
210 * \brief Log a cs_enforcement_param_t structure
211 *
212 * \param[in] eqname name of the related equation
213 * \param[in] efp pointer to a cs_enforcement_param_t structure
214 */
215 /*----------------------------------------------------------------------------*/
216
217 void
cs_enforcement_param_log(const char * eqname,const cs_enforcement_param_t * efp)218 cs_enforcement_param_log(const char *eqname,
219 const cs_enforcement_param_t *efp)
220 {
221 if (efp == NULL)
222 return;
223
224 if (efp->type == CS_ENFORCEMENT_BY_CONSTANT) {
225
226 switch (efp->selection_type) {
227
228 case CS_ENFORCEMENT_SELECTION_CELLS:
229 cs_log_printf(CS_LOG_SETUP, " * %s | Cell selection | Constant value:",
230 eqname);
231 break;
232
233 case CS_ENFORCEMENT_SELECTION_FACES:
234 cs_log_printf(CS_LOG_SETUP, " * %s | Face selection | Constant value:",
235 eqname);
236 break;
237
238 case CS_ENFORCEMENT_SELECTION_EDGES:
239 cs_log_printf(CS_LOG_SETUP, " * %s | Edge selection | Constant value:",
240 eqname);
241 break;
242
243 case CS_ENFORCEMENT_SELECTION_VERTICES:
244 cs_log_printf(CS_LOG_SETUP, " * %s | Vertex selection | Constant value:",
245 eqname);
246 break;
247
248 default:
249 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of selection.",
250 __func__);
251
252 } /* Switch on selection type */
253
254 for (int i = 0; i < efp->stride; i++)
255 cs_log_printf(CS_LOG_SETUP, " % -6.3e", efp->values[i]);
256 cs_log_printf(CS_LOG_SETUP, "\n");
257
258 }
259 else if (efp->type == CS_ENFORCEMENT_BY_DOF_VALUES) {
260
261 switch (efp->selection_type) {
262
263 case CS_ENFORCEMENT_SELECTION_CELLS:
264 cs_log_printf(CS_LOG_SETUP, " * %s | Cell selection | By DoF values\n",
265 eqname);
266 break;
267
268 case CS_ENFORCEMENT_SELECTION_FACES:
269 cs_log_printf(CS_LOG_SETUP, " * %s | Face selection | By DoF values\n",
270 eqname);
271 break;
272
273 case CS_ENFORCEMENT_SELECTION_EDGES:
274 cs_log_printf(CS_LOG_SETUP, " * %s | Edge selection | By DoF values\n",
275 eqname);
276 break;
277
278 case CS_ENFORCEMENT_SELECTION_VERTICES:
279 cs_log_printf(CS_LOG_SETUP, " * %s | Vertex selection | By DoF values\n",
280 eqname);
281 break;
282
283 default:
284 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of selection.",
285 __func__);
286
287 } /* Switch on selection type */
288
289 }
290 else
291 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition",
292 __func__);
293 }
294
295 /*----------------------------------------------------------------------------*/
296 /*!
297 * \brief Build a cs_enforcement_t structure for vertex-based scheme
298 *
299 * \param[in] connect pointer to a cs_cdo_connect_t
300 * \param[in] n_params number of enforcement parameters
301 * \param[in] efp_array array of parameter structures defining the enforcement
302 *
303 * \return an array with the values to enforce
304 */
305 /*----------------------------------------------------------------------------*/
306
307 cs_real_t *
cs_enforcement_define_at_vertices(const cs_cdo_connect_t * connect,int n_params,cs_enforcement_param_t ** efp_array)308 cs_enforcement_define_at_vertices(const cs_cdo_connect_t *connect,
309 int n_params,
310 cs_enforcement_param_t **efp_array)
311 {
312 if (n_params == 0)
313 return NULL;
314
315 cs_lnum_t n_vertices = connect->n_vertices;
316 cs_real_t *values = NULL;
317 int stride = (efp_array[0])->stride;
318
319 BFT_MALLOC(values, stride*n_vertices, cs_real_t);
320 for (cs_lnum_t i = 0; i < stride*n_vertices; i++)
321 values[i] = FLT_MAX; /* By default, max value */
322
323 /* Define the enforcement value for each vertex related to an enforcement */
324
325 for (int param_id = 0; param_id < n_params; param_id++) {
326
327 cs_enforcement_param_t *efp = efp_array[param_id];
328 assert(stride == efp->stride);
329
330 switch (efp->selection_type) {
331
332 case CS_ENFORCEMENT_SELECTION_VERTICES:
333
334 switch (efp->type) {
335
336 case CS_ENFORCEMENT_BY_CONSTANT:
337 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
338
339 cs_lnum_t vtx_id = efp->elt_ids[i];
340 for (int k = 0; k < stride; k++)
341 values[stride*vtx_id + k] = efp->values[k];
342
343 }
344 break;
345
346 case CS_ENFORCEMENT_BY_DOF_VALUES:
347 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
348
349 cs_lnum_t vtx_id = efp->elt_ids[i];
350 for (int k = 0; k < stride; k++)
351 values[stride*vtx_id + k] = efp->values[stride*i+k];
352
353 }
354 break;
355
356 default:
357 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition.\n",
358 __func__);
359
360 } /* End of switch on type */
361 break;
362
363 case CS_ENFORCEMENT_SELECTION_CELLS:
364 {
365 const cs_adjacency_t *c2v = connect->c2v;
366
367 switch (efp->type) {
368
369 case CS_ENFORCEMENT_BY_CONSTANT:
370 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
371
372 const cs_lnum_t c_id = efp->elt_ids[i];
373 for (cs_lnum_t j = c2v->idx[c_id]; j < c2v->idx[c_id+1]; j++)
374 for (int k = 0; k < stride; k++)
375 values[stride*c2v->ids[j] + k] = efp->values[k];
376
377 }
378 break;
379
380 case CS_ENFORCEMENT_BY_DOF_VALUES:
381 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
382
383 const cs_lnum_t c_id = efp->elt_ids[i];
384 for (cs_lnum_t j = c2v->idx[c_id]; j < c2v->idx[c_id+1]; j++)
385 for (int k = 0; k < stride; k++)
386 values[stride*c2v->ids[j] + k] = efp->values[stride*c_id + k];
387
388 }
389 break;
390
391 default:
392 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition.\n",
393 __func__);
394
395 } /* End of switch on type */
396
397 }
398 break;
399
400 default:
401 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of selection",
402 __func__);
403
404 } /* End of switch on selection */
405
406 } /* Loop on parameters */
407
408 /* Parallel synchronization: If there is a conflict between two definitions
409 or if a DoF at the parallel interface is defined and its corresponding one
410 is not defined, one takes the min. values (since one initializes with
411 FLT_MAX). */
412
413 cs_interface_set_t *ifs = connect->interfaces[CS_CDO_CONNECT_VTX_SCAL];
414
415 if (ifs != NULL)
416 cs_interface_set_min(ifs,
417 n_vertices, /* array size */
418 stride, /* array stride */
419 true, /* interlace */
420 CS_REAL_TYPE,
421 values);
422
423 return values;
424 }
425
426 /*----------------------------------------------------------------------------*/
427 /*!
428 * \brief Build a cs_enforcement_t structure for face-based scheme
429 *
430 * \param[in] connect pointer to a cs_cdo_connect_t
431 * \param[in] n_params number of enforcement parameters
432 * \param[in] efp_array array of parameter structures defining the enforcement
433 *
434 * \return an array with the values to enforce
435 */
436 /*----------------------------------------------------------------------------*/
437
438 cs_real_t *
cs_enforcement_define_at_faces(const cs_cdo_connect_t * connect,int n_params,cs_enforcement_param_t ** efp_array)439 cs_enforcement_define_at_faces(const cs_cdo_connect_t *connect,
440 int n_params,
441 cs_enforcement_param_t **efp_array)
442 {
443 if (n_params == 0)
444 return NULL;
445
446 cs_lnum_t n_faces = connect->n_faces[0];
447 cs_real_t *values = NULL;
448 int stride = (efp_array[0])->stride;
449
450 BFT_MALLOC(values, stride*n_faces, cs_real_t);
451 for (cs_lnum_t i = 0; i < stride*n_faces; i++)
452 values[i] = FLT_MAX; /* By default, max value */
453
454 /* Define the enforcement value for each vertex related to an enforcement */
455
456 for (int param_id = 0; param_id < n_params; param_id++) {
457
458 cs_enforcement_param_t *efp = efp_array[param_id];
459 assert(stride == efp->stride);
460
461 switch (efp->selection_type) {
462
463 case CS_ENFORCEMENT_SELECTION_FACES:
464
465 switch (efp->type) {
466
467 case CS_ENFORCEMENT_BY_CONSTANT:
468 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
469
470 cs_lnum_t f_id = efp->elt_ids[i];
471 for (int k = 0; k < stride; k++)
472 values[stride*f_id + k] = efp->values[k];
473
474 }
475 break;
476
477 case CS_ENFORCEMENT_BY_DOF_VALUES:
478 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
479
480 cs_lnum_t f_id = efp->elt_ids[i];
481 for (int k = 0; k < stride; k++)
482 values[stride*f_id + k] = efp->values[stride*i+k];
483
484 }
485 break;
486
487 default:
488 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition.\n",
489 __func__);
490
491 } /* End of switch on type */
492 break;
493
494 case CS_ENFORCEMENT_SELECTION_CELLS:
495 {
496 const cs_adjacency_t *c2f = connect->c2f;
497
498 switch (efp->type) {
499
500 case CS_ENFORCEMENT_BY_CONSTANT:
501 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
502
503 const cs_lnum_t c_id = efp->elt_ids[i];
504 for (cs_lnum_t j = c2f->idx[c_id]; j < c2f->idx[c_id+1]; j++)
505 for (int k = 0; k < stride; k++)
506 values[stride*c2f->ids[j] + k] = efp->values[k];
507
508 }
509 break;
510
511 case CS_ENFORCEMENT_BY_DOF_VALUES:
512 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
513
514 const cs_lnum_t c_id = efp->elt_ids[i];
515 for (cs_lnum_t j = c2f->idx[c_id]; j < c2f->idx[c_id+1]; j++)
516 for (int k = 0; k < stride; k++)
517 values[stride*c2f->ids[j] + k] = efp->values[stride*c_id + k];
518
519 }
520 break;
521
522 default:
523 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition.\n",
524 __func__);
525
526 } /* End of switch on type */
527
528 }
529 break;
530
531 default:
532 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of selection",
533 __func__);
534
535 } /* End of switch on selection */
536
537 } /* Loop on parameters */
538
539 /* Parallel synchronization: If there is a conflict between two definitions
540 or if a DoF at the parallel interface is defined and its corresponding one
541 is not defined, one takes the min. values (since one initializes with
542 FLT_MAX). */
543
544 cs_interface_set_t *ifs = connect->interfaces[CS_CDO_CONNECT_FACE_SP0];
545
546 if (ifs != NULL)
547 cs_interface_set_min(ifs,
548 n_faces, /* array size */
549 stride, /* array stride */
550 true, /* interlace */
551 CS_REAL_TYPE,
552 values);
553
554 return values;
555 }
556
557 /*----------------------------------------------------------------------------*/
558 /*!
559 * \brief Build a cs_enforcement_t structure for edge-based scheme
560 *
561 * \param[in] connect pointer to a cs_cdo_connect_t
562 * \param[in] n_params number of enforcement parameters
563 * \param[in] efp_array array of parameter structures defining the enforcement
564 *
565 * \return an array with the values to enforce
566 */
567 /*----------------------------------------------------------------------------*/
568
569 cs_real_t *
cs_enforcement_define_at_edges(const cs_cdo_connect_t * connect,int n_params,cs_enforcement_param_t ** efp_array)570 cs_enforcement_define_at_edges(const cs_cdo_connect_t *connect,
571 int n_params,
572 cs_enforcement_param_t **efp_array)
573 {
574 if (n_params == 0)
575 return NULL;
576
577 cs_lnum_t n_edges = connect->n_edges;
578 cs_real_t *values = NULL;
579 int stride = (efp_array[0])->stride;
580
581 BFT_MALLOC(values, stride*n_edges, cs_real_t);
582 for (cs_lnum_t i = 0; i < stride*n_edges; i++)
583 values[i] = FLT_MAX; /* By default, max value */
584
585 /* Define the enforcement value for each vertex related to an enforcement */
586
587 for (int param_id = 0; param_id < n_params; param_id++) {
588
589 cs_enforcement_param_t *efp = efp_array[param_id];
590 assert(stride == efp->stride);
591
592 switch (efp->selection_type) {
593
594 case CS_ENFORCEMENT_SELECTION_EDGES:
595
596 switch (efp->type) {
597
598 case CS_ENFORCEMENT_BY_CONSTANT:
599 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
600
601 cs_lnum_t f_id = efp->elt_ids[i];
602 for (int k = 0; k < stride; k++)
603 values[stride*f_id + k] = efp->values[k];
604
605 }
606 break;
607
608 case CS_ENFORCEMENT_BY_DOF_VALUES:
609 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
610
611 cs_lnum_t f_id = efp->elt_ids[i];
612 for (int k = 0; k < stride; k++)
613 values[stride*f_id + k] = efp->values[stride*i+k];
614
615 }
616 break;
617
618 default:
619 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition.\n",
620 __func__);
621
622 } /* End of switch on type */
623 break;
624
625 case CS_ENFORCEMENT_SELECTION_CELLS:
626 {
627 const cs_adjacency_t *c2e = connect->c2e;
628
629 switch (efp->type) {
630
631 case CS_ENFORCEMENT_BY_CONSTANT:
632 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
633
634 const cs_lnum_t c_id = efp->elt_ids[i];
635 for (cs_lnum_t j = c2e->idx[c_id]; j < c2e->idx[c_id+1]; j++)
636 for (int k = 0; k < stride; k++)
637 values[stride*c2e->ids[j] + k] = efp->values[k];
638
639 }
640 break;
641
642 case CS_ENFORCEMENT_BY_DOF_VALUES:
643 for (cs_lnum_t i = 0; i < efp->n_elts; i++) {
644
645 const cs_lnum_t c_id = efp->elt_ids[i];
646 for (cs_lnum_t j = c2e->idx[c_id]; j < c2e->idx[c_id+1]; j++)
647 for (int k = 0; k < stride; k++)
648 values[stride*c2e->ids[j] + k] = efp->values[stride*c_id + k];
649
650 }
651 break;
652
653 default:
654 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of definition.\n",
655 __func__);
656
657 } /* End of switch on type */
658
659 }
660 break;
661
662 default:
663 bft_error(__FILE__, __LINE__, 0, "%s: Invalid type of selection",
664 __func__);
665
666 } /* End of switch on selection */
667
668 } /* Loop on parameters */
669
670 /* Parallel synchronization: If there is a conflict between two definitions
671 or if a DoF at the parallel interface is defined and its corresponding one
672 is not defined, one takes the min. values (since one initializes with
673 FLT_MAX). */
674
675 cs_interface_set_t *ifs = connect->interfaces[CS_CDO_CONNECT_EDGE_SCAL];
676
677 if (ifs != NULL)
678 cs_interface_set_min(ifs,
679 n_edges, /* array size */
680 stride, /* array stride */
681 true, /* interlace */
682 CS_REAL_TYPE,
683 values);
684
685 return values;
686 }
687
688 /*----------------------------------------------------------------------------*/
689 /*!
690 * \brief Build the cell-wise value to enforce
691 *
692 * \param[in] forced_values values to enforce or FLT_MAX
693 * \param[in, out] csys pointer to a cs_cell_sys_t structure
694 * \param[in, out] cw_forced_values local values to enforce
695 *
696 * \return true if at least one DoF has to be enforced
697 */
698 /*----------------------------------------------------------------------------*/
699
700 bool
cs_enforcement_dofs_cw(const cs_real_t * forced_values,cs_cell_sys_t * csys,cs_real_t * cw_forced_values)701 cs_enforcement_dofs_cw(const cs_real_t *forced_values,
702 cs_cell_sys_t *csys,
703 cs_real_t *cw_forced_values)
704 {
705 assert(forced_values != NULL && cw_forced_values != NULL);
706
707 /* cw_forced_values is initialized by the calling function */
708
709 /* Initialization */
710
711 bool has_enforcement = false;
712
713 for (int i = 0; i < csys->n_dofs; i++) {
714
715 csys->dof_is_forced[i] = false; /* Not enforced by default */
716
717 /* In case of a Dirichlet BC or a circulation BC, this BC is applied and
718 the enforcement is ignored. A dirichlet BC is included inside the
719 circulation condition */
720
721 if (!cs_cdo_bc_is_circulation(csys->dof_flag[i])) {
722
723 cs_real_t _val = forced_values[csys->dof_ids[i]];
724 if (_val < FLT_MAX) {
725
726 cw_forced_values[i] = _val;
727 has_enforcement = true;
728 csys->dof_is_forced[i] = true;
729
730 }
731
732 } /* DoF is not associated to a Dirichlet BCs */
733
734 } /* Loop on cell-wise DoFs */
735
736 return has_enforcement;
737 }
738
739 /*----------------------------------------------------------------------------*/
740
741 END_C_DECLS
742