8.2
general documentation
Loading...
Searching...
No Matches
cs_defs.h
Go to the documentation of this file.
1#ifndef __CS_DEFS_H__
2#define __CS_DEFS_H__
3
4/*============================================================================
5 * Base macro and typedef definitions for system portability
6 *============================================================================*/
7
8/*
9 This file is part of code_saturne, a general-purpose CFD tool.
10
11 Copyright (C) 1998-2024 EDF S.A.
12
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 2 of the License, or (at your option) any later
16 version.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21 details.
22
23 You should have received a copy of the GNU General Public License along with
24 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
25 Street, Fifth Floor, Boston, MA 02110-1301, USA.
26*/
27
28/*----------------------------------------------------------------------------*/
29
30/*============================================================================
31 * Autoconf-defined macros
32 *============================================================================*/
33
34#if defined(HAVE_CONFIG_H)
35# include "cs_config.h"
36#endif
37
38/*============================================================================
39 * Internationalization
40 *============================================================================*/
41
42#ifdef __cplusplus
43extern "C" {
44#if 0
45} /* Fake brace to force Emacs auto-indentation back to column 0 */
46#endif
47#endif /* __cplusplus */
48
49#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
50
51# include <libintl.h>
52# define _(String) dgettext(PACKAGE, String)
53# ifdef gettext_noop
54# define N_(String) gettext_noop(String)
55# else
56# define N_(String) String
57# endif /* gettext_noop */
58
59#else
60
61# define _LIBINTL_H /* Prevent inclusion of <libintl.h> by other files
62 with incorrect or missing checks;
63 TODO locate files causing issues to avoid
64 requiring this workaround */
66# define _(String) (String)
67# define N_(String) String
68# define textdomain(String) (String)
69# define gettext(String) (String)
70# define dgettext(Domain,String) (String)
71# define dcgettext(Domain,String,Type) (String)
72# define bindtextdomain(Domain, Directory) (Domain)
73
74#endif /* ENABLE_NLS && HAVE_GETTEXT */
75
76#ifdef __cplusplus
77}
78#endif /* __cplusplus */
79
80/*============================================================================
81 * Parallelism
82 *============================================================================*/
83
84#if defined(HAVE_MPI) && !defined(CS_IGNORE_MPI)
85
86# include <mpi.h>
87
88# if !defined(MPI_VERSION) /* Defined in up-to-date MPI versions */
89# define MPI_VERSION 1
90# endif
91
92# if MPI_VERSION == 1
93# define MPI_Info int
94# define MPI_INFO_NULL 0
95# endif
96
97#endif
98
99#if defined(HAVE_OPENMP)
100
101# include <omp.h>
102
103#if _OPENMP >= 201307 /* simd construct available from OpenMP 4.0 */
104#undef HAVE_OPENMP_SIMD
105#define HAVE_OPENMP_SIMD 1
106#endif
107
108#endif
109
110/* Do we have accelerator support ? */
111
112#if defined(HAVE_CUDA)
113#define HAVE_ACCEL 1
114#elif defined(HAVE_SYCL)
115#define HAVE_ACCEL 1
116#elif defined(HAVE_OPENMP_TARGET)
117#define HAVE_ACCEL 1
118#endif
119
120/*============================================================================
121 * C99 Qualifiers
122 *============================================================================*/
123
124#ifndef __cplusplus /* C */
125
126/* inline provided by cs_config.h if necessary */
127
128#if !defined(__STDC_VERSION__)
129# define __STDC_VERSION__ 1989
130#endif
131
132/*
133 * Redefinition of "inline" et "restrict" qualifiers incompatible with
134 * some C89 compilers (standard in C99)
135 */
136
137#if (__STDC_VERSION__ < 199901L)
138
139# if defined(__GNUC__)
140# define inline __inline__
141# define restrict __restrict__
142# else
143# define inline
144# define restrict
145# endif
146
147#endif
148
149#else /* C++ */
150
151# ifndef HAVE_RESTRICT /* Must be provided by caller */
152# define restrict
153# endif
154
155#endif /* __cplusplus */
156
157/* Definition of a DEPRECATED decorator which may be called in the code */
158
159#if defined(__GNUC__) || defined(__clang__)
160# define DEPRECATED __attribute__((deprecated))
161#elif defined(_MSC_VER)
162# define DEPRECATED __declspec(deprecated)
163#else
164# define DEPRECATED
165#endif
166
167/*============================================================================
168 * Definitions that may not always be provided directly by the system
169 *============================================================================*/
170
171/*
172 * Obtain definitions such as that of size_t through stddef.h (C99 standard)
173 * if available (preferred method), or through stdlib.h (which defines
174 * malloc() and family and so must define size_t some way) otherwise.
175 */
176
177#if HAVE_STDDEF_H
178# include <stddef.h>
179#else
180# include <stdlib.h>
181#endif
182
183/*
184 * Usually stdint.h is included by inttypes.h, but only inttypes.h exists
185 * on certain systems, such as Tru64Unix.
186 */
187
188#if HAVE_STDINT_H
189# include <stdint.h>
190#elif HAVE_INTTYPES_H
191# include <inttypes.h>
192#endif
193
194/*
195 * Obtain the definition of off_t.
196 */
197
198#if defined(HAVE_SYS_TYPES_H)
199#include <sys/types.h>
200#endif
201
202/* C99 _Bool type */
203
204#if HAVE_STDBOOL_H
205# include <stdbool.h>
206#else
207# ifndef __cplusplus
208# ifndef HAVE__BOOL
209# define _Bool signed char;
210# endif
211# define bool _Bool
212# define false 0
213# define true 1
214# else
215# define _Bool bool;
216# endif
217# define __bool_true_false_are_defined 1
218#endif
219
220/* int32_t type */
221
222#if !defined(HAVE_INT32_T)
223# if (SIZEOF_INT == 4)
224typedef int int32_t;
225# elif (SIZEOF_SHORT == 4)
226typedef short int32_t;
227# else
228# error
229# endif
230#endif
231
232/* int64_t type */
233
234#if !defined(HAVE_INT64_T)
235# if (SIZEOF_INT == 8)
236typedef int int64_t;
237# elif (SIZEOF_LONG == 8)
238typedef long int64_t;
239# elif (HAVE_LONG_LONG == 8) /* SIZEOF_LONG_LONG not generally available */
240typedef long long int64_t;
241# else
242# error
243# endif
244#endif
245
246/* uint32_t type */
247
248#if !defined(HAVE_UINT32_T)
249# if (SIZEOF_INT == 4)
250typedef unsigned uint32_t;
251# elif (SIZEOF_SHORT == 4)
252typedef unsigned short uint32_t;
253# else
254# error
255# endif
256#endif
257
258/* uint64_t type */
259
260#if !defined(HAVE_UINT64_T)
261# if (SIZEOF_INT == 8)
262typedef unsigned uint64_t;
263# elif (SIZEOF_LONG == 8)
264typedef unsigned long uint64_t;
265# elif (HAVE_LONG_LONG) /* SIZEOF_LONG_LONG not generally available */
266typedef unsigned long long uint64_t;
267# else
268# error
269# endif
270#endif
271
272/*============================================================================
273 * General types and macros used throughout code_saturne
274 *============================================================================*/
275
276#ifdef __cplusplus
277extern "C" {
278#if 0
279} /* Fake brace to force Emacs auto-indentation back to column 0 */
280#endif
281#endif /* __cplusplus */
282
283/*----------------------------------------------------------------------------
284 * Variable value type.
285 *----------------------------------------------------------------------------*/
287typedef enum {
289 CS_DATATYPE_NULL, /* empty datatype */
290 CS_CHAR, /* character values */
291 CS_FLOAT, /* 4-byte floating point values */
292 CS_DOUBLE, /* 8-byte floating point values */
293 CS_UINT16, /* 2-byte unsigned integer values */
294 CS_INT32, /* 4-byte signed integer values */
295 CS_INT64, /* 8-byte signed integer values */
296 CS_UINT32, /* 4-byte unsigned integer values */
297 CS_UINT64 /* 8-byte unsigned integer values */
298
300
301/*----------------------------------------------------------------------------
302 * Basic types used by code_saturne
303 * They may be modified here to better map to a given library, with the
304 * following constraints:
305 * - cs_lnum_t must be signed
306 * - cs_gnum_t may be signed or unsigned
307 *----------------------------------------------------------------------------*/
308
309/* Global integer index or number */
310
311#if defined(HAVE_LONG_GNUM)
312 #if (SIZEOF_LONG == 8)
313 typedef unsigned long cs_gnum_t;
314 #elif (SIZEOF_LONG_LONG == 8)
315 typedef unsigned long long cs_gnum_t;
316 #else
317 #error
318 #endif
319#else
320 typedef unsigned cs_gnum_t;
321#endif
322
323/* Local integer index or number */
324
325#if defined(HAVE_LONG_LNUM)
326 typedef long cs_lnum_t;
327#else
328 typedef int cs_lnum_t;
329#endif
331/* Other types */
333typedef double cs_coord_t; /* Real number (coordinate value) */
335typedef double cs_real_t; /* Fortran double precision */
336typedef char cs_byte_t; /* Byte (untyped memory unit) */
337typedef unsigned short int cs_flag_t; /* Flag storing metadata */
338
339typedef double cs_nreal_t; /* Real number (normalized value) */
341/* Vector or array block types */
342
343typedef cs_lnum_t cs_lnum_2_t[2]; /* Vector of 2 local numbers */
344typedef cs_lnum_t cs_lnum_3_t[3]; /* Vector of 3 local numbers */
345
346typedef cs_coord_t cs_coord_3_t[3]; /* Vector of 3 real (coordinate)
347 values */
349typedef cs_real_t cs_real_2_t[2]; /* Vector of 2 real values */
350typedef cs_real_t cs_real_3_t[3]; /* Vector of 3 real values */
351typedef cs_real_t cs_real_4_t[4]; /* Vector of 4 real values */
352typedef cs_real_t cs_real_6_t[6]; /* Vector of 6 real values
353 (for symmetric tensor) */
354typedef cs_real_t cs_real_9_t[9]; /* Vector of 9 real values */
355typedef cs_real_t cs_real_10_t[10]; /* Vector of 10 real values */
357typedef cs_real_t cs_real_23_t[2][3]; /* Matrix of 2x3 real values */
359typedef cs_real_t cs_real_33_t[3][3]; /* Matrix of 3x3 real values */
360typedef cs_real_t cs_real_66_t[6][6]; /* Matrix of 6x6 real values */
361typedef cs_real_t cs_real_99_t[9][9]; /* Matrix of 9x9 real values */
363typedef cs_real_t cs_real_333_t[3][3][3]; /* tensor of 3x3x3 real values */
365typedef cs_real_t cs_real_34_t[3][4]; /* Matrix of 3x4 real values */
367typedef cs_real_t cs_real_63_t[6][3]; /* Matrix of 6x3 real values */
369typedef cs_real_t cs_real_69_t[6][9]; /* Matrix of 6x9 real values */
371typedef cs_real_33_t cs_real_332_t[2]; /* vector of 2 3x3 matrices
372 of real values */
373typedef cs_real_66_t cs_real_662_t[2]; /* vector of 2 6x6 matrices
374 of real values */
375
376typedef cs_nreal_t cs_nreal_3_t[3]; /* Vector of normalized real values
377 (i.e. unit vector) */
379typedef struct {
380
381 double val; /* Value */
382 int id; /* Id related to value */
383
385
386/* Vector-valued quantity stored using its measure (i.e. length) and
387 its direction given by a unitary vector */
389typedef struct {
390
391 double meas;
392 double unitv[3];
393
394} cs_nvec3_t;
395
396/* Mappings to MPI datatypes */
397/*---------------------------*/
399#if defined(HAVE_MPI) && !defined(CS_IGNORE_MPI)
400
401# define CS_MPI_REAL MPI_DOUBLE /* If cs_real_t is a double */
402
403/* MPI type for cs_gnum_t integer type (depends on configuration) */
404
405# if defined(HAVE_LONG_GNUM)
406# if (SIZEOF_LONG == 8)
407# define CS_MPI_GNUM MPI_UNSIGNED_LONG
408# elif (SIZEOF_LONG_LONG == 8)
409# if defined(MPI_UNSIGNED_LONG_LONG)
410# define CS_MPI_GNUM MPI_UNSIGNED_LONG_LONG
411# elif defined(MPI_LONG_LONG)
412# define CS_MPI_GNUM MPI_LONG_LONG
413# endif
414# endif
415# if !defined(CS_MPI_GNUM)
416# error
417# endif
418# else
419# define CS_MPI_GNUM MPI_UNSIGNED
420# endif
421
422/* MPI type for cs_lnum_t type */
423
424# if defined(HAVE_LONG_LNUM)
425# define CS_MPI_LNUM MPI_LONG
426# else
427# define CS_MPI_LNUM MPI_INT
428# endif
430# define CS_MPI_EFLAG MPI_UNSIGNED /* MPI type for cs_mflag_t type */
431# define CS_MPI_FLAG MPI_UNSIGNED_SHORT /* MPI type for cs_flag_t type */
432# define CS_MPI_COORD MPI_DOUBLE /* MPI type for cs_coord_t type */
433
434#endif /* defined(HAVE_MPI) && !defined(CS_IGNORE_MPI) */
435
436/* Mappings to code_saturne datatypes */
437/*------------------------------------*/
438
439#if defined(HAVE_LONG_GNUM)
440# define CS_GNUM_TYPE CS_UINT64
441#elif (SIZEOF_INT == 8)
442# define CS_GNUM_TYPE CS_UINT64
443#else
444# define CS_GNUM_TYPE CS_UINT32
445#endif
446
447#if defined(HAVE_LONG_LNUM)
448# if (SIZEOF_LONG == 8)
449# define CS_LNUM_TYPE CS_INT64
450# else
451# define CS_LNUM_TYPE CS_INT32
452# endif
453#else
454# if (SIZEOF_INT == 8)
455# define CS_LNUM_TYPE CS_INT64
456# else
457# define CS_LNUM_TYPE CS_INT32
458# endif
459#endif
460
461#if (SIZEOF_INT == 8)
462# define CS_INT_TYPE CS_INT64
463#else
464# define CS_INT_TYPE CS_INT32
465#endif
466
467#if (SIZEOF_INT == 8)
468# define CS_UINT_TYPE CS_UINT64
469#else
470# define CS_UINT_TYPE CS_UINT32
471#endif
473#define CS_FLAG_TYPE CS_UINT16
474#define CS_EFLAG_TYPE CS_UINT_TYPE
475#define CS_REAL_TYPE CS_DOUBLE
476#define CS_COORD_TYPE CS_DOUBLE
477
478/* Minimum size for OpenMP loops
479 * (will need benchmarking and tuning for various systems)
480 *---------------------------------------------------------*/
481
482#define CS_THR_MIN 128
483
484/* Cache line size, or multiple thereof */
485/*--------------------------------------*/
486
487#define CS_CL_SIZE 64
488
489/*----------------------------------------------------------------------------
490 * Type independent min an max (caution: the argument is evaluated)
491 *----------------------------------------------------------------------------*/
493#define CS_ABS(a) ((a) < 0 ? -(a) : (a))
494#define CS_MIN(a,b) ((a) < (b) ? (a) : (b))
495#define CS_MAX(a,b) ((a) > (b) ? (a) : (b))
496
497/*----------------------------------------------------------------------------
498 * Variable interlace type:
499 * {x1, y1, z1, x2, y2, z2, ...,xn, yn, zn} if interlaced
500 * {x1, x2, ..., xn, y1, y2, ..., yn, z1, z2, ..., zn} if non interlaced
501 *----------------------------------------------------------------------------*/
503typedef enum {
504
505 CS_INTERLACE, /* Variable is interlaced */
506 CS_NO_INTERLACE /* Variable is not interlaced */
507
509
510/*----------------------------------------------------------------------------
511 * Macro used to silence "unused argument" warnings.
512 *
513 * This is useful when a function must match a given function pointer
514 * type, but does not use all possible arguments.
515 *----------------------------------------------------------------------------*/
516
517#define CS_UNUSED(x) (void)(x)
518#define CS_NO_WARN_IF_UNUSED(x) (void)(x)
519
520/*----------------------------------------------------------------------------
521 * Macros for compilation with a C++ compiler
522 *----------------------------------------------------------------------------*/
523
524#undef BEGIN_C_DECLS
525#undef END_C_DECLS
526
527#if defined(__cplusplus)
528# define BEGIN_C_DECLS extern "C" {
529# define END_C_DECLS }
530#else
531# define BEGIN_C_DECLS
532# define END_C_DECLS
533#endif
534
535/*----------------------------------------------------------------------------
536 * Macros for function type qualifiers
537 *----------------------------------------------------------------------------*/
538
539#ifdef __NVCC__
540
541#define CS_F_HOST __host__
542#define CS_F_DEVICE __device__
543#define CS_F_HOST_DEVICE __host__ __device__
545#else
547#define CS_F_HOST
548#define CS_F_DEVICE
549#define CS_F_HOST_DEVICE
550
551#endif
552
553/*----------------------------------------------------------------------------
554 * Macros for Fortran interoperability
555 *----------------------------------------------------------------------------*/
556
557/*
558 * Macro for handling of different symbol names (underscored or not,
559 * lowercase or uppercase) between C and Fortran, for link resolution.
560 */
561
562#if !defined (__hpux)
563#define CS_PROCF(x, y) x##_
564#else
565#define CS_PROCF(x, y) x
566#endif
567
568/*
569 * Macro used to handle automatic "Fortran string length" arguments
570 * (not used by code_saturne calls, but set by many compilers).
571 * Some compilers may not
572 * support the variable length lists in mixed C/Fortran calls.
573 */
574
575#define CS_ARGF_SUPP_CHAINE , ...
576
577/*=============================================================================
578 * Global variables
579 *============================================================================*/
580
581/* Empty but non-NULL string */
582
583extern const char cs_empty_string[];
584
585/* Sizes and names associated with datatypes */
586
587extern const size_t cs_datatype_size[];
588extern const char *cs_datatype_name[];
589
590/* MPI Datatypes associated with code_saturne datatypes */
591
592#if defined(HAVE_MPI) && !defined(CS_IGNORE_MPI)
593
594extern MPI_Datatype cs_datatype_to_mpi[];
595
596#endif
597
598/* Global variables indicating task state */
599
600extern int cs_glob_n_threads; /* Number of threads */
601
602extern int cs_glob_rank_id; /* Rank in main MPI communicator */
603extern int cs_glob_n_ranks; /* Size of main MPI communicator */
604
605extern int cs_glob_node_rank_id; /* Rank on node in main MPI communicator */
606extern int cs_glob_node_n_ranks; /* Number of ranks on node of main
607 MPI communicator */
608
609#if defined(HAVE_MPI) && !defined(CS_IGNORE_MPI)
610
611extern MPI_Comm cs_glob_mpi_comm; /* Main MPI intra-communicator */
612
613#endif
614
615/*----------------------------------------------------------------------------
616 * Function pointer types
617 *----------------------------------------------------------------------------*/
618
619/*----------------------------------------------------------------------------*/
627/*----------------------------------------------------------------------------*/
628
629typedef void *
630(cs_destructor_t)(void *s);
631
632/*=============================================================================
633 * Public functions
634 *============================================================================*/
635
636/*----------------------------------------------------------------------------*/
637/*
638 * \brief Given a base index i, return the next index aligned with a size m.
639 *
640 * \param[in] i base index
641 * \param[in] m block size to align with
642 *
643 * \return aligned index
644 */
645/*----------------------------------------------------------------------------*/
646
647inline static cs_lnum_t
649 cs_lnum_t m)
650{
651 return ((i > 0) ? ((i-1)/m+1)*m : 0);
652}
653
654/*----------------------------------------------------------------------------*/
661/*----------------------------------------------------------------------------*/
662
663inline static int
665{
666#if defined(HAVE_OPENMP)
667 return omp_get_thread_num();
668#else
669 return 0;
670#endif
671}
672
673/*----------------------------------------------------------------------------*/
674
675#ifdef __cplusplus
676}
677#endif /* __cplusplus */
678
679#endif /* __CS_DEFS_H__ */
int cs_glob_n_ranks
Definition cs_defs.c:175
const char * cs_datatype_name[]
Definition cs_defs.c:143
const size_t cs_datatype_size[]
Definition cs_defs.c:133
int cs_glob_node_rank_id
Definition cs_defs.c:177
const char cs_empty_string[]
Definition cs_defs.c:129
int cs_glob_n_threads
Definition cs_defs.c:172
int cs_glob_node_n_ranks
Definition cs_defs.c:178
MPI_Datatype cs_datatype_to_mpi[]
Definition cs_defs.c:157
MPI_Comm cs_glob_mpi_comm
Definition cs_defs.c:183
int cs_glob_rank_id
Definition cs_defs.c:174
cs_datatype_t
Definition cs_defs.h:284
@ CS_FLOAT
Definition cs_defs.h:288
@ CS_CHAR
Definition cs_defs.h:287
@ CS_UINT16
Definition cs_defs.h:290
@ CS_INT64
Definition cs_defs.h:292
@ CS_UINT64
Definition cs_defs.h:294
@ CS_DOUBLE
Definition cs_defs.h:289
@ CS_UINT32
Definition cs_defs.h:293
@ CS_INT32
Definition cs_defs.h:291
@ CS_DATATYPE_NULL
Definition cs_defs.h:286
cs_lnum_t cs_lnum_3_t[3]
Definition cs_defs.h:341
cs_real_t cs_real_66_t[6][6]
6x6 matrix of floating-point values
Definition cs_defs.h:357
cs_real_t cs_real_33_t[3][3]
3x3 matrix of floating-point values
Definition cs_defs.h:356
char cs_byte_t
Definition cs_defs.h:333
void * cs_destructor_t(void *s)
Destroy a given structure.
Definition cs_defs.h:627
cs_real_t cs_real_69_t[6][9]
Definition cs_defs.h:366
cs_nreal_t cs_nreal_3_t[3]
Definition cs_defs.h:373
double cs_real_t
Floating-point value.
Definition cs_defs.h:332
cs_lnum_t cs_lnum_2_t[2]
vector of 2 local mesh-entity ids
Definition cs_defs.h:340
static int cs_get_thread_id(void)
Retrieve the associated thread id (0 if no OpenMP or if outside an OpenMP region)
Definition cs_defs.h:661
cs_real_t cs_real_10_t[10]
Definition cs_defs.h:352
cs_real_t cs_real_99_t[9][9]
Definition cs_defs.h:358
double cs_coord_t
Definition cs_defs.h:330
cs_real_t cs_real_34_t[3][4]
Definition cs_defs.h:362
cs_real_t cs_real_2_t[2]
vector of 2 floating-point values
Definition cs_defs.h:346
cs_coord_t cs_coord_3_t[3]
Definition cs_defs.h:343
cs_real_t cs_real_6_t[6]
vector of 6 floating-point values
Definition cs_defs.h:349
cs_real_66_t cs_real_662_t[2]
Definition cs_defs.h:370
cs_real_33_t cs_real_332_t[2]
vector of 2 3x3 matrices of floating-point values
Definition cs_defs.h:368
cs_interlace_t
Definition cs_defs.h:500
@ CS_INTERLACE
Definition cs_defs.h:502
@ CS_NO_INTERLACE
Definition cs_defs.h:503
static cs_lnum_t cs_align(cs_lnum_t i, cs_lnum_t m)
Given a base index i, return the next index aligned with a size m.
Definition cs_defs.h:645
cs_real_t cs_real_4_t[4]
vector of 4 floating-point values
Definition cs_defs.h:348
cs_real_t cs_real_333_t[3][3][3]
Definition cs_defs.h:360
cs_real_t cs_real_63_t[6][3]
Definition cs_defs.h:364
double cs_nreal_t
Definition cs_defs.h:336
cs_real_t cs_real_9_t[9]
Definition cs_defs.h:351
int cs_lnum_t
local mesh entity id
Definition cs_defs.h:325
cs_real_t cs_real_23_t[2][3]
Definition cs_defs.h:354
unsigned short int cs_flag_t
Definition cs_defs.h:334
cs_real_t cs_real_3_t[3]
vector of 3 floating-point values
Definition cs_defs.h:347
Definition cs_defs.h:376
double val
Definition cs_defs.h:378
int id
Definition cs_defs.h:379
Definition cs_defs.h:386
double meas
Definition cs_defs.h:388
double unitv[3]
Definition cs_defs.h:389