commit 7931abdb3a38702965db98487207b7d59f15be91
parent 806c14f4e28b2f73471c19e88d8b9fda4091d7d6
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 14 Mar 2022 10:08:07 +0100
Merge branch 'release_0.8'
Diffstat:
27 files changed, 3110 insertions(+), 2254 deletions(-)
diff --git a/README.md b/README.md
@@ -22,7 +22,10 @@ It also depends on the
[star-stl](https://gitlab.com/meso-star/star-stl) and
[stardis-solver](https://gitlab.com/meso-star/stardis-solver) libraries
as well as on the [OpenMP](http://www.openmp.org) 2.0 specification to
-parallelize its computations.
+parallelize its computations. It may depend on
+[OpenMPI](https://www.open-mpi.org/) 2.0 if distributed memory parallelism
+is enabled via the `ENABLE_MPI` variable of the CMake file.
+
First ensure that CMake and a C compiler are installed on your system.
@@ -33,6 +36,18 @@ variable the install directories of its dependencies.
## Release notes
+## Version 0.8
+
+- Add a new option to support non-linear radiative transfer computations.
+- Changes in input file's format to support non-linear radiative transfer by
+ adding reference temperatures on interfaces.
+- Add optional support for MPI (must be enabled at compile time, default is OFF).
+- Change random number generator type to use Threefry.
+- Change the format of binary Green files. A new public header file is now
+ installed that describes all types involved in binary Green files.
+- Fix a crash on an exit-on-error execution path.
+- Fix parsing of command-line options.
+
### Version 0.7.2
Fix the binary file format of the green function: the fileformat has been
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+# Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,6 +17,12 @@ cmake_minimum_required(VERSION 3.0)
project(stardis C)
set(SDIS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src)
+set(SDIS_SGT_DIR ${PROJECT_SOURCE_DIR}/../stardis-green-types)
+
+
+option(ENABLE_MPI
+ "Enable the support of distributed parallelism \
+using the Message Passing Interface specification." OFF)
if(CMAKE_HOST_UNIX)
set(STARDIS_DOC "TROFF" CACHE STRING
@@ -35,8 +41,10 @@ set_property(CACHE STARDIS_DOC PROPERTY STRINGS
###############################################################################
# Generate files
###############################################################################
-set(STARDIS_ARGS_DEFAULT_AMBIENT_TEMP "300")
+set(STARDIS_ARGS_DEFAULT_TRAD "300")
+set(STARDIS_ARGS_DEFAULT_TRAD_REFERENCE "300")
set(STARDIS_ARGS_DEFAULT_COMPUTE_TIME "INF")
+set(STARDIS_ARGS_DEFAULT_PICARD_ORDER "1")
set(STARDIS_ARGS_DEFAULT_RENDERING_FOV "70") # degrees
set(STARDIS_ARGS_DEFAULT_RENDERING_IMG_HEIGHT "480")
set(STARDIS_ARGS_DEFAULT_RENDERING_IMG_WIDTH "640")
@@ -46,7 +54,6 @@ set(STARDIS_ARGS_DEFAULT_RENDERING_SPP "4")
set(STARDIS_ARGS_DEFAULT_RENDERING_TGT "0, 0, 0")
set(STARDIS_ARGS_DEFAULT_RENDERING_TIME "INF, INF")
set(STARDIS_ARGS_DEFAULT_RENDERING_UP "0, 0, 1")
-set(STARDIS_ARGS_DEFAULT_REFERENCE_TEMP "300")
set(STARDIS_ARGS_DEFAULT_SAMPLES_COUNT "10000")
set(STARDIS_ARGS_DEFAULT_SCALE_FACTOR "1")
set(STARDIS_ARGS_DEFAULT_VERBOSE_LEVEL "1")
@@ -55,8 +62,8 @@ configure_file(${SDIS_SOURCE_DIR}/../doc/stardis.1.txt.in
${CMAKE_CURRENT_BINARY_DIR}/doc/stardis.1.txt @ONLY)
set(SDIS_VERSION_MAJOR 0)
-set(SDIS_VERSION_MINOR 7)
-set(SDIS_VERSION_PATCH 2)
+set(SDIS_VERSION_MINOR 8)
+set(SDIS_VERSION_PATCH 0)
set(SDIS_VERSION ${SDIS_VERSION_MAJOR}.${SDIS_VERSION_MINOR}.${SDIS_VERSION_PATCH})
configure_file(${SDIS_SOURCE_DIR}/stardis-default.h.in
@@ -65,20 +72,34 @@ configure_file(${SDIS_SOURCE_DIR}/stardis-default.h.in
configure_file(${SDIS_SOURCE_DIR}/stardis-version.h.in
${CMAKE_CURRENT_BINARY_DIR}/stardis-version.h @ONLY)
+set(STARDIS_GREEN_TYPES_VERSION "4")
+
+configure_file(${SDIS_SOURCE_DIR}/stardis-green-types.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types/stardis-green-types.h @ONLY)
+
+configure_file(${SDIS_SGT_DIR}/stardis-green-types-config-version.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types/stardis-green-types-config-version.cmake @ONLY)
+
###############################################################################
# Check dependencies
###############################################################################
-find_package(RCMake 0.4.1 REQUIRED)
+find_package(RCMake 0.4 REQUIRED)
find_package(RSys 0.12 REQUIRED)
find_package(StarGeom3D 0.1 REQUIRED)
find_package(Star3D 0.8 REQUIRED)
-find_package(StarEnc3D 0.5.3 REQUIRED)
-find_package(Stardis 0.12 REQUIRED)
-find_package(StarSTL 0.3.3 REQUIRED)
-find_package(StarSP 0.12 REQUIRED)
+find_package(StarEnc3D 0.5 REQUIRED)
+find_package(Stardis 0.13 REQUIRED)
+find_package(StarSTL 0.3 REQUIRED)
+find_package(StarSP 0.13 REQUIRED)
if(MSVC)
find_package(MuslGetopt REQUIRED)
endif()
+if(ENABLE_MPI)
+ find_package(MPI 2 REQUIRED)
+ set(CMAKE_C_COMPILER ${MPI_C_COMPILER})
+ include_directories(${MPI_INCLUDE_PATH})
+endif()
+
include_directories(
${RSys_INCLUDE_DIR}
@@ -88,7 +109,8 @@ include_directories(
${Stardis_INCLUDE_DIR}
${StarSTL_INCLUDE_DIR}
${StarSP_INCLUDE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR})
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types)
if(MSVC)
include_directories(${MuslGetopt_INCLUDE_DIR})
endif()
@@ -113,11 +135,14 @@ if(NOT STARDIS_DOC STREQUAL "NONE")
add_subdirectory(doc)
endif()
+add_subdirectory(stardis-green-types)
+
###############################################################################
# Configure and define targets
###############################################################################
set(SDIS_FILES_SRC
stardis-app.c
+ stardis-args.c
stardis-compute.c
stardis-fluid.c
stardis-intface.c
@@ -128,9 +153,11 @@ set(SDIS_FILES_SRC
set(SDIS_FILES_INC
stardis-app.h
+ stardis-args.h
stardis-compute.h
stardis-default.h.in
stardis-fluid.h
+ stardis-green-types.h.in
stardis-intface.h
stardis-output.h
stardis-parsing.h
@@ -160,6 +187,10 @@ set_target_properties(stardis
target_link_libraries(stardis
Stardis Star3D StarGeom3D StarEnc3D StarSTL StarSP RSys ${GETOPT_LIB} ${MATH_LIB})
+if(ENABLE_MPI)
+ set_target_properties(stardis PROPERTIES COMPILE_DEFINITIONS "STARDIS_ENABLE_MPI")
+endif()
+
###############################################################################
# Define output & install directories
###############################################################################
@@ -169,5 +200,7 @@ install(TARGETS stardis
RUNTIME DESTINATION bin)
install(FILES ${SDIS_FILES_DOC} DESTINATION share/doc/stardis)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/stardis-version.h
+ DESTINATION include/stardis)
rcmake_copy_runtime_libraries(stardis)
diff --git a/cmake/stardis-green-types/CMakeLists.txt b/cmake/stardis-green-types/CMakeLists.txt
@@ -0,0 +1,53 @@
+# Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 3.0)
+
+set(STARDIS_SGT_DIR ${PROJECT_SOURCE_DIR}/../stardis-green-types)
+
+################################################################################
+# Copy stardis-green-types CMake files
+################################################################################
+set(SGT_NAMES
+ stardis-green-types-config)
+
+set(SGT_FILES)
+foreach(_name IN LISTS SGT_NAMES)
+ set(_src ${STARDIS_SGT_DIR}/${_name}.cmake)
+ set(_dst ${CMAKE_CURRENT_BINARY_DIR}/${_name}.cmake)
+ add_custom_command(
+ OUTPUT ${_dst}
+ COMMAND ${CMAKE_COMMAND} -E copy ${_src} ${_dst}
+ DEPENDS ${_src}
+ COMMENT "Copy the CMake file ${_src}"
+ VERBATIM)
+ list(APPEND SGT_FILES ${_dst})
+endforeach()
+add_custom_target(sgt-cmake ALL DEPENDS ${SGT_FILES})
+
+################################################################################
+# Install stardis-green-types CMake Files
+################################################################################
+list(APPEND SGT_FILES ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types-config-version.cmake)
+
+install(FILES ${SGT_FILES}
+ DESTINATION lib/cmake/stardis-green-types)
+
+################################################################################
+# Install stardis-green-types header Files
+################################################################################
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types.h
+ DESTINATION include/stardis/)
diff --git a/doc/stardis-input.5.txt b/doc/stardis-input.5.txt
@@ -76,7 +76,6 @@ description.
[verse]
_______
<thermal-system> ::= <description-lines>
- [ <scaling-factor> ]
<description-lines> ::= <description-line>
[ <description-lines> ]
@@ -84,8 +83,8 @@ _______
<description-line> ::= [ <medium-frontier> ] [ <comment> ]
| [ <medium-boundary> ] [ <comment> ]
| [ <media-connection> ] [ <comment> ]
-
-<scaling-factor> ::= "SCALE" <scaling_factor> [ <comment> ]
+ | [ <scaling-factor> ] [ <comment> ] # at most once
+ | [ <radiative-temps> ] [ <comment > ] # at most once
-------------------------------------
@@ -117,22 +116,26 @@ _______
<triangles>
-<h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID" <bound-name> <emissivity> \
+<h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID" <bound-name> <Tref> <emissivity> \
<specular-fraction> <hc> <outside-temperature> \
<triangles>
-<h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID" <bound-name> <emissivity> \
+<h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID" <bound-name> <Tref> <emissivity> \
<specular-fraction> <hc> <outside-temperature> \
<triangles>
<f-bound-for-solid> ::= "F_BOUNDARY_FOR_SOLID" <bound-name> <flux> <triangles>
-<solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION" <bound-name> <emissivity> \
+<solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION" <bound-name> <Tref> <emissivity> \
<specular-fraction> <hc> <triangles>
<solid-solid-connect> ::= "SOLID_SOLID_CONNECTION" <bound-name> \
<contact-resistance> <triangles>
+<scaling-factor> ::= "SCALE" <scaling_factor> [ <comment> ]
+
+<radiative-temps> ::= "TRAD" <radiative-temp> <radiative-temp-ref>
+
-------------------------------------
<medium-name> ::= STRING # no space allowed, must not be parsable as a
@@ -163,6 +166,8 @@ _______
<bound-name> ::= STRING # no space allowed
+<Tref> ::= REAL # in [0, inf)
+
<emissivity> ::= REAL # in [0, 1]
<specular-fraction> ::= REAL # in [0, 1]
@@ -175,6 +180,10 @@ _______
<triangles> ::= <file-name> [ <triangles> ]
+<radiative-temp> ::= REAL # in [0, inf)
+
+<radiative-temp-ref> ::= REAL # in [0, inf)
+
-------------------------------------
<side-specifier> ::= "FRONT" | "BACK" | "BOTH"
@@ -199,11 +208,12 @@ one or ore ASCII characters, including numbers and special characters like
spacing* either escaped or not. Names are case-sensitive and two different
description lines, either in the same description file or from different
description files, cannot use the same name. Additionaly, medium and boundary
-names cannot be parsable as a number, nor be one of the few keywords defined
+names cannot be parsable as a number, nor be one of the keywords defined
by the present grammar (AUTO, BACK, BOTH, FLUID, FRONT, F_BOUNDARY_FOR_SOLID,
H_BOUNDARY_FOR_FLUID, H_BOUNDARY_FOR_SOLID, SCALE, SOLID,
SOLID_FLUID_CONNECTION, T_BOUNDARY_FOR_FLUID, T_BOUNDARY_FOR_SOLID, UNKNOWN) or
-their lowercase counterparts.
+their lowercase counterparts. Finally, description names cannot be longer than
+63 characters.
EXAMPLES
--------
@@ -212,10 +222,12 @@ the file cube.stl and the solid medium properties are lambda=0.1, rho=25, cp=2.
The numerical parameter delta, that is used for solid conductive walks, is
0.05. The initial temperature of the cube is 0°K and its volumic power is 0.
The boundary properties are emisivity=0, specular-fraction=0, h=10 and
-external-temperature = 100°K.
+external-temperature = 100°K, while the reference temperature for radiative
+transfer linearization in the Picard algorithm is set to 300°K.
+.
.......
SOLID Cube 0.1 25 2 0.05 0 0 FRONT cube.stl
-H_BOUNDARY_FOR_SOLID HdT 0 0 10 100 cube.stl
+H_BOUNDARY_FOR_SOLID HdT 300 0 0 10 100 cube.stl
.......
SEE ALSO
diff --git a/doc/stardis-output.5.txt b/doc/stardis-output.5.txt
@@ -210,7 +210,7 @@ Note that to be able to explore different values of volumic power when
applying the Green function, it must have been generated with these values
being non-zero. On the other hand, any temperature or flux value in boundary
descriptions can be modified when applying the Green function, as well as the
-ambient temperature.
+ambient radiative temperature (Trad).
The output in green mode is made of tables containing the different media and
boundaries and their imposed temperature, flux and volumic power values,
@@ -222,38 +222,40 @@ be computed as the mean and standard deviation of the samples of the *Green
function* computed using these settings. Each sample can be computed as
follows:
-* Get the temperature of the ending boundary, medium or ambient;
+* Get the temperature of the ending boundary, medium or Trad;
* Add the temperature gain of each power term;
* Add the temperature gain of each flux term.
=== BINARY GREEN
-Thereafter is the format of binary Green outputs. This output is produced by
-fwrite calls and does not take care of endianness. Comments include the C type
-of the written data.
+Binary Green outputs are formated according to the various C types from the
+*stardis-green.h* header file. The output begins with a header (of type struct
+green_file_header) that includes counts, followed by descriptions (of type
+struct green_description) and samples. Thereafter is the format of binary
+Green outputs. This output is produced by fwrite calls and does not take care
+of endianness. Comments include the C type of the written data.
[verse]
_______
-<binary-green> ::= "BINGREEN" # char[8]
+<binary-green> ::= "GREEN_BIN_FILE:" # char[16]
+ <file_format_version> # unsigned
#descriptions # unsigned
#solids # unsigned
#fluids # unsigned
- #t-boundaries # unsigned
#h-boundaries # unsigned
- #flux-boundaries # unsigned
+ #t-boundaries # unsigned
+ #f-boundaries # unsigned
#solid-fluid-connections # unsigned
- names-pool-size # size of concatenated description names
- # unsigned
+ #solid-solid-connections # unsigned
#ok-samples # size_t
#failed-samples # size_t
- <descriptions>
- <concatenated-names> # char[names-pool-size]
- ambient-temperature # double
- reference-temperature # double
+ Trad # double
+ Trad-reference # double
time-range # double[2]
+ <descriptions>
<samples>
-<descriptions> ::= description # struct description
+<descriptions> ::= description # struct green_description
<descriptions> # #descriptions descriptions
<samples> ::= <sample>
@@ -261,111 +263,11 @@ _______
---------------------
-<sample> ::= <sample-header> # struct path_header
- <ids> # unsigned[header.pcount + header.fcount]
- <weights> # double[header.pcount + header.fcount]
+<sample> ::= <sample-header> # struct green_sample_header
+ <ids> # unsigned[header.pw_count then header.fx_count]
+ <weights> # double[header.pw_count then header.fx_count]
_______
-[literal]
- /* The content of stuct str name members in descriptions is meaningless.
- * The name of the ith description is the ith nul-terminated string in
- * <concatenated-names>.
- * As a convenience, one could use char* baz to store a pointer to the
- * description's name into <concatenated-names>. */
- struct str {
- void* foo;
- size_t bar;
- char* baz;
- char qux[16];
- };
-
- struct mat_fluid {
- struct str name;
- double rho;
- double cp;
- double tinit;
- double imposed_temperature;
- double t0;
- int is_outside;
- int is_green;
- unsigned desc_id;
- unsigned fluid_id;
- };
-
- struct mat_solid {
- struct str name;
- double lambda;
- double rho;
- double cp;
- double delta;
- double tinit;
- double imposed_temperature;
- double vpower;
- double t0;
- int is_outside;
- int is_green;
- unsigned desc_id;
- unsigned solid_id;
- };
-
- struct t_boundary {
- struct str name;
- double imposed_temperature;
- unsigned mat_id;
- };
-
- struct h_boundary {
- struct str name;
- double emissivity;
- double specular_fraction;
- double hc;
- double imposed_temperature;
- unsigned mat_id;
- };
-
- struct solid_fluid_connect {
- struct str name;
- double emissivity;
- double specular_fraction;
- double hc;
- unsigned connection_id;
- };
-
- enum description_type {
- DESC_MAT_SOLID,
- DESC_MAT_FLUID,
- DESC_BOUND_H_FOR_FLUID,
- DESC_BOUND_H_FOR_SOLID,
- DESC_BOUND_T_FOR_SOLID,
- DESC_BOUND_F_FOR_SOLID,
- DESC_SOLID_FLUID_CONNECT,
- DESCRIPTION_TYPE_COUNT__,
- DESC_OUTSIDE
- };
-
- struct f_boundary {
- struct str name;
- double imposed_flux;
- unsigned mat_id;
- };
-
- struct description {
- enum description_type type;
- union {
- struct mat_fluid fluid;
- struct mat_solid solid;
- struct t_boundary t_boundary;
- struct f_boundary f_boundary;
- struct h_boundary h_boundary;
- struct solid_fluid_connect sf_connect;
- } d;
- };
-
- struct path_header {
- unsigned id;
- unsigned pcount, fcount;
- char at_initial;
- };
=== ASCII GREEN
@@ -390,13 +292,13 @@ _______
"# ID Name temperature"
<t-bounds>
"# H Boundaries"
- "# ID Name emissivity specular_fraction hc T_env"
+ "# ID Name ref_temperature emissivity specular_fraction hc T_env"
<h-bounds>
"# F Boundaries"
"# ID Name flux"
<f-bounds>
- "# Radiative Temperatures"
- "# ID Rad_Temp Lin_Temp"
+ "# Radiative Temperature"
+ "# ID Rad_Temp"
<rad-temps>
"# Samples"
"# end #power_terms #flux_terms power_term_1 ... \
@@ -425,7 +327,7 @@ _______
<f-bounds> ::= <f-bound>
<f-bounds> # #f-bounds f-bound descriptions
-<rad-temps> ::= <green-id> <rad-temp> <lin-temp>
+<rad-temps> ::= <green-id> <Trad> <Trad-ref>
<samples> ::= <sample>
<samples> # #samples sample descriptions
@@ -443,12 +345,11 @@ _______
<t-bound> ::= <green-id> <name> <temperature>
-<h-bound> ::= <green-id> <name> <emissivity> <specular_fraction> \
- <hc> <temperature>
+<h-bound> ::= <green-id> <name> <ref_temperature> <emissivity> \
+ <specular_fraction> <hc> <temperature>
<f-bound> ::= <green-id> <name> <flux>
-<rad-temps> ::= <green-id> <ambient-temp> <lin-temp>
<name> ::= STRING # no space allowed
@@ -468,6 +369,8 @@ _______
<temperature> ::= REAL # in [0, INF)
+<ref-temperature> ::= REAL # in [0, INF)
+
<emissivity> ::= REAL # in [0, 1]
<specular-fraction> ::= REAL # in [0, 1]
@@ -476,9 +379,9 @@ _______
<flux> ::= REAL # in (-INF, INF)
-<ambient-temp> ::= REAL # in [0, INF)
+<Trad> ::= REAL # in [0, INF)
-<lin-temp> ::= REAL # in [0, INF)
+<Trad-ref> ::= REAL # in [0, INF)
<green-id> ::= INTEGER # in [0 #green-sources[
@@ -488,7 +391,7 @@ _______
<end-type> ::= "T" # sample ends at an t-bound
| "H" # sample ends at an h-bound
# a sample cannot end at an f-bound
- | "A" # sample ends with ambient temperature
+ | "R" # sample ends with Trad
| "F" # sample ends in a fluid with known temperature
| "S" # sample ends in a solid with known temperature
@@ -540,11 +443,11 @@ _______
-------------------------------------
<end-name> ::= STRING # the name of the boundary at the end of the
- # heat path, or AMBIENT for radiative ending
+ # heat path, or TRAD for radiative ending
<end-id> ::= INTEGER # in [0 #boundaries]
# order is the order in the description file,
- # AMBIENT's id being #boundaries
+ # TRAD's id being #boundaries
<x> ::= REAL
@@ -900,7 +803,13 @@ computes a result, some of the heat paths (successful paths, erroneous paths,
or both) sampled during the simulation are written to files. Each path is
written in VTK [1] format, one VTK file per path. The path description can
include vertices' time if it makes sense, that is if the computation time is
-not INF.
+not INF. Due to the branching nature of non-linear Monte-Carlo algorithms,
+paths are made of strips. Whith a Picard order of 1, there is only a single
+strip, with higher orders, the number of strips can be greater than 1. As a
+result, the whole path is a tree: past the first strip, each strip can start
+from any vertex of one of the previous strips. This tree, when displaying the
+*Branch_id* field, starts with id 0, then increments each time a non-linearity
+leads to the creation of a new strip (to fetch a temperature).
[verse]
_______
@@ -911,31 +820,41 @@ _______
"DATASET POLYDATA"
"POINTS" #vertices "double"
<path-vertices>
- "LINES 1" #vertices+1
- <heat-path>
+ "LINES" #strips #vertices+#strips
+ <heat-strips>
+ "CELL_DATA" #strips
+ "SCALAR Path_Failure unsigned_char 1"
+ "LOOKUP_TABLE default"
+ <path-failures>
"POINT_DATA" #vertices
"SCALARS Vertex_Type unsigned_char 1"
"LOOKUP_TABLE default"
<vertices-types>
- "CELL_DATA 1"
- "SCALAR Path_type unsigned_char 1"
- "LOOKUP_TABLE default"
- <path-type>
"SCALARS Weight double 1"
"LOOKUP_TABLE default"
- <weigths>
+ <weights>
+ "SCALARS Branch_id int 1"
+ "LOOKUP_TABLE default"
+ <branch_ids>
[ <vertices-time> ] # if not steady
<path-vertices> ::= <real3>
<path-vertices> # #vertices vertices
-<heat-path> ::= #vertices "0" "1" ... #vertices-1
+<path-failures> ::= <path-failure>
+ <path-failures> # #strips failure statutes
+
+<heat-strips> ::= <heat-strip>
+ <heat-strips> # #strips strips
<vertices-types> ::= <vertice-type>
<vertices-types> # #vertices types
-<weigths> ::= REAL
- <weigths> # #vertices weigths
+<weights> ::= <weight>
+ <weights> # #vertices weights
+
+<branch_ids> ::= <branch_id>
+ <branch_ids> # #vertices ids
<vertices-time> ::= "SCALARS Time double 1"
"LOOKUP_TABLE default"
@@ -945,15 +864,23 @@ _______
<real3> ::= REAL REAL REAL
-<durations> ::= REAL # in [0, INF)
- <durations> # #vertices durations
+<path-failure> ::= "0" # SUCCESS
+ | "1" # FAILURE
+
+<heat-strip> ::= #strip_vertices <vtx_idx 1> ... <vtx_idx #strip_vertices>
<vertice-type> ::= "0" # CONDUCTION
| "1" # CONVECTION
| "2" # RADIATIVE
-<path-type> ::= "0" # SUCCESS
- | "1" # FAILURE
+<weight> ::= REAL
+
+<branch-id> ::= INTEGER in [0 Picard_Order]
+
+<durations> ::= REAL # in [0, INF)
+ <durations> # #vertices durations
+
+<vtx_idx> ::= INTEGER # in [0 #vertices[
_______
diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in
@@ -29,12 +29,14 @@ SYNOPSIS
*stardis* *-M* <__file__> [_option_]
DESCRIPTION
------------
-*stardis* solves coupled thermal systems under the linear assumption. Here
-coupled refers to conductive, convective and radiative transfers, and linear
-means that each phenomena is represented using a model that is linear
-with temperature. *stardis* can deal with complex geometries as well as
-high-frequency external solicitations over a very long period of time,
+*stardis* solves coupled thermal systems: conductive, convective and
+radiative transfers are solved together. The physical model used for
+conduction is the local unstationary heat conduction equation.
+Convection fluxes are assumed to be linear with temperature, and radiation
+is assumed to be integrated over the whole thermal spectral range,
+therefore radiative heat fluxes are proportionnal to a difference of
+temperatures to the power 4. *stardis* can deal with complex geometries as
+well as high-frequency external solicitations over a very long period of time,
relative to the characteristic time of the system. The provided system
description should comply with the *stardis-input*(5) format.
@@ -62,13 +64,28 @@ computer graphics technology which has already been a game changer in the
cinema industry (FX and animated movies), this theoretical framework can now
be practically used on the most geometrically complex systems.
-Everytime the linear assumption is relevant, this theoretical framework allows
-to encompass all the heat transfer mechanisms (conductive-convective-radiative)
-in an unified statistical model. Such systems can be solved by a Monte-Carlo
-approach just by sampling heat paths. This can be seen as an extension of
-Monte-Carlo algorithms that solve radiative transfer by sampling optical paths.
-A main property of this approach is that the resulting algorithms does not rely
-on a volume mesh of the system.
+Monte-Carlo algorithms associated with convective and conductive processes
+consist in sampling heat paths: this can be seen as an extension of
+Monte-Carlo algorithms that solve monochromatic radiative transfer.
+The radiative transfer algorithm, based on the Picard method, is also based
+on sampling radiative paths. However, since stardis solves the spectrally
+integrated radiative transfer, the process can be recursive: secondary heat
+paths (convective, conductive and radiative) may be necessary along the
+sampling of an initial radiative path.
+
+The solution may not be sufficiently converged with a Picard order equal
+to 1 in the presence of high temperature gradients.
+Increasing the Picard order may be necessary in this case, until the
+required convergence is reached.
+
+A main property of this approach is that the resulting algorithms do
+not rely on a volumic mesh of the system: only the representation
+of interfaces is necessary.
+
+*stardis* supports shared memory parallelism and relies on the Message
+Passing Interface specification [4] to parallelise its computations in a
+distributed memory environment; it can thus be run either directly or through
+a MPI process launcher like *mpirun(1)*.
[1] Delatorre et al., Monte Carlo advances and concentrated solar applications,
Solar Energy, 2014
@@ -79,6 +96,8 @@ Mathematical Statistics, 1949.
[3] Muller, Some continuous Monte-Carlo Methods for the Dirichlet Problem,
Transactions of the American Mathematical Society, 1956.
+[4] MPI specifications - https://www.mpi-forum.org/docs/
+
MANDATORY OPTIONS
-----------------
*-M* _file_::
@@ -186,10 +205,6 @@ EXCLUSIVE OPTIONS
OTHER OPTIONS
-------------
-*-a* _ambient_::
- Set the ambient radiative temperature for the whole system, in Kelvin. By
- default *ambient* is @STARDIS_ARGS_DEFAULT_AMBIENT_TEMP@.
-
*-d*::
Write the geometry to _standard output_ in VTK format along with various
properties, including possible errors. If this option is used, no
@@ -242,10 +257,13 @@ different temperature, flux or volumic power values.
Number of Monte-Carlo samples. By default *samples-count* is set to
@STARDIS_ARGS_DEFAULT_SAMPLES_COUNT@.
-*-r* _reference_::
- Set the reference temperature used for the linearization of the radiative
- transfer, in Kelvin. By default *reference*
- is @STARDIS_ARGS_DEFAULT_REFERENCE_TEMP@.
+*-o* _Picard_order_::
+ Determine the iteration level used with the Picard method to deal with
+ non-linear radiative transfer accross the model.
+ By default *Picard_order* is set to @STARDIS_ARGS_DEFAULT_PICARD_ORDER@.
+ Note that a Picard order greater than 1 is incompatible both with Green
+ computations and models including volumic power sources or non zero flux
+ at a boundary.
*-t* _threads-count_::
Hint on the number of threads to use. By default use as many threads as CPU
@@ -306,9 +324,11 @@ Compute 3 probe temperatures, ensuring statistical independence:
$ stardis -M model.txt -p 1,2.5,0,50,5000 -xstate1 -Xstate2
$ stardis -M model.txt -p 1,3.5,0,50,5000 -xstate2
+
+Use mpirun(1) to launch stardis on several hosts defined in the my_hosts file.
Render the system as described in *scene.txt* with default settings:
- $ stardis -M scene.txt -R :
+ $ mpirun --hostfile my_hosts stardis -M scene.txt -R :
Render the system as described in *scn.txt* at *t=100*, *spp=2*,
*img=800x600*, with output format *fmt=ht* and all other settings set to their
@@ -342,3 +362,4 @@ SEE ALSO
*sgreen*(1),
*htpp*(1)
*htrdr-image*(5)
+*mpirun(1)*
diff --git a/src/stardis-app.c b/src/stardis-app.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,6 +13,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#ifdef STARDIS_ENABLE_MPI
+#define _POSIX_C_SOURCE 200112L
+#endif
+
#include "stardis-app.h"
#include "stardis-output.h"
#include "stardis-compute.h"
@@ -32,8 +36,12 @@
#include <string.h>
-static const struct dummies DUMMIES_NULL = DUMMIES_NULL__;
+#ifdef STARDIS_ENABLE_MPI
+#include <stdio.h>
+#include <mpi.h>
+#endif
+static const struct dummies DUMMIES_NULL = DUMMIES_NULL__;
static const struct counts COUNTS_NULL = COUNTS_NULL__;
/*******************************************************************************
@@ -42,8 +50,7 @@ static const struct counts COUNTS_NULL = COUNTS_NULL__;
static res_T
read_model
(const struct darray_str* model_files,
- struct stardis* stardis,
- struct dummies* dummies)
+ struct stardis* stardis)
{
res_T res = RES_OK;
const struct str* files = NULL;
@@ -51,7 +58,7 @@ read_model
FILE* f = NULL;
struct txtrdr* txtrdr = NULL;
- ASSERT(model_files && stardis && dummies);
+ ASSERT(model_files && stardis);
files = darray_str_cdata_get(model_files);
FOR_EACH(i, 0, darray_str_size_get(model_files)) {
const char* name = str_cget(files + i);
@@ -69,7 +76,7 @@ read_model
ERR(txtrdr_read_line(txtrdr));
line = txtrdr_get_line(txtrdr);
if(!line) break;
- ERR(process_model_line(name, line, stardis, dummies));
+ ERR(process_model_line(name, line, stardis));
}
txtrdr_ref_put(txtrdr);
txtrdr = NULL;
@@ -80,6 +87,14 @@ read_model
stardis->scale_factor = STARDIS_DEFAULT_SCALE_FACTOR;
logger_print(stardis->logger, LOG_OUTPUT,
"Scaling factor is %g\n", stardis->scale_factor);
+ logger_print(stardis->logger, LOG_OUTPUT,
+ "Trad is %g, Trad reference is %g\n", stardis->trad, stardis->trad_ref);
+ stardis->t_range[0] = MMIN(stardis->t_range[0], stardis->trad_ref);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], stardis->trad_ref);
+ logger_print(stardis->logger, LOG_OUTPUT,
+ "System T range is [%g %g]\n", SPLIT2(stardis->t_range));
+ logger_print(stardis->logger, LOG_OUTPUT,
+ "Picard order is %u\n", stardis->picard_order);
ASSERT(!f && !txtrdr);
exit:
@@ -110,6 +125,7 @@ check_delta_and_create_solid
double ratio, delta_range[2] = { DBL_MAX, -DBL_MAX };
const double acceptance_ratio = 3;
struct senc3d_enclosure_header header;
+ struct solid* solid = description->d.solid;
ASSERT(stardis && description && description->type == DESC_MAT_SOLID);
@@ -118,7 +134,7 @@ check_delta_and_create_solid
if(stardis->senc3d_scn) {
/* Due to previous errors, senc3d_scn can be unavailable */
unsigned e, ecount = 0;
- const unsigned desc_id = description->d.solid.desc_id;
+ const unsigned desc_id = solid->desc_id;
/* The enclosures where created using description ids */
ERR(senc3d_scene_get_enclosure_count_by_medium(stardis->senc3d_scn,
@@ -153,31 +169,31 @@ check_delta_and_create_solid
logger_print(stardis->logger, LOG_WARNING,
"Solid '%s' is used in %u different enclosures that have different "
"delta requirements.\n",
- str_cget(&description->d.solid.name), ecount);
+ str_cget(&solid->name), ecount);
/* Delta needs to be substituted with actual value */
- if(description->d.solid.delta == DELTA_AUTO) {
- description->d.solid.delta = delta_range[0];
+ if(solid->delta == DELTA_AUTO) {
+ solid->delta = delta_range[0];
logger_print(stardis->logger, LOG_OUTPUT,
"Auto delta for solid '%s' set to %g\n",
- str_cget(&description->d.solid.name), description->d.solid.delta);
+ str_cget(&solid->name), solid->delta);
} else {
int too_small
- = (delta_range[0] > description->d.solid.delta * acceptance_ratio);
+ = (delta_range[0] > solid->delta * acceptance_ratio);
int too_big
- = (delta_range[0] * acceptance_ratio < description->d.solid.delta);
+ = (delta_range[0] * acceptance_ratio < solid->delta);
/* Check if user delta is OK */
if(too_small || too_big) {
logger_print(stardis->logger, LOG_WARNING,
"User delta for solid '%s' seems too %s: %g; "
"auto delta would have set it to %g.\n",
- str_cget(&description->d.solid.name), (too_big ? "big" : "small"),
- description->d.solid.delta, delta_range[0]);
+ str_cget(&solid->name), (too_big ? "big" : "small"),
+ solid->delta, delta_range[0]);
}
}
}
}
}
- ERR(create_solver_solid(stardis, &description->d.solid));
+ ERR(create_solver_solid(stardis, solid));
end:
if(enc) SENC3D(enclosure_ref_put(enc));
@@ -190,6 +206,58 @@ error:
* Public Functions
******************************************************************************/
+#ifdef STARDIS_ENABLE_MPI
+/* To be called after logger has been initialized
+ * and before stardis is initialized */
+res_T
+init_mpi
+ (int* pargc,
+ char** pargv[],
+ void (*prt_err_fn)(const char* msg, void* ctx),
+ void (*prt_warn_fn)(const char* msg, void* ctx))
+{
+ res_T res = RES_OK;
+ char buf[64];
+ int mpi_provided;
+
+ ASSERT(pargc && pargv && prt_err_fn && prt_warn_fn);
+
+ if(MPI_Init_thread(pargc, pargv, MPI_THREAD_MULTIPLE, &mpi_provided)
+ != MPI_SUCCESS)
+ {
+ prt_err_fn("Cannot init MPI\n", NULL);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ else if(mpi_provided != MPI_THREAD_MULTIPLE) {
+ const char* lvl;
+ switch(mpi_provided) {
+ case MPI_THREAD_SINGLE: lvl = "MPI_THREAD_SINGLE"; break;
+ case MPI_THREAD_FUNNELED: lvl = "MPI_THREAD_FUNNELED"; break;
+ case MPI_THREAD_SERIALIZED: lvl = "MPI_THREAD_SERIALIZED"; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ snprintf(buf, sizeof(buf)-1, "MPI support restricted to %s\n", lvl);
+ prt_warn_fn(buf, NULL);
+ }
+
+end:
+ return res;
+error:
+ goto end;
+}
+
+void
+finalize_mpi(void)
+{
+ int initialized;
+
+ CHK(MPI_Initialized(&initialized) == MPI_SUCCESS);
+ if(initialized)
+ CHK(MPI_Finalize() == MPI_SUCCESS);
+}
+#endif
+
res_T
stardis_init
(const struct args* args,
@@ -199,16 +267,17 @@ stardis_init
{
res_T tmp_res, res = RES_OK;
struct sg3d_sdisXd_scene_create_context create_context;
- struct dummies dummies = DUMMIES_NULL;
struct htable_intface htable_interfaces;
struct str str;
unsigned i, vcount, tcount, ocount, count;
int is_for_compute;
+ struct sdis_device_create_args dev_args;
ASSERT(args && logger && allocator && stardis);
str_init(allocator, &str);
/* Init everithing that cannot fail */
+ stardis->dummies = DUMMIES_NULL;
stardis->logger = logger;
stardis->allocator = allocator;
htable_intface_init(stardis->allocator, &htable_interfaces);
@@ -234,9 +303,13 @@ stardis_init
stardis->compute_surface.area = 0;
stardis->samples = args->samples;
stardis->nthreads = args->nthreads;
+ stardis->picard_order = args->picard_order;
stardis->scale_factor = -1; /* invalid value */
- stardis->ambient_temp = args->ambient_temp;
- stardis->ref_temp = args->ref_temp;
+ stardis->trad = STARDIS_DEFAULT_TRAD;
+ stardis->trad_ref = STARDIS_DEFAULT_TRAD_REFERENCE;
+ stardis->trad_def = 0;
+ stardis->geometry_initialized = 0;
+ d2(stardis->t_range, INF, -INF);
stardis->dump_paths = SDIS_HEAT_PATH_NONE;
if(args->dump_paths & DUMP_ERROR)
stardis->dump_paths |= SDIS_HEAT_PATH_FAILURE;
@@ -251,11 +324,30 @@ stardis_init
is_for_compute =
(stardis->mode & COMPUTE_MODES) && !(stardis->mode & MODE_DUMP_VTK);
- ERR(sdis_device_create(stardis->logger, stardis->allocator, stardis->nthreads,
- args->verbose, &stardis->dev));
+ dev_args.logger = stardis->logger;
+ dev_args.allocator = stardis->allocator;
+ dev_args.nthreads_hint = stardis->nthreads;
+ dev_args.verbosity = stardis->verbose;
+
+#ifdef STARDIS_ENABLE_MPI
+ logger_print(stardis->logger, LOG_OUTPUT, "MPI is enabled.\n");
+ /* Open MPI accepts the C/C++ argc and argv arguments to main,
+ * but neither modifies, interprets, nor distributes them: use NULL */
+ CHK(MPI_Initialized(&stardis->mpi_initialized) == MPI_SUCCESS);
+ if(stardis->mpi_initialized)
+ CHK(MPI_Comm_rank(MPI_COMM_WORLD, &stardis->mpi_rank) == MPI_SUCCESS);
+#else
+ logger_print(stardis->logger, LOG_OUTPUT, "MPI is disabled.\n");
+ stardis->mpi_initialized = 0;
+#endif
+
+ dev_args.use_mpi = stardis->mpi_initialized;
+
+ ERR(sdis_device_create(&dev_args, &stardis->dev));
ERR(init_geometry(stardis->logger, stardis->allocator, stardis->verbose,
&stardis->geometry));
+ stardis->geometry_initialized = 1;
if(args->mode & MODE_IR_COMPUTE) {
ERR(parse_camera(stardis->logger, args->camera, stardis));
@@ -272,7 +364,7 @@ stardis_init
else if(args->mode & MODE_DUMP_C_CHUNKS) {
ERR(str_set(&stardis->chunks_prefix, args->chunks_prefix));
}
- ERR(read_model(&args->model_files, stardis, &dummies));
+ ERR(read_model(&args->model_files, stardis));
create_context.geometry = stardis->geometry.sg3d;
create_context.app_interface_getter = geometry_get_interface;
@@ -394,8 +486,9 @@ stardis_init
scn_args.nprimitives = tcount;
scn_args.nvertices = vcount;
scn_args.fp_to_meter = stardis->scale_factor;
- scn_args.trad = stardis->ambient_temp;
- scn_args.tref = stardis->ref_temp;
+ scn_args.trad.temperature = stardis->trad;
+ scn_args.trad.reference = stardis->trad_ref;
+ d2_set(scn_args.t_range, stardis->t_range);
scn_args.context = &create_context;
res = sdis_scene_create(stardis->dev, &scn_args, &stardis->sdis_scn);
if(res != RES_OK) {
@@ -430,8 +523,13 @@ stardis_release
str_release(&stardis->bin_green_filename);
str_release(&stardis->end_paths_filename);
str_release(&stardis->chunks_prefix);
+ FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) {
+ struct description* d = darray_descriptions_data_get(&stardis->descriptions) +i;
+ release_description(d, stardis->allocator);
+ }
darray_descriptions_release(&stardis->descriptions);
- release_geometry(&stardis->geometry);
+ if(stardis->geometry_initialized)
+ release_geometry(&stardis->geometry);
darray_size_t_release(&stardis->compute_surface.primitives);
darray_sides_release(&stardis->compute_surface.sides);
darray_uint_release(&stardis->compute_surface.err_triangles);
@@ -441,6 +539,12 @@ stardis_release
}
darray_media_ptr_release(&stardis->media);
release_camera(&stardis->camera);
+ if(stardis->dummies.stardis_fluid) {
+ release_fluid(stardis->dummies.stardis_fluid, stardis->allocator);
+ }
+ if(stardis->dummies.stardis_solid) {
+ release_solid(stardis->dummies.stardis_solid, stardis->allocator);
+ }
}
res_T
@@ -473,8 +577,7 @@ error:
if(properties[(Rank)] == SG3D_UNSPECIFIED_PROPERTY) undef_count++;\
else {\
ASSERT(properties[(Rank)] < darray_descriptions_size_get(&stardis->descriptions));\
- ASSERT(descs[properties[(Rank)]].type == DESC_MAT_SOLID\
- || descs[properties[(Rank)]].type == DESC_MAT_FLUID);\
+ ASSERT(DESC_IS_MEDIUM(descs[properties[(Rank)]].type));\
if(descs[properties[(Rank)]].type == DESC_MAT_SOLID) solid_count++;\
else fluid_count++;\
}\
diff --git a/src/stardis-app.h b/src/stardis-app.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
#ifndef STARDIS_APP_H
#define STARDIS_APP_H
+#include "stardis-args.h"
#include "stardis-parsing.h"
#include "stardis-default.h"
#include "stardis-solid.h"
@@ -37,6 +38,10 @@
#include <limits.h>
#include <stdarg.h>
+#ifdef STARDIS_ENABLE_MPI
+#include <mpi/mpi.h>
+#endif
+
/* Forward declarations */
struct logger;
struct mem_allocator;
@@ -125,12 +130,15 @@ enum description_type {
struct dummies {
struct sdis_medium* dummy_fluid;
unsigned dummy_fluid_id;
+ struct fluid* stardis_fluid;
struct sdis_medium* dummy_solid;
unsigned dummy_solid_id;
+ struct solid* stardis_solid;
};
#define DUMMIES_NULL__ {\
- NULL, UINT_MAX, NULL, UINT_MAX\
+ NULL, UINT_MAX, NULL, NULL, UINT_MAX, NULL\
}
+static const struct dummies DUMMIES_NULL;
static FINLINE void
init_media_ptr
@@ -193,30 +201,80 @@ error:
/******************************************************************************/
+struct fluid;
+struct solid;
+struct t_boundary;
+struct f_boundary;
+struct h_boundary;
+struct solid_fluid_connect;
+struct solid_solid_connect;
+
+struct description {
+ enum description_type type;
+ union {
+ struct fluid* fluid;
+ struct solid* solid;
+ struct t_boundary* t_boundary;
+ struct f_boundary* f_boundary;
+ struct h_boundary* h_boundary;
+ struct solid_fluid_connect* sf_connect;
+ struct solid_solid_connect* ss_connect;
+ } d;
+};
+
+/******************************************************************************/
+
struct h_boundary {
struct str name;
+ double ref_temperature;
double emissivity;
double specular_fraction;
double hc;
double imposed_temperature;
unsigned mat_id;
+ struct fluid* possible_external_fluid; /* if H for solid */
};
-static FINLINE void
-init_h(struct mem_allocator* allocator, struct h_boundary* dst)
+static FINLINE res_T
+init_h
+ (struct mem_allocator* allocator,
+ struct h_boundary** dst)
{
- str_init(allocator, &dst->name);
- dst->emissivity = 0;
- dst->specular_fraction = 0;
- dst->hc = 0;
- dst->imposed_temperature = -1;
- dst->mat_id = UINT_MAX;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct h_boundary));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ (*dst)->ref_temperature = 0;
+ (*dst)->emissivity = 0;
+ (*dst)->specular_fraction = 0;
+ (*dst)->hc = 0;
+ (*dst)->imposed_temperature = -1;
+ (*dst)->mat_id = UINT_MAX;
+ (*dst)->possible_external_fluid = NULL;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
static FINLINE void
-release_h_boundary(struct h_boundary* bound)
+release_h_boundary
+ (struct h_boundary* bound,
+ struct mem_allocator* allocator)
{
+ ASSERT(bound && allocator);
str_release(&bound->name);
+ if(bound->possible_external_fluid) {
+ release_fluid(bound->possible_external_fluid, allocator);
+ }
+ MEM_RM(allocator, bound);
}
static res_T
@@ -228,45 +286,55 @@ str_print_h_boundary
res_T res = RES_OK;
ASSERT(str && b && DESC_IS_H(type));
STR_APPEND_PRINTF(str,
- "H boundary for %s '%s': emissivity=%g specular_fraction=%g hc=%g T=%g "
- "(using medium %u as external medium)",
- ARG7( (type == DESC_BOUND_H_FOR_SOLID ? "solid" : "fluid"), str_cget(&b->name),
- b->emissivity, b->specular_fraction, b->hc, b->imposed_temperature, b->mat_id ) );
+ "H boundary for %s '%s': ref_temperature=%g emissivity=%g specular_fraction=%g "
+ "hc=%g T=%g (using medium %u as external medium)",
+ ARG8( (type == DESC_BOUND_H_FOR_SOLID ? "solid" : "fluid"), str_cget(&b->name),
+ b->ref_temperature, b->emissivity, b->specular_fraction, b->hc,
+ b->imposed_temperature, b->mat_id ) );
end:
return res;
error:
goto end;
}
-static FINLINE res_T
-cp_h_boundary(struct h_boundary* dst, const struct h_boundary* src)
-{
- dst->specular_fraction = src->specular_fraction;
- dst->imposed_temperature = src->imposed_temperature;
- dst->emissivity = src->emissivity;
- dst->hc = src->hc;
- dst->mat_id = src->mat_id;
- return str_copy(&dst->name, &src->name);
-}
-
struct t_boundary {
struct str name;
double imposed_temperature;
unsigned mat_id;
};
-static FINLINE void
-init_t(struct mem_allocator* allocator, struct t_boundary* dst)
+static FINLINE res_T
+init_t
+ (struct mem_allocator* allocator,
+ struct t_boundary** dst)
{
- str_init(allocator, &dst->name);
- dst->imposed_temperature = -1;
- dst->mat_id = UINT_MAX;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct t_boundary));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ (*dst)->imposed_temperature = -1;
+ (*dst)->mat_id = UINT_MAX;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
static FINLINE void
-release_t_boundary(struct t_boundary* bound)
+release_t_boundary
+ (struct t_boundary* bound,
+ struct mem_allocator* allocator)
{
+ ASSERT(bound && allocator);
str_release(&bound->name);
+ MEM_RM(allocator, bound);
}
static res_T
@@ -287,32 +355,44 @@ error:
goto end;
}
-static FINLINE res_T
-cp_t_boundary(struct t_boundary* dst, const struct t_boundary* src)
-{
- dst->imposed_temperature = src->imposed_temperature;
- dst->mat_id = src->mat_id;
- return str_copy(&dst->name, &src->name);
-}
-
struct f_boundary {
struct str name;
double imposed_flux;
unsigned mat_id;
};
-static FINLINE void
-init_f(struct mem_allocator* allocator, struct f_boundary* dst)
+static FINLINE res_T
+init_f
+ (struct mem_allocator* allocator,
+ struct f_boundary** dst)
{
- str_init(allocator, &dst->name);
- dst->mat_id = UINT_MAX;
- dst->imposed_flux = -1;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct f_boundary));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ (*dst)->mat_id = UINT_MAX;
+ (*dst)->imposed_flux = -1;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
static FINLINE void
-release_f_boundary(struct f_boundary* bound)
+release_f_boundary
+ (struct f_boundary* bound,
+ struct mem_allocator* allocator)
{
+ ASSERT(bound && allocator);
str_release(&bound->name);
+ MEM_RM(allocator, bound);
}
static res_T
@@ -331,16 +411,9 @@ error:
goto end;
}
-static FINLINE res_T
-cp_f_boundary(struct f_boundary* dst, const struct f_boundary* src)
-{
- dst->imposed_flux = src->imposed_flux;
- dst->mat_id = src->mat_id;
- return str_copy(&dst->name, &src->name);
-}
-
struct solid_fluid_connect {
struct str name;
+ double ref_temperature;
double emissivity;
double specular_fraction;
double hc;
@@ -348,19 +421,40 @@ struct solid_fluid_connect {
};
static FINLINE void
-release_sf_connect(struct solid_fluid_connect* connect)
+release_sf_connect
+ (struct solid_fluid_connect* connect,
+ struct mem_allocator* allocator)
{
+ ASSERT(connect && allocator);
str_release(&connect->name);
+ MEM_RM(allocator, connect);
}
-static FINLINE void
-init_sf(struct mem_allocator* allocator, struct solid_fluid_connect* dst)
+static FINLINE res_T
+init_sf
+ (struct mem_allocator* allocator,
+ struct solid_fluid_connect** dst)
{
- str_init(allocator, &dst->name);
- dst->emissivity = 0;
- dst->specular_fraction = 0;
- dst->hc = 0;
- dst->connection_id = UINT_MAX;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct solid_fluid_connect));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ (*dst)->ref_temperature = 0;
+ (*dst)->emissivity = 0;
+ (*dst)->specular_fraction = 0;
+ (*dst)->hc = 0;
+ (*dst)->connection_id = UINT_MAX;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
static res_T
@@ -370,33 +464,15 @@ str_print_sf_connect
{
res_T res = RES_OK;
ASSERT(str && c);
- STR_APPEND_PRINTF(str, "Solid-Fluid connection '%s':", ARG1( str_cget(&c->name) ) );
- STR_APPEND_PRINTF(str, " emissivity=%g, specular_fraction=%g hc=%g",
- ARG3( c->emissivity, c->specular_fraction, c->hc ) );
+ STR_APPEND_PRINTF(str, "Solid-Fluid connection '%s': ", ARG1( str_cget(&c->name) ) );
+ STR_APPEND_PRINTF(str, "ref_temperature=%g emissivity=%g, specular_fraction=%g hc=%g",
+ ARG4( c->ref_temperature, c->emissivity, c->specular_fraction, c->hc ) );
end:
return res;
error:
goto end;
}
-static FINLINE res_T
-cp_sf_connect
- (struct solid_fluid_connect* dst, const struct solid_fluid_connect* src)
-{
- dst->connection_id = src->connection_id;
- dst->specular_fraction = src->specular_fraction;
- dst->emissivity = src->emissivity;
- dst->hc = src->hc;
- return str_copy(&dst->name, &src->name);
-}
-
-static FINLINE res_T
-cp_release_sf_connect
- (struct solid_fluid_connect* dst, struct solid_fluid_connect* src)
-{
- return cp_sf_connect(dst, src);
-}
-
struct solid_solid_connect {
struct str name;
double tcr;
@@ -404,17 +480,37 @@ struct solid_solid_connect {
};
static FINLINE void
-release_ss_connect(struct solid_solid_connect* connect)
+release_ss_connect
+ (struct solid_solid_connect* connect,
+ struct mem_allocator* allocator)
{
+ ASSERT(connect && allocator);
str_release(&connect->name);
+ MEM_RM(allocator, connect);
}
-static FINLINE void
-init_ss(struct mem_allocator* allocator, struct solid_solid_connect* dst)
+static FINLINE res_T
+init_ss
+ (struct mem_allocator* allocator,
+ struct solid_solid_connect** dst)
{
- str_init(allocator, &dst->name);
- dst->tcr = 0;
- dst->connection_id = UINT_MAX;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct solid_solid_connect));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ (*dst)->tcr = 0;
+ (*dst)->connection_id = UINT_MAX;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
static res_T
@@ -424,8 +520,8 @@ str_print_ss_connect
{
res_T res = RES_OK;
ASSERT(str && c);
- STR_APPEND_PRINTF(str, "Solid-Solid connection '%s':", ARG1( str_cget(&c->name) ) );
- STR_APPEND_PRINTF(str, " contact resistance=%g", ARG1( c->tcr ) );
+ STR_APPEND_PRINTF(str, "Solid-Solid connection '%s': ", ARG1( str_cget(&c->name) ) );
+ STR_APPEND_PRINTF(str, "contact resistance=%g", ARG1( c->tcr ) );
end:
return res;
error:
@@ -433,69 +529,45 @@ error:
}
static FINLINE res_T
-cp_ss_connect
- (struct solid_solid_connect* dst, const struct solid_solid_connect* src)
-{
- dst->connection_id = src->connection_id;
- dst->tcr = src->tcr;
- return str_copy(&dst->name, &src->name);
-}
-
-static FINLINE res_T
-cp_release_ss_connect
- (struct solid_solid_connect* dst, struct solid_solid_connect* src)
-{
- return cp_ss_connect(dst, src);
-}
-
-
-struct description {
- enum description_type type;
- union {
- struct fluid fluid;
- struct solid solid;
- struct t_boundary t_boundary;
- struct f_boundary f_boundary;
- struct h_boundary h_boundary;
- struct solid_fluid_connect sf_connect;
- struct solid_solid_connect ss_connect;
- } d;
-};
-
-static FINLINE res_T
-init_description(struct mem_allocator* alloc, struct description* desc)
+init_description
+ (struct mem_allocator* alloc,
+ struct description* desc)
{
ASSERT(desc);
(void)alloc;
desc->type = DESCRIPTION_TYPE_COUNT__;
+ desc->d.fluid = NULL;
return RES_OK;
}
static FINLINE void
-release_description(struct description* desc)
+release_description
+ (struct description* desc,
+ struct mem_allocator* allocator)
{
+ ASSERT(desc && allocator);
switch (desc->type) {
case DESC_MAT_SOLID:
- release_solid(&desc->d.solid);
+ release_solid(desc->d.solid, allocator);
break;
case DESC_MAT_FLUID:
- release_fluid(&desc->d.fluid);
+ release_fluid(desc->d.fluid, allocator);
break;
case DESC_BOUND_H_FOR_SOLID:
case DESC_BOUND_H_FOR_FLUID:
- release_h_boundary(&desc->d.h_boundary);
+ release_h_boundary(desc->d.h_boundary, allocator);
break;
case DESC_BOUND_T_FOR_SOLID:
- release_t_boundary(&desc->d.t_boundary);
+ release_t_boundary(desc->d.t_boundary, allocator);
break;
case DESC_BOUND_F_FOR_SOLID:
- release_f_boundary(&desc->d.f_boundary);
+ release_f_boundary(desc->d.f_boundary, allocator);
break;
case DESC_SOLID_FLUID_CONNECT:
- release_sf_connect(&desc->d.sf_connect);
+ release_sf_connect(desc->d.sf_connect, allocator);
break;
case DESC_SOLID_SOLID_CONNECT:
- release_ss_connect(&desc->d.ss_connect);
+ release_ss_connect(desc->d.ss_connect, allocator);
break;
default:
FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
@@ -514,26 +586,26 @@ str_print_description
ERR(str_printf(str, "Description %u: ", rank));
switch (desc->type) {
case DESC_MAT_SOLID:
- ERR(str_print_solid(str, &desc->d.solid));
+ ERR(str_print_solid(str, desc->d.solid));
break;
case DESC_MAT_FLUID:
- ERR(str_print_fluid(str, &desc->d.fluid));
+ ERR(str_print_fluid(str, desc->d.fluid));
break;
case DESC_BOUND_T_FOR_SOLID:
- ERR(str_print_t_boundary(str, &desc->d.t_boundary));
+ ERR(str_print_t_boundary(str, desc->d.t_boundary));
break;
case DESC_BOUND_H_FOR_SOLID:
case DESC_BOUND_H_FOR_FLUID:
- ERR(str_print_h_boundary(str, &desc->d.h_boundary, desc->type));
+ ERR(str_print_h_boundary(str, desc->d.h_boundary, desc->type));
break;
case DESC_BOUND_F_FOR_SOLID:
- ERR(str_print_f_boundary(str, &desc->d.f_boundary));
+ ERR(str_print_f_boundary(str, desc->d.f_boundary));
break;
case DESC_SOLID_FLUID_CONNECT:
- ERR(str_print_sf_connect(str, &desc->d.sf_connect));
+ ERR(str_print_sf_connect(str, desc->d.sf_connect));
break;
case DESC_SOLID_SOLID_CONNECT:
- ERR(str_print_ss_connect(str, &desc->d.ss_connect));
+ ERR(str_print_ss_connect(str, desc->d.ss_connect));
break;
default:
FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
@@ -551,92 +623,25 @@ get_description_name
ASSERT(desc);
switch (desc->type) {
case DESC_MAT_SOLID:
- return &desc->d.solid.name;
+ return &desc->d.solid->name;
case DESC_MAT_FLUID:
- return &desc->d.fluid.name;
+ return &desc->d.fluid->name;
case DESC_BOUND_T_FOR_SOLID:
- return &desc->d.t_boundary.name;
+ return &desc->d.t_boundary->name;
case DESC_BOUND_H_FOR_SOLID:
case DESC_BOUND_H_FOR_FLUID:
- return &desc->d.h_boundary.name;
+ return &desc->d.h_boundary->name;
case DESC_BOUND_F_FOR_SOLID:
- return &desc->d.f_boundary.name;
+ return &desc->d.f_boundary->name;
case DESC_SOLID_FLUID_CONNECT:
- return &desc->d.sf_connect.name;
+ return &desc->d.sf_connect->name;
case DESC_SOLID_SOLID_CONNECT:
- return &desc->d.ss_connect.name;
+ return &desc->d.ss_connect->name;
default:
FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
}
}
-static FINLINE res_T
-cp_description
- (struct description* dst,
- const struct description* src)
-{
- res_T res = RES_OK;
- ASSERT(src && dst);
- switch (src->type) {
- case DESC_MAT_SOLID:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_solid(src->d.solid.name.allocator, &dst->d.solid);
- }
- ERR(cp_solid(&dst->d.solid, &src->d.solid));
- break;
- case DESC_MAT_FLUID:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_fluid(src->d.fluid.name.allocator, &dst->d.fluid);
- }
- ERR(cp_fluid(&dst->d.fluid, &src->d.fluid));
- break;
- case DESC_BOUND_H_FOR_SOLID:
- case DESC_BOUND_H_FOR_FLUID:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_h(src->d.h_boundary.name.allocator, &dst->d.h_boundary);
- }
- ERR(cp_h_boundary(&dst->d.h_boundary, &src->d.h_boundary));
- break;
- case DESC_BOUND_T_FOR_SOLID:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_t(src->d.t_boundary.name.allocator, &dst->d.t_boundary);
- }
- ERR(cp_t_boundary(&dst->d.t_boundary, &src->d.t_boundary));
- break;
- case DESC_BOUND_F_FOR_SOLID:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_f(src->d.f_boundary.name.allocator, &dst->d.f_boundary);
- }
- ERR(cp_f_boundary(&dst->d.f_boundary, &src->d.f_boundary));
- break;
- case DESC_SOLID_FLUID_CONNECT:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_sf(src->d.sf_connect.name.allocator, &dst->d.sf_connect);
- }
- ERR(cp_sf_connect(&dst->d.sf_connect, &src->d.sf_connect));
- break;
- case DESC_SOLID_SOLID_CONNECT:
- if(dst->type == DESCRIPTION_TYPE_COUNT__) {
- dst->type = src->type;
- init_ss(src->d.ss_connect.name.allocator, &dst->d.ss_connect);
- }
- ERR(cp_ss_connect(&dst->d.ss_connect, &src->d.ss_connect));
- break;
- default:
- FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
- }
-end:
- return res;
-error:
- goto end;
-}
-
static FINLINE void
description_get_medium_id
(const struct description* desc,
@@ -645,20 +650,20 @@ description_get_medium_id
ASSERT(desc && id);
switch (desc->type) {
case DESC_MAT_SOLID:
- *id = desc->d.solid.solid_id;
+ *id = desc->d.solid->solid_id;
return;
case DESC_MAT_FLUID:
- *id = desc->d.fluid.fluid_id;
+ *id = desc->d.fluid->fluid_id;
return;
case DESC_BOUND_H_FOR_SOLID:
case DESC_BOUND_H_FOR_FLUID:
- *id = desc->d.h_boundary.mat_id;
+ *id = desc->d.h_boundary->mat_id;
return;
case DESC_BOUND_T_FOR_SOLID:
- *id = desc->d.t_boundary.mat_id;
+ *id = desc->d.t_boundary->mat_id;
return;
case DESC_BOUND_F_FOR_SOLID:
- *id = desc->d.f_boundary.mat_id;
+ *id = desc->d.f_boundary->mat_id;
return;
case DESC_SOLID_FLUID_CONNECT: /* No medium linked to SF */
case DESC_SOLID_SOLID_CONNECT: /* No medium linked to SS */
@@ -710,8 +715,20 @@ release_camera(struct camera* cam) {
static INLINE void
log_err_fn(const char* msg, void* ctx)
{
+#ifdef STARDIS_ENABLE_MPI
+ int initialized, rank = 0;
+#endif
+
ASSERT(msg);
(void)ctx;
+
+#ifdef STARDIS_ENABLE_MPI
+ CHK(MPI_Initialized(&initialized) == MPI_SUCCESS);
+ if(initialized) CHK(MPI_Comm_rank(MPI_COMM_WORLD, &rank) == MPI_SUCCESS);
+ /* Only master prints */
+ if(rank != 0) return;
+#endif
+
#ifdef OS_WINDOWS
fprintf(stderr, "error: %s", msg);
#else
@@ -722,8 +739,20 @@ log_err_fn(const char* msg, void* ctx)
static INLINE void
log_warn_fn(const char* msg, void* ctx)
{
+#ifdef STARDIS_ENABLE_MPI
+ int initialized, rank = 0;
+#endif
+
ASSERT(msg);
(void)ctx;
+
+#ifdef STARDIS_ENABLE_MPI
+ CHK(MPI_Initialized(&initialized) == MPI_SUCCESS);
+ if(initialized) CHK(MPI_Comm_rank(MPI_COMM_WORLD, &rank) == MPI_SUCCESS);
+ /* Only master prints */
+ if(rank != 0) return;
+#endif
+
#ifdef OS_WINDOWS
fprintf(stderr, "warning: %s", msg);
#else
@@ -734,8 +763,20 @@ log_warn_fn(const char* msg, void* ctx)
static INLINE void
log_prt_fn(const char* msg, void* ctx)
{
+#ifdef STARDIS_ENABLE_MPI
+ int initialized, rank = 0;
+#endif
+
ASSERT(msg);
(void)ctx;
+
+#ifdef STARDIS_ENABLE_MPI
+ CHK(MPI_Initialized(&initialized) == MPI_SUCCESS);
+ if(initialized) CHK(MPI_Comm_rank(MPI_COMM_WORLD, &rank) == MPI_SUCCESS);
+ /* Only master prints */
+ if(rank != 0) return;
+#endif
+
#ifdef OS_WINDOWS
fprintf(stderr, "message: %s", msg);
#else
@@ -759,8 +800,6 @@ struct counts {
#define DARRAY_NAME descriptions
#define DARRAY_DATA struct description
#define DARRAY_FUNCTOR_INIT init_description
-#define DARRAY_FUNCTOR_COPY cp_description
-#define DARRAY_FUNCTOR_RELEASE release_description
#include <rsys/dynamic_array.h>
struct compute_surface {
@@ -771,6 +810,7 @@ struct compute_surface {
};
struct stardis {
+ struct dummies dummies; /* dummy meterials for boundaries' outside */
struct geometry geometry;
struct sdis_scene* sdis_scn; /* The solver scene */
struct darray_descriptions descriptions; /* Materials and boundaries */
@@ -793,18 +833,24 @@ struct stardis {
struct str rndgen_state_in_filename;
struct str rndgen_state_out_filename;
struct str chunks_prefix;
- int mode;
- size_t samples;
- unsigned nthreads;
- double scale_factor;
- double ambient_temp, ref_temp;
struct mem_allocator* allocator;
struct logger* logger;
struct sdis_device* dev;
+ size_t samples;
+ double scale_factor;
+ double trad, trad_ref;
+ double t_range[2];
+ int mode;
+ int trad_def;
+ unsigned nthreads;
+ unsigned picard_order;
unsigned next_medium_id;
unsigned undefined_medium_behind_boundary_id;
int dump_paths;
int verbose;
+ int geometry_initialized;
+ int mpi_initialized;
+ int mpi_rank;
};
static INLINE unsigned
@@ -814,6 +860,18 @@ allocate_stardis_medium_id(struct stardis* stardis)
return stardis->next_medium_id++;
}
+#ifdef STARDIS_ENABLE_MPI
+extern LOCAL_SYM res_T
+init_mpi
+ (int* pargc,
+ char** pargv[],
+ void (*prt_err_fn)(const char* msg, void* ctx),
+ void (*prt_warn_fn)(const char* msg, void* ctx));
+
+extern LOCAL_SYM void
+finalize_mpi(void);
+#endif
+
extern LOCAL_SYM res_T
stardis_init
(const struct args* args,
diff --git a/src/stardis-args.c b/src/stardis-args.c
@@ -0,0 +1,986 @@
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#define _POSIX_C_SOURCE 200809L /* strdup */
+#include "stardis-parsing.h"
+#include "stardis-app.h"
+#include "stardis-default.h"
+#include "stardis-version.h"
+
+#include <rsys/cstr.h>
+#include <rsys/double2.h>
+#include <rsys/double3.h>
+#include <sdis_version.h>
+#include <rsys/logger.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifdef COMPILER_GCC
+#include <strings.h> /* strcasecmp */
+#else
+#define strcasecmp(s1, s2) _stricmp((s1), (s2))
+#endif
+
+#ifdef STARDIS_ENABLE_MPI
+#include <mpi/mpi.h>
+#endif
+
+/*******************************************************************************
+ * Local Functions
+ ******************************************************************************/
+
+static char**
+split_line
+ (char* a_str,
+ const char a_delim)
+{
+ char** result = 0;
+ size_t chunks_count;
+ char* tmp = a_str;
+ char delim[2];
+ char* tok_ctx = NULL;
+
+ ASSERT(a_str);
+
+ delim[0] = a_delim;
+ delim[1] = 0;
+
+ /* if a_str starts with initial useless delimiters remove them */
+ while(*a_str == a_delim) a_str++;
+
+ /* if a_str ends with final useless delimiters remove them */
+ tmp = a_str + strlen(a_str) - 1;
+ while(*tmp == a_delim && tmp >= a_str) { *tmp = '\0'; tmp--; }
+
+ if(tmp >= a_str) chunks_count = 1;
+ else return NULL;
+
+ tmp = a_str;
+ while(*tmp) {
+ int delim_found = 0;
+ while(*tmp == a_delim) { delim_found = 1; tmp++; }
+ if(delim_found) chunks_count++;
+ tmp++;
+ }
+
+ /* Add space for terminating null string so caller
+ knows where the list of returned strings ends. */
+ result = malloc(sizeof(char*) * (1 + chunks_count));
+ if(result) {
+ size_t idx = 0;
+ char* token = strtok_r(a_str, delim, &tok_ctx);
+
+ while(token) {
+ ASSERT(idx <= chunks_count);
+#ifdef COMPILER_CL
+ *(result + idx++) = _strdup(token);
+#else
+ *(result + idx++) = strdup(token);
+#endif
+ token = strtok_r(NULL, delim, &tok_ctx);
+ }
+ ASSERT(idx == chunks_count);
+ *(result + idx) = 0;
+ }
+ return result;
+}
+
+static char
+mode_option
+ (const int m)
+{
+ int found = 0;
+ char res = '?';
+ if(m & MODE_DUMP_C_CHUNKS) { found++; res = 'c'; }
+ if(m & MODE_DUMP_VTK) { found++; res = 'd'; }
+ if(m & MODE_DUMP_PATHS) { found++; res = 'D'; }
+ if(m & MODE_EXTENDED_RESULTS) { found++; res = 'e'; }
+ if(m & MODE_FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; }
+ if(m & MODE_GREEN) { found++; res = 'g'; }
+ if(m & MODE_BIN_GREEN) { found++; res = 'G'; }
+ if(m & MODE_DUMP_HELP) { found++; res = 'h'; }
+ if(m & MODE_MEDIUM_COMPUTE) { found++; res = 'm'; }
+ if(m & MODE_PROBE_COMPUTE) { found++; res = 'p'; }
+ if(m & MODE_PROBE_COMPUTE_ON_INTERFACE) { found++; res = 'P'; }
+ if(m & MODE_IR_COMPUTE) { found++; res = 'R'; }
+ if(m & MODE_BOUNDARY_COMPUTE) { found++; res = 's'; }
+ if(m & MODE_MAP_COMPUTE) { found++; res = 'S'; }
+ if(m & MODE_VERBOSITY) { found++; res = 'V'; }
+ if(m & MODE_DUMP_VERSION) { found++; res = 'v'; }
+ ASSERT(found == 1);
+ return res;
+}
+
+static void
+print_multiple_modes
+ (char* buf,
+ const size_t sz,
+ const int modes,
+ const int dont) /* Modes in dont are not printed */
+{
+ int b = 0, fst = 1;
+ int m = UNDEF_MODE;
+ size_t left = sz;
+ ASSERT(buf);
+ do {
+ m = BIT(b++);
+ if(m & dont) continue;
+ if(m & modes) {
+ size_t n =
+ (size_t)snprintf(buf, left, (fst ? "-%c" : ", -%c"), mode_option(m));
+ if(n >= left) FATAL("Buffer is too small.");
+ left -= n;
+ buf += n;
+ fst = 0;
+ }
+ } while(m < modes);
+}
+
+/*******************************************************************************
+ * Public Functions
+ ******************************************************************************/
+
+void
+print_version
+ (FILE* stream)
+{
+ ASSERT(stream);
+ fprintf(stream,
+ "Stardis version %i.%i.%i built on stardis solver version %i.%i.%i; MPI is "
+#ifdef STARDIS_ENABLE_MPI
+ "enabled.\n",
+#else
+ "disabled.\n",
+#endif
+ STARDIS_APP_VERSION_MAJOR, STARDIS_APP_VERSION_MINOR, STARDIS_APP_VERSION_PATCH,
+ Stardis_VERSION_MAJOR, Stardis_VERSION_MINOR, Stardis_VERSION_PATCH);
+}
+
+res_T
+init_args
+ (struct logger* logger,
+ struct mem_allocator* allocator,
+ struct args** out_args)
+{
+ res_T res = RES_OK;
+ struct args* args = NULL;
+ ASSERT(logger && allocator && out_args);
+
+ args = calloc(sizeof(struct args), 1);
+ if(!args) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ args->logger = logger;
+ args->allocator = allocator;
+ darray_str_init(allocator, &args->model_files);
+ /* Set non-zero default values */
+ args->samples = STARDIS_DEFAULT_SAMPLES_COUNT;
+ args->nthreads = SDIS_NTHREADS_DEFAULT;
+ args->picard_order = STARDIS_DEFAULT_PICARD_ORDER;
+ d2(args->pos_and_time+3,
+ STARDIS_DEFAULT_COMPUTE_TIME, STARDIS_DEFAULT_COMPUTE_TIME);
+ args->verbose = STARDIS_DEFAULT_VERBOSE_LEVEL;
+
+end:
+ *out_args = args;
+ return res;
+error:
+ if(args) release_args(args);
+ args = NULL;
+ goto end;
+}
+
+void
+release_args(struct args* args)
+{
+ ASSERT(args);
+ darray_str_release(&args->model_files);
+ free(args);
+}
+
+void
+short_help
+ (FILE* stream,
+ const char* prog)
+{
+ const char* name;
+#ifdef STARDIS_ENABLE_MPI
+ int rank;
+#endif
+ ASSERT(stream && prog);
+
+#ifdef STARDIS_ENABLE_MPI
+ CHK(MPI_Comm_rank(MPI_COMM_WORLD, &rank) == MPI_SUCCESS);
+ /* Only master prints */
+ if(rank != 0) return;
+#endif
+
+#ifdef COMPILER_GCC
+ name = strrchr(prog, '/');
+#else
+ name = strrchr(prog, '\\');
+#endif
+
+ name = name ? name + 1 : prog;
+ fprintf(stream,
+ "Usage: %s [OPTIONS]\n"
+ "\nSolve coupled thermal systems under the linear assumption.\n"
+ "Refer to stardis(1) man page for more information.\n\n",
+ name);
+ print_version(stream);
+
+ fprintf(stream, "\nMandatory options\n");
+ fprintf(stream, "-----------------\n");
+
+ fprintf(stream, "\n -M <FILE>\n");
+ fprintf(stream, " Read a text file that contains (partial) description of the model.\n");
+
+ fprintf(stream, "\nExclusive options\n");
+ fprintf(stream, "-----------------\n");
+
+ fprintf(stream, "\n -F STL_FILE[,TIME-RANGE]\n");
+ fprintf(stream, " Compute the mean flux on a given 2D region at a given time.\n");
+
+ fprintf(stream, "\n -m MEDIUM_NAME[,TIME-RANGE]\n");
+ fprintf(stream, " Compute the mean temperature in a given medium at a given time.\n");
+
+ fprintf(stream, "\n -p X,Y,Z[,TIME-RANGE]\n");
+ fprintf(stream, " Compute the temperature at the given probe.\n");
+
+ fprintf(stream, "\n -P X,Y,Z[,TIME-RANGE]\n");
+ fprintf(stream, " Compute the temperature at the given probe on an interface.\n");
+
+ fprintf(stream, "\n -R [RENDERING_OPTIONS]\n");
+ fprintf(stream, " Compute an infra-red image of the model.\n");
+
+ fprintf(stream, "\n -s STL_FILE[,TIME-RANGE]\n");
+ fprintf(stream, " Compute the mean temperature on a given 2D region.\n");
+
+ fprintf(stream, "\n -S STL_FILE[,TIME-RANGE]\n");
+ fprintf(stream, " Compute the by-triangle mean temperature on a given 2D region.\n");
+
+ fprintf(stream, "\nOther options\n");
+ fprintf(stream, "-------------\n");
+
+ fprintf(stream, "\n -c NAMES_PREFIX\n");
+ fprintf(stream, " Dump the geometry and property ids to stdout as C chunks.\n");
+
+ fprintf(stream, "\n -d\n");
+ fprintf(stream, " Dump the geometry to stdout in VTK format along with various properties.\n");
+
+ fprintf(stream, "\n -D TYPE,FILE_NAMES_PREFIX\n");
+ fprintf(stream, " Write thermal paths of the given TYPE in VTK format.\n");
+
+ fprintf(stream, "\n -e\n");
+ fprintf(stream, " Use extended format to output Monte-Carlo results.\n");
+
+ fprintf(stream, "\n -g\n");
+ fprintf(stream, " Change the computation to produce the green function.\n");
+
+ fprintf(stream, "\n -G BIN_FILE_NAME[,CSV_FILE_NAME]\n");
+ fprintf(stream, " Change the computation to produce the green function and possibly end of paths information.\n");
+
+ fprintf(stream, "\n -h\n");
+ fprintf(stream, " Print this help and exit.\n");
+
+ fprintf(stream, "\n -n SAMPLE_COUNT\n");
+ fprintf(stream, " Set the number of Monte-Carlo samples.\n");
+
+ fprintf(stream, "\n -o\n");
+ fprintf(stream, " Set the order for the Picard linearization of radiative transfer.\n");
+
+ fprintf(stream, "\n -t NUM_OF_THREADS\n");
+ fprintf(stream, " Hint on the number of threads.\n");
+
+ fprintf(stream, "\n -v\n");
+ fprintf(stream, " Print version information and exit.\n");
+
+ fprintf(stream, "\n -V LEVEL\n");
+ fprintf(stream, " Set the verbosity level.\n");
+
+ fprintf(stream, "\n -x <FILE>\n");
+ fprintf(stream, " Use a random generator's state read from a file.\n");
+
+ fprintf(stream, "\n -X <FILE>\n");
+ fprintf(stream, " Save the final random generator's state in a file.\n");
+
+ fprintf(stream,
+"\nCopyright (C) 2018-2022 |Meso|Star> <contact@meso-star.com>.\n"
+"stardis is free software released under the GNU GPL license, version 3 or later.\n"
+"You are free to change or redistribute it under certain conditions\n"
+"<http://gnu.org/licenses/gpl.html>.\n");
+}
+
+#define FREE_AARRAY(ARRAY) \
+if(ARRAY) {\
+ int i__ = 0; \
+ for(i__=0; *((ARRAY)+i__);i__++){\
+ free((ARRAY)[i__]);\
+ }\
+ free(ARRAY);\
+ (ARRAY) = NULL;\
+}
+
+/* Workaround for a gcc warning when GET_OPTIONAL_TIME_RANGE used with Rank=0 */
+static FINLINE int is_less(size_t a, size_t b) { return a < b; }
+
+/* Get a time range from a coma-separated list of doubles
+ * The first Rank values are mandatory, followed by an optional time range
+ * that can be a single time */
+#define GET_OPTIONAL_TIME_RANGE(Src, Rank, Dst, Logger, OptionString, Option, FullSrc) \
+ res = cstr_to_list_double((Src), ',', (Dst), &len, (Rank)+2); \
+ if(res != RES_OK \
+ || is_less(len, (Rank)) \
+ || (len == (Rank)+1 && (Dst)[(Rank)] < 0) \
+ || (len == (Rank)+2 && ((Dst)[0] < 0 || (Dst)[(Rank)] > (Dst)[(Rank)+1])) \
+ || len > (Rank)+2) \
+ { \
+ if(res == RES_OK) res = RES_BAD_ARG; \
+ logger_print((Logger), LOG_ERROR, \
+ "Invalid argument for option "OptionString": %s\n", \
+ (Option), (FullSrc)); \
+ goto error; \
+ } else { \
+ if(len == (Rank)+1) (Dst)[(Rank)+1] = (Dst)[(Rank)];\
+ }
+
+/* Get a string followed by an optional time range */
+#define GET_STR_AND_OPTIONAL_TIME_RANGE(Str, Time) \
+ ptr = strchr(optarg, ','); /* First ',' */ \
+ if(ptr) { /* Time range provided */ \
+ GET_OPTIONAL_TIME_RANGE(ptr+1, 0, (Time), args->logger, "-%c", opt, optarg); \
+ *ptr = '\0'; \
+ } \
+ (Str) = optarg;
+
+/* Get a position followed by an optional time range */
+#define GET_POS_AND_OPTIONAL_TIME_RANGE(Src, Dst, FullSrc) \
+ GET_OPTIONAL_TIME_RANGE((Src), 3, (Dst), args->logger, "-%c", opt, (FullSrc));
+
+res_T
+parse_args
+ (const int argc,
+ char** argv,
+ struct args* args,
+ struct mem_allocator* allocator)
+{
+ int opt = 0, n_used = 0, o_used = 0;
+ size_t len = 0;
+ const char option_list[] = "c:dD:eF:gG:hm:M:n:o:p:P:R:s:S:t:vV:x:X:";
+ char buf[128];
+ struct str keep;
+ char** line = NULL;
+ res_T res = RES_OK;
+
+ ASSERT(argv && args);
+
+ str_init(allocator, &keep);
+ opterr = 0; /* No default error messages */
+ while((opt = getopt(argc, argv, option_list)) != -1) {
+ switch (opt) {
+
+ case '?': /* Unreconised option */
+ {
+ char* ptr = strchr(option_list, optopt);
+ res = RES_BAD_ARG;
+ if(ptr && ptr[1] == ':') {
+ logger_print(args->logger, LOG_ERROR,
+ "Missing argument for option -%c\n",
+ optopt);
+ } else {
+ logger_print(args->logger, LOG_ERROR, "Invalid option -%c\n", optopt);
+ }
+ goto error;
+ }
+
+ case 'c':
+ if(args->mode & USE_STDOUT_MODES) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_C_CHUNKS);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used in conjunction with other dump options (%s).\n",
+ (char)opt, buf);
+ goto error;
+ }
+ args->chunks_prefix = optarg;
+ args->mode |= MODE_DUMP_C_CHUNKS;
+ break;
+
+ case 'd':
+ if(args->mode & USE_STDOUT_MODES) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_VTK);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used in conjunction with other dump options (%s).\n",
+ (char)opt, buf);
+ goto error;
+ }
+ args->mode |= MODE_DUMP_VTK;
+ break;
+
+ case 'D': {
+ char* ptr = strrchr(optarg, ',');
+ if(!ptr || ptr != strchr(optarg, ','))
+ res = RES_BAD_ARG; /* Single ',' expected */
+ else {
+ args->paths_filename = ptr + 1;
+ *ptr = '\0';
+ }
+ if(res == RES_OK) {
+ if(0 == strcasecmp(optarg, "all")) {
+ args->dump_paths = DUMP_ALL;
+ }
+ else if(0 == strcasecmp(optarg, "error")) {
+ args->dump_paths = DUMP_ERROR;
+ }
+ else if(0 == strcasecmp(optarg, "success")) {
+ args->dump_paths = DUMP_SUCCESS;
+ }
+ }
+ if(res != RES_OK) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Invalid argument for option -%c: %s\n",
+ opt, optarg);
+ goto error;
+ }
+ args->mode |= MODE_DUMP_PATHS;
+ break;
+ }
+
+ case 'e':
+ args->mode |= MODE_EXTENDED_RESULTS;
+ break;
+
+ /*case 'F': see 's' */
+
+ case 'g':
+ if(args->mode & MODE_BIN_GREEN) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(MODE_BIN_GREEN));
+ goto error;
+ }
+ args->mode |= MODE_GREEN;
+ break;
+
+ case 'G': {
+ char* ptr = strrchr(optarg, ',');
+ if(ptr && ptr != strchr(optarg, ','))
+ res = RES_BAD_ARG; /* Expecting 1 or 0 ',' */
+ if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
+ res = RES_BAD_ARG;
+ if(args->mode & MODE_BIN_GREEN)
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used twice.\n",
+ (char)opt);
+ else
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(MODE_GREEN));
+ goto error;
+ }
+ args->mode |= MODE_BIN_GREEN;
+ if(ptr) {
+ args->end_paths_filename = ptr + 1;
+ *ptr = '\0';
+ }
+ args->bin_green_filename = optarg;
+ break;
+ }
+
+ case 'h':
+ if(args->mode & USE_STDOUT_MODES) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_HELP);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used in conjunction with other dump options (%s).\n",
+ (char)opt, buf);
+ goto error;
+ }
+ args->mode |= MODE_DUMP_HELP;
+ break;
+
+ case 'm': {
+ char* ptr;
+ if(args->mode & EXCLUSIVE_MODES) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(args->mode));
+ goto error;
+ }
+ args->mode |= MODE_MEDIUM_COMPUTE;
+ GET_STR_AND_OPTIONAL_TIME_RANGE(args->medium_name, args->pos_and_time + 3);
+ break;
+ }
+
+ case 'M': {
+ struct str name;
+ str_init(args->allocator, &name);
+ ERR(str_set(&name, optarg));
+ ERR(darray_str_push_back(&args->model_files, &name));
+ str_release(&name);
+ break;
+ }
+ case 'n': {
+ long n;
+ res = cstr_to_long(optarg, &n);
+ if(res != RES_OK
+ || n <= 0)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Invalid argument for option -%c: %s\n",
+ opt, optarg);
+ goto error;
+ }
+ args->samples = (unsigned long)n;
+ n_used = 1;
+ break;
+ }
+
+ case 'o': {
+ int order;
+ res = cstr_to_int(optarg, &order);
+ if(res != RES_OK
+ || order <= 0)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Invalid argument for option -%c: %s\n",
+ opt, optarg);
+ goto error;
+ }
+ args->picard_order = (unsigned)order;
+ o_used = 1;
+ break;
+ }
+
+ case 'p':
+ if(args->mode & EXCLUSIVE_MODES) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(args->mode));
+ goto error;
+ }
+ args->mode |= MODE_PROBE_COMPUTE;
+ GET_POS_AND_OPTIONAL_TIME_RANGE(optarg, args->pos_and_time, optarg);
+ break;
+
+ case 'P':
+ if(args->mode & EXCLUSIVE_MODES) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(args->mode));
+ goto error;
+ }
+ args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE;
+
+ ERR(str_set(&keep, optarg));
+ line = split_line(optarg, ':');
+ if(!line) {
+ res = RES_MEM_ERR;
+ str_release(&keep);
+ goto error;
+ }
+
+ /* We expect 1 or 2 parts in line */
+ if(!line[0] || (line[1] && line[2])) {
+ logger_print((args->logger), LOG_ERROR,
+ "Invalid argument for option ""-%c"": %s\n",
+ opt, str_cget(&keep));
+ str_release(&keep);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* First part is pos and optional time, optional second part is a
+ * medium name (OK if NULL) */
+ GET_POS_AND_OPTIONAL_TIME_RANGE(line[0], args->pos_and_time,
+ str_cget(&keep));
+ if(line[1])
+ args->medium_name = optarg + strlen(line[0]) + 1;
+
+ break;
+
+ case 'R':
+ if(args->mode & EXCLUSIVE_MODES) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(args->mode));
+ goto error;
+ }
+ args->mode |= MODE_IR_COMPUTE;
+ args->camera = optarg;
+ break;
+
+ case 's':
+ case 'S':
+ case 'F': {
+ char *ptr;
+ if(args->mode & EXCLUSIVE_MODES) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Options -%c and -%c are exclusive.\n",
+ (char)opt, mode_option(args->mode));
+ goto error;
+ }
+ switch (opt) {
+ case 's':
+ args->mode |= MODE_BOUNDARY_COMPUTE;
+ break;
+ case 'S':
+ args->mode |= MODE_MAP_COMPUTE;
+ break;
+ case 'F':
+ args->mode |= MODE_FLUX_BOUNDARY_COMPUTE;
+ break;
+ }
+ GET_STR_AND_OPTIONAL_TIME_RANGE(args->solve_filename, args->pos_and_time + 3);
+ break;
+ }
+
+ case 't': {
+ int nt;
+ res = cstr_to_int(optarg, &nt);
+ if(res != RES_OK
+ || nt <= 0)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Invalid argument for option -%c: %s\n",
+ opt, optarg);
+ goto error;
+ }
+ args->nthreads = (unsigned)nt;
+ break;
+ }
+
+ case 'v':
+ if(args->mode & USE_STDOUT_MODES) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_VERSION);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used in conjunction with other dump options (%s).\n",
+ (char)opt, buf);
+ goto error;
+ }
+ args->mode |= MODE_DUMP_VERSION;
+ break;
+
+ case 'V':
+ res = cstr_to_int(optarg, &args->verbose);
+ if(res != RES_OK
+ || args->verbose < 0
+ || args->verbose > 3)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Invalid argument for option -%c: %s\n",
+ opt, optarg);
+ goto error;
+ }
+ break;
+
+ case 'x':
+ if(!(args->mode & RANDOM_RW_MODES)) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), RANDOM_RW_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c can only be used in conjunction with one of the following options: %s.\n",
+ (char)opt, buf);
+ goto error;
+ }
+ args->rndgen_state_in_filename = optarg;
+ break;
+
+ case 'X':
+ if(!(args->mode & RANDOM_RW_MODES)) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), RANDOM_RW_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c can only be used in conjunction with one of the following options: %s.\n",
+ (char)opt, buf);
+ goto error;
+ }
+ args->rndgen_state_out_filename = optarg;
+ break;
+ }
+ }
+
+ if(argc > optind) {
+ int i;
+ for(i = optind; i < argc; i++) {
+ logger_print(args->logger, LOG_ERROR, "Unexpected argument: %s.\n", argv[i]);
+ }
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!darray_str_size_get(&args->model_files)
+ && !(args->mode & SHORT_EXIT_MODES)) {
+ logger_print(args->logger, LOG_ERROR,
+ "Missing mandatory argument: -M <model_file_name>\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->mode == UNDEF_MODE) {
+ print_multiple_modes(buf, sizeof(buf), EXCLUSIVE_MODES | USE_STDOUT_MODES, 0);
+ logger_print(args->logger, LOG_WARNING,
+ "Nothing to do.\nOne of the following options should be used: %s\n",
+ buf);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)
+ && !(args->mode & GREEN_COMPATIBLE_MODES))
+ {
+ print_multiple_modes(buf, sizeof(buf), GREEN_COMPATIBLE_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c can only be used in conjunction with: %s\n",
+ mode_option(args->mode & (MODE_BIN_GREEN | MODE_GREEN)), buf);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)
+ && o_used && args->picard_order > 1)
+ {
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used if Picard order is not 1 (here order is %u)\n",
+ mode_option(args->mode & (MODE_BIN_GREEN | MODE_GREEN)),
+ args->picard_order);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->mode & MODE_IR_COMPUTE && n_used) {
+ logger_print(args->logger, LOG_ERROR,
+ "The -n option has no effect in rendering mode;"
+ " use rendering's SPP suboption instead.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->mode & MODE_DUMP_PATHS) {
+ if(!(args->mode & COMPUTE_MODES)) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c can only be used in conjunction with an option"
+ " that samples heat paths (%s).\n",
+ mode_option(MODE_DUMP_PATHS), buf);
+ goto error;
+ }
+ if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used in conjunction with -%c nor -%c.\n",
+ mode_option(MODE_DUMP_PATHS), mode_option(MODE_GREEN)
+ , mode_option(MODE_BIN_GREEN));
+ goto error;
+ }
+ }
+
+ if(args->mode & MODE_EXTENDED_RESULTS) {
+ if(!(args->mode & EXT_COMPATIBLE_MODES)) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), EXT_COMPATIBLE_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c can only be used in conjunction with an option"
+ " that computes a single Monte-Carlo (%s).\n",
+ mode_option(MODE_EXTENDED_RESULTS), buf);
+ goto error;
+ }
+ if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
+ res = RES_BAD_ARG;
+ logger_print(args->logger, LOG_ERROR,
+ "Option -%c cannot be used in conjunction with -%c nor -%c.\n",
+ mode_option(MODE_EXTENDED_RESULTS), mode_option(MODE_GREEN)
+ , mode_option(MODE_BIN_GREEN));
+ goto error;
+ }
+ }
+
+ if(args->rndgen_state_in_filename && !(args->mode & COMPUTE_MODES)) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -x can only be used in conjunction with an option"
+ " that launch a MC computation (%s).\n",
+ buf);
+ goto error;
+ }
+
+ if(args->rndgen_state_out_filename && !(args->mode & COMPUTE_MODES)) {
+ res = RES_BAD_ARG;
+ print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0);
+ logger_print(args->logger, LOG_ERROR,
+ "Option -X can only be used in conjunction with an option"
+ " that launch a MC computation (%s).\n",
+ buf);
+ goto error;
+ }
+
+end:
+ FREE_AARRAY(line);
+ str_release(&keep);
+ return res;
+error:
+ logger_print(args->logger, LOG_ERROR, "Use option -h to print help.\n");
+ goto end;
+}
+
+res_T
+parse_camera
+ (struct logger* logger,
+ char* cam_param,
+ struct stardis* stardis)
+{
+ char** line = NULL;
+ char** opt = NULL;
+ struct camera* cam;
+ struct str keep;
+ int i = 0;
+ res_T res = RES_OK;
+
+ ASSERT(cam_param && stardis);
+ cam = &stardis->camera;
+ line = split_line(cam_param, ':');
+ if(!line) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ str_init(stardis->allocator, &keep);
+ for(i = 0; *(line + i); i++) {
+ size_t len = 0;
+ ERR(str_set(&keep, line[i]));
+ opt = split_line(line[i], '=');
+ if(!opt[0] || !opt[1] || opt[2]) { /* We expect 2 parts */
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print((logger), LOG_ERROR,
+ "Invalid option syntax: %s\n", str_cget(&keep));
+ goto error;
+ }
+ if(strcasecmp(opt[0], "T") == 0) {
+ GET_OPTIONAL_TIME_RANGE(opt[1], 0, cam->time_range, logger, "%s", opt[0],
+ str_cget(&keep));
+ }
+ else if(strcasecmp(opt[0], "FILE") == 0) {
+ ERR(str_set(&cam->file_name, opt[1]));
+ }
+ else if(strcasecmp(opt[0], "FMT") == 0) {
+ if(strcasecmp(opt[1], "VTK") == 0)
+ cam->fmt = STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK;
+ else if(strcasecmp(opt[1], "HT") == 0)
+ cam->fmt = STARDIS_RENDERING_OUTPUT_FILE_FMT_HT;
+ else {
+ logger_print(logger, LOG_ERROR,
+ "Unexpected value for rendering option %s: %s.\n",
+ opt[0], opt[1]);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ else if(strcasecmp(opt[0], "FOV") == 0) {
+ res = cstr_to_double(opt[1], &cam->fov);
+ if(res != RES_OK
+ || cam->fov <= 0)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print((logger), LOG_ERROR,
+ "Invalid %s option: %s\n", opt[0], opt[1]);
+ goto error;
+ }
+ }
+ else if(strcasecmp(opt[0], "UP") == 0) {
+ ERR(cstr_to_list_double(opt[1], ',', cam->up, &len, 3));
+ }
+ else if(strcasecmp(opt[0], "TGT") == 0) {
+ ERR(cstr_to_list_double(opt[1], ',', cam->tgt, &len, 3));
+ cam->auto_look_at = 0;
+ }
+ else if(strcasecmp(opt[0], "POS") == 0) {
+ ERR(cstr_to_list_double(opt[1], ',', cam->pos, &len, 3));
+ cam->auto_look_at = 0;
+ }
+ else if(strcasecmp(opt[0], "IMG") == 0) {
+ unsigned img_sz[2];
+ res = cstr_to_list_uint(opt[1], 'x', img_sz, &len, 2);
+ if(res != RES_OK
+ /* mimic cstr_to_list_int() possible behaviour; but it doesnt exist */
+ || img_sz[0] == 0 || img_sz[0] > INT_MAX
+ || img_sz[1] == 0 || img_sz[1] > INT_MAX)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print((logger), LOG_ERROR,
+ "Invalid %s option: %s\n", opt[0], opt[1]);
+ goto error;
+ }
+ cam->img_width = img_sz[0];
+ cam->img_height = img_sz[1];
+ }
+ else if(strcasecmp(opt[0], "SPP") == 0) {
+ int ssp;
+ res = cstr_to_int(opt[1], &ssp);
+ if(res != RES_OK
+ || ssp <= 0)
+ {
+ if(res == RES_OK) res = RES_BAD_ARG;
+ logger_print((logger), LOG_ERROR,
+ "Invalid %s option: %s\n", opt[0], opt[1]);
+ goto error;
+ }
+ cam->spp = (unsigned)ssp;
+ } else {
+ logger_print(logger, LOG_ERROR,
+ "Unexpected option for rendering mode: %s.\n",
+ opt[0]);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ FREE_AARRAY(opt);
+ }
+
+end:
+ FREE_AARRAY(line);
+ FREE_AARRAY(opt);
+#undef FREE_AARRAY
+
+ str_release(&keep);
+ return res;
+error:
+ logger_print(logger, LOG_ERROR, "Error parsing camera options.\n");
+ logger_print(logger, LOG_ERROR, "Use the -h option to get help.\n");
+ goto end;
+}
+
+#undef GET_STR_AND_OPTIONAL_TIME_RANGE
+#undef GET_POS_AND_OPTIONAL_TIME_RANGE
+#undef GET_OPTIONAL_TIME_RANGE
diff --git a/src/stardis-args.h b/src/stardis-args.h
@@ -0,0 +1,141 @@
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef STARDIS_ARGS_H
+#define STARDIS_ARGS_H
+
+#include <sdis.h>
+
+#include <rsys/rsys.h>
+#include <rsys/dynamic_array_str.h>
+
+struct camera;
+struct logger;
+struct mem_allocator;
+struct stardis;
+struct dummies;
+
+enum stardis_mode {
+ /* Ordered so that print_multiple_modes() prints in alphabetical order */
+ UNDEF_MODE = 0,
+ MODE_DUMP_C_CHUNKS = BIT(0), /* -c */
+ MODE_DUMP_PATHS = BIT(1), /* -D */
+ MODE_DUMP_VTK = BIT(2), /* -d */
+ MODE_EXTENDED_RESULTS = BIT(3), /* -e */
+ MODE_FLUX_BOUNDARY_COMPUTE = BIT(4), /* -F */
+ MODE_BIN_GREEN = BIT(5), /* -G */
+ MODE_GREEN = BIT(6), /* -g */
+ MODE_DUMP_HELP = BIT(7), /* -h */
+ MODE_MEDIUM_COMPUTE = BIT(8), /* -m */
+ MODE_PROBE_COMPUTE_ON_INTERFACE = BIT(9), /* -P */
+ MODE_PROBE_COMPUTE = BIT(10), /* -p */
+ MODE_IR_COMPUTE = BIT(11), /* -R */
+ MODE_MAP_COMPUTE = BIT(12), /* -S */
+ MODE_BOUNDARY_COMPUTE = BIT(13), /* -s */
+ MODE_VERBOSITY = BIT(14), /* -V */
+ MODE_DUMP_VERSION = BIT(15), /* -v */
+
+ GREEN_COMPATIBLE_MODES
+ = MODE_PROBE_COMPUTE | MODE_PROBE_COMPUTE_ON_INTERFACE | MODE_MEDIUM_COMPUTE
+ | MODE_BOUNDARY_COMPUTE,
+
+ SURFACE_COMPUTE_MODES
+ = MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE | MODE_MAP_COMPUTE,
+
+ EXT_COMPATIBLE_MODES
+ = GREEN_COMPATIBLE_MODES | MODE_MEDIUM_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE,
+
+ REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES | MODE_MEDIUM_COMPUTE,
+
+ COMPUTE_MODES = GREEN_COMPATIBLE_MODES | MODE_IR_COMPUTE | SURFACE_COMPUTE_MODES,
+
+ EXCLUSIVE_MODES = COMPUTE_MODES,
+
+ SHORT_EXIT_MODES = MODE_DUMP_HELP | MODE_DUMP_VERSION,
+
+ USE_STDOUT_MODES
+ = MODE_DUMP_C_CHUNKS | MODE_DUMP_VTK | MODE_DUMP_HELP | MODE_DUMP_VERSION
+ | MODE_IR_COMPUTE | MODE_GREEN,
+
+ RANDOM_RW_MODES
+ = MODE_PROBE_COMPUTE | MODE_PROBE_COMPUTE_ON_INTERFACE | MODE_MEDIUM_COMPUTE
+ | MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE
+};
+
+STATIC_ASSERT(GREEN_COMPATIBLE_MODES == (COMPUTE_MODES & GREEN_COMPATIBLE_MODES),
+ Cannot_have_a_GREEN_COMPATIBLE_MODE_that_is_not_a_COMPUTE_MODE);
+
+enum dump_path_type {
+ DUMP_NONE = 0,
+ DUMP_SUCCESS = BIT(0),
+ DUMP_ERROR = BIT(1),
+ DUMP_ALL = DUMP_SUCCESS | DUMP_ERROR
+};
+
+struct args {
+ struct logger* logger;
+ struct mem_allocator* allocator;
+ struct darray_str model_files;
+ char* medium_name;
+ char* solve_filename;
+ char* bin_green_filename;
+ char* end_paths_filename;
+ char* paths_filename;
+ char* rndgen_state_in_filename;
+ char* rndgen_state_out_filename;
+ char* chunks_prefix;
+ char* camera;
+ size_t samples;
+ double pos_and_time[5];
+ unsigned nthreads;
+ unsigned picard_order;
+ enum stardis_mode mode;
+ enum dump_path_type dump_paths;
+ int verbose;
+};
+
+extern LOCAL_SYM res_T
+init_args
+ (struct logger* logger,
+ struct mem_allocator* mem,
+ struct args** args);
+
+extern LOCAL_SYM void
+release_args
+ (struct args* args);
+
+extern void
+print_version
+ (FILE* stream);
+
+extern void
+short_help
+ (FILE* stream,
+ const char* prog);
+
+extern res_T
+parse_args
+ (const int argc,
+ char** argv,
+ struct args* args,
+ struct mem_allocator* allocator);
+
+extern res_T
+parse_camera
+ (struct logger* logger,
+ char* cam_param,
+ struct stardis* stardis);
+
+#endif /* STRADIS_ARGS_H */
diff --git a/src/stardis-compute.c b/src/stardis-compute.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -246,35 +246,35 @@ check_probe_conform_to_type
"Could not determine the medium probe is in.\n");
} else {
if(filter_ctx.desc->type == DESC_MAT_SOLID) {
- double delta = filter_ctx.desc->d.solid.delta;
- ASSERT(delta < INF);
+ struct solid* solid = filter_ctx.desc->d.solid;
+ ASSERT(solid->delta < INF);
logger_print(stardis->logger, LOG_OUTPUT,
- "Probe was in solid '%s'.\n", str_cget(&filter_ctx.desc->d.solid.name));
- if(filter_ctx.dist > 2 * delta) {
+ "Probe was in solid '%s'.\n", str_cget(&solid->name));
+ if(filter_ctx.dist > 2 * solid->delta) {
logger_print(stardis->logger, LOG_ERROR,
"Probe moved to (%g, %g, %g), primitive %u, uv = (%g, %g).\n",
SPLIT3(filter_ctx.pos), hit.prim.prim_id, SPLIT2(hit.uv));
logger_print(stardis->logger, LOG_ERROR,
"Move is %g delta long. Use -p instead of -P.\n",
- filter_ctx.dist / delta);
+ filter_ctx.dist / solid->delta);
res = RES_BAD_ARG;
goto error;
}
- if(filter_ctx.dist > 0.5 * delta) {
+ if(filter_ctx.dist > 0.5 * solid->delta) {
logger_print(stardis->logger, LOG_WARNING,
"Probe was %g delta from closest boundary. "
- "Consider using -P instead of -p.\n",
- filter_ctx.dist / delta);
+ "Consider using -p instead of -P.\n",
+ filter_ctx.dist / solid->delta);
} else {
if(filter_ctx.dist != 0)
logger_print(stardis->logger, LOG_OUTPUT,
"Probe was %g delta from closest boundary.\n",
- filter_ctx.dist / delta);
+ filter_ctx.dist / solid->delta);
}
} else {
/* TODO: check move length wrt local geometry? */
logger_print(stardis->logger, LOG_OUTPUT,
- "Probe was in fluid '%s'.\n", str_cget(&filter_ctx.desc->d.fluid.name));
+ "Probe was in fluid '%s'.\n", str_cget(&filter_ctx.desc->d.fluid->name));
logger_print(stardis->logger, LOG_OUTPUT,
"Probe distance from closest boundary was %g.\n", filter_ctx.dist);
}
@@ -329,34 +329,34 @@ check_probe_conform_to_type
goto error;
}
logger_print(stardis->logger, LOG_OUTPUT,
- "Probe is in solid '%s'.\n", str_cget(&filter_ctx.desc->d.solid.name));
+ "Probe is in solid '%s'.\n", str_cget(&filter_ctx.desc->d.solid->name));
if(filter_ctx.desc->type == DESC_MAT_SOLID) {
- double delta = filter_ctx.desc->d.solid.delta;
- if(filter_ctx.dist < 0.25 * delta) {
+ struct solid* solid = filter_ctx.desc->d.solid;
+ if(filter_ctx.dist < 0.25 * solid->delta) {
logger_print(stardis->logger, LOG_ERROR,
"Probe is %g delta from closest boundary. Use -P instead of -p.\n",
- filter_ctx.dist / delta);
+ filter_ctx.dist / solid->delta);
logger_print(stardis->logger, LOG_ERROR,
"Closest geometry is primitive %u, uv = (%g, %g).\n",
hit.prim.prim_id, SPLIT2(hit.uv));
res = RES_BAD_ARG;
goto error;
}
- if(filter_ctx.dist < 0.5 * delta) {
+ if(filter_ctx.dist < 0.5 * solid->delta) {
logger_print(stardis->logger, LOG_WARNING,
"Probe is %g delta from closest boundary. "
"Consider using -P instead of -p.\n",
- filter_ctx.dist / delta);
+ filter_ctx.dist / solid->delta);
} else {
logger_print(stardis->logger, LOG_OUTPUT,
"Probe is %g delta from closest boundary.\n",
- filter_ctx.dist / delta);
+ filter_ctx.dist / solid->delta);
}
} else {
logger_print(stardis->logger, LOG_WARNING,
"Probe is in fluid '%s': computing fluid temperature, "
"not using a specific position.\n",
- str_cget(&filter_ctx.desc->d.fluid.name));
+ str_cget(&filter_ctx.desc->d.fluid->name));
/* In fluid; TODO: check distance wrt local geometry (use 4V/S?) */
}
}
@@ -375,40 +375,47 @@ error:
}
#define READ_RANDOM_STATE(Name) \
- if(!str_is_empty(Name)) { \
- const char* name = str_cget(Name); \
- stream = fopen(name, "r"); \
- if(!stream) { \
- res = RES_IO_ERR; \
- logger_print(stardis->logger, LOG_ERROR, \
- "Could not open generator's state file ('%s').\n", \
- name); \
- goto error; \
+ if(!stardis->mpi_initialized || stardis->mpi_rank == 0) { \
+ if(str_is_empty(Name)) { \
+ /* Force using threefry independently of the default RNG type */ \
+ args.rng_type = SSP_RNG_THREEFRY; \
+ } else { \
+ const char* name = str_cget(Name); \
+ stream = fopen(name, "r"); \
+ if(!stream) { \
+ res = RES_IO_ERR; \
+ logger_print(stardis->logger, LOG_ERROR, \
+ "Could not open generator's state file ('%s').\n", \
+ name); \
+ goto error; \
+ } \
+ ERR(ssp_rng_create(stardis->allocator, SSP_RNG_THREEFRY, &args.rng_state)); \
+ res = read_random_generator_state(args.rng_state, stream); \
+ if(res != RES_OK) { \
+ logger_print(stardis->logger, LOG_ERROR, \
+ "Could not read random generator's state ('%s').\n", \
+ name); \
+ goto error; \
+ } \
+ fclose(stream); stream = NULL; \
} \
- ERR(ssp_rng_create(stardis->allocator, SSP_RNG_MT19937_64, &args.rng_state)); \
- res = read_random_generator_state(args.rng_state, stream); \
- if(res != RES_OK) { \
- logger_print(stardis->logger, LOG_ERROR, \
- "Could not read random generator's state ('%s').\n", \
- name); \
- goto error; \
- } \
- fclose(stream); stream = NULL; \
}
#define WRITE_RANDOM_STATE(Name) \
- if(!str_is_empty(Name)) { \
- const char* name = str_cget(Name); \
- stream = fopen(name, "wb"); \
- if(!stream) { \
- res = RES_IO_ERR; \
- logger_print(stardis->logger, LOG_ERROR, \
- "Could not write random generator's state ('%s').\n", \
- name); \
- goto error; \
+ if(!stardis->mpi_initialized || stardis->mpi_rank == 0) { \
+ if(!str_is_empty(Name)) { \
+ const char* name = str_cget(Name); \
+ stream = fopen(name, "wb"); \
+ if(!stream) { \
+ res = RES_IO_ERR; \
+ logger_print(stardis->logger, LOG_ERROR, \
+ "Could not write random generator's state ('%s').\n", \
+ name); \
+ goto error; \
+ } \
+ ERR(write_random_generator_state(estimator, stream)); \
+ fclose(stream); stream = NULL; \
} \
- ERR(write_random_generator_state(estimator, stream)); \
- fclose(stream); stream = NULL; \
}
static res_T
@@ -436,50 +443,59 @@ compute_probe(struct stardis* stardis, struct time* start)
READ_RANDOM_STATE(&stardis->rndgen_state_in_filename);
if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- time_current(&compute_start);
- ERR(sdis_solve_probe_green_function(stardis->sdis_scn, &args, &green));
- time_current(&compute_end);
- if(stardis->mode & MODE_BIN_GREEN) {
- struct time output_end;
- ASSERT(!str_is_empty(&stardis->bin_green_filename));
- stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
- if(!stream) {
- res = RES_IO_ERR;
- goto error;
- }
- ERR(dump_green_bin(green, stardis, stream));
- fclose(stream); stream = NULL;
- if(str_cget(&stardis->end_paths_filename)
- && strlen(str_cget(&stardis->end_paths_filename)))
- {
- stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_probe_green_function(stardis->sdis_scn, &args, &green));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_probe_green_function(stardis->sdis_scn, &args, &green));
+ time_current(&compute_end);
+ if(stardis->mode & MODE_BIN_GREEN) {
+ struct time output_end;
+ ASSERT(!str_is_empty(&stardis->bin_green_filename));
+ stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
if(!stream) {
res = RES_IO_ERR;
goto error;
}
- ERR(dump_paths_end(green, stardis, stream));
+ ERR(dump_green_bin(green, stardis, stream));
fclose(stream); stream = NULL;
+ if(str_cget(&stardis->end_paths_filename)
+ && strlen(str_cget(&stardis->end_paths_filename)))
+ {
+ stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(!stream) {
+ res = RES_IO_ERR;
+ goto error;
+ }
+ ERR(dump_paths_end(green, stardis, stream));
+ fclose(stream); stream = NULL;
+ }
+ time_current(&output_end);
+ ERR(print_computation_time(NULL, stardis,
+ start, &compute_start, &compute_end, &output_end));
+ }
+ if(stardis->mode & MODE_GREEN) {
+ ERR(dump_green_ascii(green, stardis, stdout));
}
- time_current(&output_end);
- ERR(print_computation_time(NULL, stardis,
- start, &compute_start, &compute_end, &output_end));
- }
- if(stardis->mode & MODE_GREEN) {
- ERR(dump_green_ascii(green, stardis, stdout));
}
} else {
args.register_paths = stardis->dump_paths;
- time_current(&compute_start);
- ERR(sdis_solve_probe(stardis->sdis_scn, &args, &estimator));
- time_current(&compute_end);
- ERR(print_computation_time(estimator, stardis,
- start, &compute_start, &compute_end, NULL));
- ERR(print_single_MC_result(estimator, stardis, stdout));
-
- /* Dump recorded paths according to user settings */
- dump_ctx.stardis = stardis;
- dump_ctx.rank = 0;
- ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ args.picard_order = stardis->picard_order;
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_probe(stardis->sdis_scn, &args, &estimator));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_probe(stardis->sdis_scn, &args, &estimator));
+ time_current(&compute_end);
+ ERR(print_computation_time(estimator, stardis,
+ start, &compute_start, &compute_end, NULL));
+ ERR(print_single_MC_result(estimator, stardis, stdout));
+
+ /* Dump recorded paths according to user settings */
+ dump_ctx.stardis = stardis;
+ dump_ctx.rank = 0;
+ ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ }
}
/* Output random state? */
@@ -532,7 +548,7 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start)
ASSERT(prop[SG3D_INTFACE] < dcount);
intface_desc = descriptions + prop[SG3D_INTFACE];
if(intface_desc->type == DESC_SOLID_SOLID_CONNECT)
- tcr = intface_desc->d.ss_connect.tcr;
+ tcr = intface_desc->d.ss_connect->tcr;
}
if(str_is_empty(&stardis->solve_name)) {
@@ -544,7 +560,7 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start)
const struct description* d;
ASSERT(prop[SG3D_FRONT] < dcount);
d = descriptions + prop[SG3D_FRONT];
- ASSERT(d->type == DESC_MAT_SOLID || d->type == DESC_MAT_FLUID);
+ ASSERT(DESC_IS_MEDIUM(d->type));
medium_name = str_cget(get_description_name(d));
compute_side = SDIS_FRONT;
compute_side_name = "FRONT";
@@ -553,7 +569,7 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start)
const struct description* d;
ASSERT(prop[SG3D_BACK] < dcount);
d = descriptions + prop[SG3D_BACK];
- ASSERT(d->type == DESC_MAT_SOLID || d->type == DESC_MAT_FLUID);
+ ASSERT(DESC_IS_MEDIUM(d->type));
medium_name = str_cget(get_description_name(d));
compute_side = SDIS_BACK;
compute_side_name = "BACK";
@@ -573,12 +589,10 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start)
fd = descriptions + prop[SG3D_FRONT];
bd = descriptions + prop[SG3D_BACK];
- ASSERT(fd->type == DESC_MAT_SOLID || fd->type == DESC_MAT_FLUID);
- fmat_id = (fd->type == DESC_MAT_SOLID)
- ? fd->d.solid.solid_id : fd->d.fluid.fluid_id;
- ASSERT(bd->type == DESC_MAT_SOLID || bd->type == DESC_MAT_FLUID);
- bmat_id = (bd->type == DESC_MAT_SOLID)
- ? bd->d.solid.solid_id : bd->d.fluid.fluid_id;
+ ASSERT(DESC_IS_MEDIUM(fd->type));
+ ASSERT(DESC_IS_MEDIUM(bd->type));
+ description_get_medium_id(fd, &fmat_id);
+ description_get_medium_id(bd, &bmat_id);
if(med_id != fmat_id && med_id != bmat_id) { /* Not here */
logger_print(stardis->logger, LOG_ERROR,
@@ -671,51 +685,61 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start)
READ_RANDOM_STATE(&stardis->rndgen_state_in_filename);
if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- time_current(&compute_start);
- ERR(sdis_solve_probe_boundary_green_function(stardis->sdis_scn, &args,
- &green));
- time_current(&compute_end);
- if(stardis->mode & MODE_BIN_GREEN) {
- struct time output_end;
- ASSERT(!str_is_empty(&stardis->bin_green_filename));
- stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
- if(!stream) {
- res = RES_IO_ERR;
- goto error;
- }
- ERR(dump_green_bin(green, stardis, stream));
- fclose(stream); stream = NULL;
- if(str_cget(&stardis->end_paths_filename)
- && strlen(str_cget(&stardis->end_paths_filename)))
- {
- stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_probe_boundary_green_function(stardis->sdis_scn, &args,
+ &green));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_probe_boundary_green_function(stardis->sdis_scn, &args,
+ &green));
+ time_current(&compute_end);
+ if(stardis->mode & MODE_BIN_GREEN) {
+ struct time output_end;
+ ASSERT(!str_is_empty(&stardis->bin_green_filename));
+ stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
if(!stream) {
res = RES_IO_ERR;
goto error;
}
- ERR(dump_paths_end(green, stardis, stream));
+ ERR(dump_green_bin(green, stardis, stream));
fclose(stream); stream = NULL;
+ if(str_cget(&stardis->end_paths_filename)
+ && strlen(str_cget(&stardis->end_paths_filename)))
+ {
+ stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(!stream) {
+ res = RES_IO_ERR;
+ goto error;
+ }
+ ERR(dump_paths_end(green, stardis, stream));
+ fclose(stream); stream = NULL;
+ }
+ time_current(&output_end);
+ ERR(print_computation_time(NULL, stardis,
+ start, &compute_start, &compute_end, &output_end));
+ }
+ if(stardis->mode & MODE_GREEN) {
+ ERR(dump_green_ascii(green, stardis, stdout));
}
- time_current(&output_end);
- ERR(print_computation_time(NULL, stardis,
- start, &compute_start, &compute_end, &output_end));
- }
- if(stardis->mode & MODE_GREEN) {
- ERR(dump_green_ascii(green, stardis, stdout));
}
} else {
args.register_paths = stardis->dump_paths;
- time_current(&compute_start);
- ERR(sdis_solve_probe_boundary(stardis->sdis_scn, &args, &estimator));
- time_current(&compute_end);
- ERR(print_computation_time(estimator, stardis,
- start, &compute_start, &compute_end, NULL));
- ERR(print_single_MC_result(estimator, stardis, stdout));
+ args.picard_order = stardis->picard_order;
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_probe_boundary(stardis->sdis_scn, &args, &estimator));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_probe_boundary(stardis->sdis_scn, &args, &estimator));
+ time_current(&compute_end);
+ ERR(print_computation_time(estimator, stardis,
+ start, &compute_start, &compute_end, NULL));
+ ERR(print_single_MC_result(estimator, stardis, stdout));
- /* Dump recorded paths according to user settings */
- dump_ctx.stardis = stardis;
- dump_ctx.rank = 0;
- ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ /* Dump recorded paths according to user settings */
+ dump_ctx.stardis = stardis;
+ dump_ctx.rank = 0;
+ ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ }
}
/* Output random state? */
@@ -849,48 +873,53 @@ compute_camera(struct stardis* stardis, struct time* start)
args.cam = cam;
d2_set(args.time_range, stardis->camera.time_range);
- args.image_resolution[0] = width;
- args.image_resolution[1] = height;
+ args.image_definition[0] = width;
+ args.image_definition[1] = height;
args.spp = (size_t)stardis->camera.spp;
args.register_paths = stardis->dump_paths;
+ args.picard_order = stardis->picard_order;
/* Launch the simulation */
- time_current(&compute_start);
- ERR(sdis_solve_camera(stardis->sdis_scn, &args, &buf));
- time_current(&compute_end);
-
- /* Write the image */
- if(str_is_empty(&stardis->camera.file_name))
- stream = stdout;
- else {
- stream = fopen(str_cget(&stardis->camera.file_name), "w");
- if(!stream) {
- res = RES_IO_ERR;
- goto error;
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_camera(stardis->sdis_scn, &args, &buf));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_camera(stardis->sdis_scn, &args, &buf));
+ time_current(&compute_end);
+
+ /* Write the image */
+ if(str_is_empty(&stardis->camera.file_name))
+ stream = stdout;
+ else {
+ stream = fopen(str_cget(&stardis->camera.file_name), "w");
+ if(!stream) {
+ res = RES_IO_ERR;
+ goto error;
+ }
}
- }
- ASSERT(stardis->camera.fmt == STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK
- || stardis->camera.fmt == STARDIS_RENDERING_OUTPUT_FILE_FMT_HT);
- if(stardis->camera.fmt == STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK)
- ERR(dump_vtk_image(buf, stream));
- else ERR(dump_ht_image(buf, stream));
- if(!str_is_empty(&stardis->camera.file_name))
- fclose(stream);
-
- /* Dump recorded paths according to user settings */
- dump_ctx.stardis = stardis;
- dump_ctx.rank = 0;
- ERR(sdis_estimator_buffer_get_definition(buf, definition));
- FOR_EACH(iy, 0, definition[1]) {
- FOR_EACH(ix, 0, definition[0]) {
- const struct sdis_estimator* estimator;
- ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator));
- ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ ASSERT(stardis->camera.fmt == STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK
+ || stardis->camera.fmt == STARDIS_RENDERING_OUTPUT_FILE_FMT_HT);
+ if(stardis->camera.fmt == STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK)
+ ERR(dump_vtk_image(buf, stream));
+ else ERR(dump_ht_image(buf, stream));
+ if(!str_is_empty(&stardis->camera.file_name))
+ fclose(stream);
+
+ /* Dump recorded paths according to user settings */
+ dump_ctx.stardis = stardis;
+ dump_ctx.rank = 0;
+ ERR(sdis_estimator_buffer_get_definition(buf, definition));
+ FOR_EACH(iy, 0, definition[1]) {
+ FOR_EACH(ix, 0, definition[0]) {
+ const struct sdis_estimator* estimator;
+ ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator));
+ ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ }
}
+ time_current(&output_end);
+ ERR(print_computation_time(NULL, stardis,
+ start, &compute_start, &compute_end, NULL));
}
- time_current(&output_end);
- ERR(print_computation_time(NULL, stardis,
- start, &compute_start, &compute_end, NULL));
end:
if(cam) SDIS(camera_ref_put(cam));
@@ -932,49 +961,58 @@ compute_medium(struct stardis* stardis, struct time* start)
READ_RANDOM_STATE(&stardis->rndgen_state_in_filename);
if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- time_current(&compute_start);
- ERR(sdis_solve_medium_green_function(stardis->sdis_scn, &args, &green));
- time_current(&compute_end);
- if(stardis->mode & MODE_BIN_GREEN) {
- struct time output_end;
- ASSERT(!str_is_empty(&stardis->bin_green_filename));
- stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
- if(!stream) {
- res = RES_IO_ERR;
- goto error;
- }
- ERR(dump_green_bin(green, stardis, stream));
- fclose(stream); stream = NULL;
- if(str_cget(&stardis->end_paths_filename)
- && strlen(str_cget(&stardis->end_paths_filename)))
- {
- stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_medium_green_function(stardis->sdis_scn, &args, &green));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_medium_green_function(stardis->sdis_scn, &args, &green));
+ time_current(&compute_end);
+ if(stardis->mode & MODE_BIN_GREEN) {
+ struct time output_end;
+ ASSERT(!str_is_empty(&stardis->bin_green_filename));
+ stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
if(!stream) {
res = RES_IO_ERR;
goto error;
}
- ERR(dump_paths_end(green, stardis, stream));
+ ERR(dump_green_bin(green, stardis, stream));
fclose(stream); stream = NULL;
+ if(str_cget(&stardis->end_paths_filename)
+ && strlen(str_cget(&stardis->end_paths_filename)))
+ {
+ stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(!stream) {
+ res = RES_IO_ERR;
+ goto error;
+ }
+ ERR(dump_paths_end(green, stardis, stream));
+ fclose(stream); stream = NULL;
+ }
+ time_current(&output_end);
+ ERR(print_computation_time(NULL, stardis,
+ start, &compute_start, &compute_end, &output_end));
+ }
+ if(stardis->mode & MODE_GREEN) {
+ ERR(dump_green_ascii(green, stardis, stdout));
}
- time_current(&output_end);
- ERR(print_computation_time(NULL, stardis,
- start, &compute_start, &compute_end, &output_end));
- }
- if(stardis->mode & MODE_GREEN) {
- ERR(dump_green_ascii(green, stardis, stdout));
}
} else {
args.register_paths = stardis->dump_paths;
- time_current(&compute_start);
- ERR(sdis_solve_medium(stardis->sdis_scn, &args, &estimator));
- time_current(&compute_end);
- ERR(print_computation_time(estimator, stardis,
- start, &compute_start, &compute_end, NULL));
- ERR(print_single_MC_result(estimator, stardis, stdout));
- /* Dump recorded paths according to user settings */
- dump_ctx.stardis = stardis;
- dump_ctx.rank = 0;
- ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ args.picard_order = stardis->picard_order;
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_medium(stardis->sdis_scn, &args, &estimator));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_medium(stardis->sdis_scn, &args, &estimator));
+ time_current(&compute_end);
+ ERR(print_computation_time(estimator, stardis,
+ start, &compute_start, &compute_end, NULL));
+ ERR(print_single_MC_result(estimator, stardis, stdout));
+ /* Dump recorded paths according to user settings */
+ dump_ctx.stardis = stardis;
+ dump_ctx.rank = 0;
+ ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ }
}
/* Output random state? */
@@ -1063,49 +1101,58 @@ compute_boundary(struct stardis* stardis, struct time* start)
READ_RANDOM_STATE(&stardis->rndgen_state_in_filename);
if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- time_current(&compute_start);
- ERR(sdis_solve_boundary_green_function(stardis->sdis_scn, &args, &green));
- time_current(&compute_end);
- if(stardis->mode & MODE_BIN_GREEN) {
- struct time output_end;
- ASSERT(!str_is_empty(&stardis->bin_green_filename));
- stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
- if(!stream) {
- res = RES_IO_ERR;
- goto error;
- }
- ERR(dump_green_bin(green, stardis, stream));
- fclose(stream); stream = NULL;
- if(str_cget(&stardis->end_paths_filename)
- && strlen(str_cget(&stardis->end_paths_filename)))
- {
- stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_boundary_green_function(stardis->sdis_scn, &args, &green));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_boundary_green_function(stardis->sdis_scn, &args, &green));
+ time_current(&compute_end);
+ if(stardis->mode & MODE_BIN_GREEN) {
+ struct time output_end;
+ ASSERT(!str_is_empty(&stardis->bin_green_filename));
+ stream = fopen(str_cget(&stardis->bin_green_filename), "wb");
if(!stream) {
res = RES_IO_ERR;
goto error;
}
- ERR(dump_paths_end(green, stardis, stream));
+ ERR(dump_green_bin(green, stardis, stream));
fclose(stream); stream = NULL;
+ if(str_cget(&stardis->end_paths_filename)
+ && strlen(str_cget(&stardis->end_paths_filename)))
+ {
+ stream = fopen(str_cget(&stardis->end_paths_filename), "w");
+ if(!stream) {
+ res = RES_IO_ERR;
+ goto error;
+ }
+ ERR(dump_paths_end(green, stardis, stream));
+ fclose(stream); stream = NULL;
+ }
+ time_current(&output_end);
+ ERR(print_computation_time(NULL, stardis,
+ start, &compute_start, &compute_end, &output_end));
+ }
+ if(stardis->mode & MODE_GREEN) {
+ ERR(dump_green_ascii(green, stardis, stdout));
}
- time_current(&output_end);
- ERR(print_computation_time(NULL, stardis,
- start, &compute_start, &compute_end, &output_end));
- }
- if(stardis->mode & MODE_GREEN) {
- ERR(dump_green_ascii(green, stardis, stdout));
}
} else {
args.register_paths = stardis->dump_paths;
- time_current(&compute_start);
- ERR(sdis_solve_boundary(stardis->sdis_scn, &args, &estimator));
- time_current(&compute_end);
- ERR(print_computation_time(estimator, stardis,
- start, &compute_start, &compute_end, NULL));
- ERR(print_single_MC_result(estimator, stardis, stdout));
- /* Dump recorded paths according to user settings */
- dump_ctx.stardis = stardis;
- dump_ctx.rank = 0;
- ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ args.picard_order = stardis->picard_order;
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_boundary(stardis->sdis_scn, &args, &estimator));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_boundary(stardis->sdis_scn, &args, &estimator));
+ time_current(&compute_end);
+ ERR(print_computation_time(estimator, stardis,
+ start, &compute_start, &compute_end, NULL));
+ ERR(print_single_MC_result(estimator, stardis, stdout));
+ /* Dump recorded paths according to user settings */
+ dump_ctx.stardis = stardis;
+ dump_ctx.rank = 0;
+ ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ }
}
/* Output random state? */
@@ -1140,22 +1187,27 @@ compute_flux_boundary(struct stardis* stardis, struct time* start)
= darray_size_t_cdata_get(&stardis->compute_surface.primitives);
args.nprimitives
= darray_size_t_size_get(&stardis->compute_surface.primitives);
+ args.picard_order = stardis->picard_order;
d2_set(args.time_range, stardis->time_range);
/* Input random state? */
READ_RANDOM_STATE(&stardis->rndgen_state_in_filename);
- time_current(&compute_start);
- ERR(sdis_solve_boundary_flux(stardis->sdis_scn, &args, &estimator));
- time_current(&compute_end);
- ERR(print_computation_time(estimator, stardis,
- start, &compute_start, &compute_end, NULL));
- ERR(print_single_MC_result(estimator, stardis, stdout));
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(sdis_solve_boundary_flux(stardis->sdis_scn, &args, &estimator));
+ } else {
+ time_current(&compute_start);
+ ERR(sdis_solve_boundary_flux(stardis->sdis_scn, &args, &estimator));
+ time_current(&compute_end);
+ ERR(print_computation_time(estimator, stardis,
+ start, &compute_start, &compute_end, NULL));
+ ERR(print_single_MC_result(estimator, stardis, stdout));
- /* Dump recorded paths according to user settings */
- dump_ctx.stardis = stardis;
- dump_ctx.rank = 0;
- ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ /* Dump recorded paths according to user settings */
+ dump_ctx.stardis = stardis;
+ dump_ctx.rank = 0;
+ ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx));
+ }
/* Output random state? */
WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename);
@@ -1201,11 +1253,14 @@ compute_map(struct stardis* stardis, struct time* start)
= darray_size_t_size_get(&stardis->compute_surface.primitives);
d2_set(args.time_range, stardis->time_range);
args.register_paths = stardis->dump_paths;
+ args.picard_order = stardis->picard_order;
ERR(sdis_solve_boundary(stardis->sdis_scn, &args,
darray_estimators_data_get(&estimators) + p));
}
- dump_map(stardis, &estimators, stdout);
+ if(stardis->mpi_initialized && stardis->mpi_rank != 0) {
+ ERR(dump_map(stardis, &estimators, stdout));
+ }
end:
if(estimators_initialized) {
@@ -1240,26 +1295,16 @@ find_medium_by_name
ASSERT(stardis && name);
FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) {
- struct description*
- desc = darray_descriptions_data_get(&stardis->descriptions) + i;
- if(desc->type == DESC_MAT_SOLID) {
- if(str_eq(name, &desc->d.solid.name)) {
- unsigned id = desc->d.solid.solid_id;
- ASSERT(darray_media_ptr_size_get(&stardis->media) > id);
- medium = darray_media_ptr_data_get(&stardis->media)[id];
- if(out_id) *out_id = id;
- break;
- }
- }
- else if(desc->type == DESC_MAT_FLUID) {
- if(str_eq(name, &desc->d.fluid.name)) {
- unsigned id = desc->d.fluid.fluid_id;
- ASSERT(darray_media_ptr_size_get(&stardis->media) > id);
- medium = darray_media_ptr_data_get(&stardis->media)[id];
- if(out_id) *out_id = id;
- break;
- }
- }
+ unsigned id;
+ struct description* desc =
+ darray_descriptions_data_get(&stardis->descriptions) + i;
+ if(!str_eq(name, get_description_name(desc)))
+ continue;
+ description_get_medium_id(desc, &id);
+ ASSERT(darray_media_ptr_size_get(&stardis->media) > id);
+ medium = darray_media_ptr_data_get(&stardis->media)[id];
+ if(out_id) *out_id = id;
+ break;
}
return medium;
}
diff --git a/src/stardis-compute.h b/src/stardis-compute.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/stardis-default.h.in b/src/stardis-default.h.in
@@ -17,8 +17,10 @@
#define STARDIS_DEFAULT_H
#define STARDIS_RENDERING_FMT(Fmt) STARDIS_RENDERING_OUTPUT_FILE_FMT_ ## Fmt
-#define STARDIS_DEFAULT_AMBIENT_TEMP @STARDIS_ARGS_DEFAULT_AMBIENT_TEMP@
+#define STARDIS_DEFAULT_TRAD @STARDIS_ARGS_DEFAULT_TRAD@
+#define STARDIS_DEFAULT_TRAD_REFERENCE @STARDIS_ARGS_DEFAULT_TRAD_REFERENCE@
#define STARDIS_DEFAULT_COMPUTE_TIME @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@
+#define STARDIS_DEFAULT_PICARD_ORDER @STARDIS_ARGS_DEFAULT_PICARD_ORDER@
#define STARDIS_DEFAULT_RENDERING_FOV @STARDIS_ARGS_DEFAULT_RENDERING_FOV@
#define STARDIS_DEFAULT_RENDERING_IMG_HEIGHT @STARDIS_ARGS_DEFAULT_RENDERING_IMG_HEIGHT@
#define STARDIS_DEFAULT_RENDERING_IMG_WIDTH @STARDIS_ARGS_DEFAULT_RENDERING_IMG_WIDTH@
@@ -28,7 +30,6 @@
#define STARDIS_DEFAULT_RENDERING_TGT @STARDIS_ARGS_DEFAULT_RENDERING_TGT@
#define STARDIS_DEFAULT_RENDERING_TIME @STARDIS_ARGS_DEFAULT_RENDERING_TIME@
#define STARDIS_DEFAULT_RENDERING_UP @STARDIS_ARGS_DEFAULT_RENDERING_UP@
-#define STARDIS_DEFAULT_REFERENCE_TEMP @STARDIS_ARGS_DEFAULT_REFERENCE_TEMP@
#define STARDIS_DEFAULT_SAMPLES_COUNT @STARDIS_ARGS_DEFAULT_SAMPLES_COUNT@
#define STARDIS_DEFAULT_SCALE_FACTOR @STARDIS_ARGS_DEFAULT_SCALE_FACTOR@
#define STARDIS_DEFAULT_VERBOSE_LEVEL @STARDIS_ARGS_DEFAULT_VERBOSE_LEVEL@
diff --git a/src/stardis-fluid.c b/src/stardis-fluid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
#include <sdis.h>
+#include <rsys/mem_allocator.h>
+
#include <limits.h>
/*******************************************************************************
@@ -30,9 +32,9 @@ fluid_get_calorific_capacity
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct fluid* fluid_props = sdis_data_cget(data);
+ const struct fluid* const* fluid_props = sdis_data_cget(data);
(void)vtx;
- return fluid_props->cp;
+ return (*fluid_props)->cp;
}
static double
@@ -40,9 +42,9 @@ fluid_get_volumic_mass
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct fluid* fluid_props = sdis_data_cget(data);
+ const struct fluid* const* fluid_props = sdis_data_cget(data);
(void)vtx;
- return fluid_props->rho;
+ return (*fluid_props)->rho;
}
static double
@@ -50,21 +52,21 @@ fluid_get_temperature
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct fluid* fluid_props = sdis_data_cget(data);
- if(fluid_props->imposed_temperature >= 0)
+ const struct fluid* const* fluid_props = sdis_data_cget(data);
+ if((*fluid_props)->imposed_temperature >= 0)
/* If there is an imposed temp, it is imposed regardless of time */
- return fluid_props->imposed_temperature;
- if(vtx->time <= fluid_props->t0) {
+ return (*fluid_props)->imposed_temperature;
+ if(vtx->time <= (*fluid_props)->t0) {
/* If time is <= t0: use tinit */
- if(fluid_props->tinit < 0) {
- if(str_is_empty(&fluid_props->name)) {
+ if((*fluid_props)->tinit < 0) {
+ if(str_is_empty(&(*fluid_props)->name)) {
FATAL("fluid_get_temperature: getting undefined Tinit\n");
} else {
VFATAL("fluid_get_temperature: getting undefined Tinit (fluid '%s')\n",
- ARG1(str_cget(&fluid_props->name)));
+ ARG1(str_cget(&(*fluid_props)->name)));
}
}
- return fluid_props->tinit;
+ return (*fluid_props)->tinit;
}
return -1; /* Unknown temperature */
}
@@ -81,22 +83,21 @@ create_solver_fluid
res_T res = RES_OK;
struct sdis_fluid_shader fluid_shader = SDIS_FLUID_SHADER_NULL;
struct sdis_data* data = NULL;
- struct fluid* props;
+ const struct fluid** props;
ASSERT(stardis && fluid_props);
fluid_shader.calorific_capacity = fluid_get_calorific_capacity;
fluid_shader.volumic_mass = fluid_get_volumic_mass;
fluid_shader.temperature = fluid_get_temperature;
- ERR(sdis_data_create(stardis->dev, sizeof(struct fluid), ALIGNOF(struct fluid),
+ ERR(sdis_data_create(stardis->dev, sizeof(struct fluid*), ALIGNOF(struct fluid*),
NULL, &data));
props = sdis_data_get(data); /* Fetch the allocated memory space */
- init_fluid(stardis->allocator, props);
- cp_fluid(props, fluid_props);
+ *props = fluid_props;
if(fluid_props->fluid_id >= darray_media_ptr_size_get(&stardis->media)) {
ERR(darray_media_ptr_resize(&stardis->media, fluid_props->fluid_id + 1));
}
- ASSERT(darray_media_ptr_data_get(&stardis->media)[fluid_props->fluid_id] == NULL);
+ ASSERT(!darray_media_ptr_data_get(&stardis->media)[fluid_props->fluid_id]);
ERR(sdis_fluid_create(stardis->dev, &fluid_shader, data,
darray_media_ptr_data_get(&stardis->media) + fluid_props->fluid_id));
@@ -107,25 +108,44 @@ error:
goto end;
}
-void
-init_fluid(struct mem_allocator* allocator, struct fluid* dst)
+res_T
+init_fluid(struct mem_allocator* allocator, struct fluid** dst)
{
- str_init(allocator, &dst->name);
- dst->rho = 1;
- dst->cp = 1;
- dst->tinit = -1;
- dst->imposed_temperature = -1;
- dst->t0 = 0;
- dst->is_outside = 0;
- dst->is_green = 0;
- dst->desc_id = UINT_MAX;
- dst->fluid_id = UINT_MAX;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct fluid));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ str_initialized = 1;
+ (*dst)->rho = 1;
+ (*dst)->cp = 1;
+ (*dst)->tinit = -1;
+ (*dst)->imposed_temperature = -1;
+ (*dst)->t0 = 0;
+ (*dst)->is_outside = 0;
+ (*dst)->is_green = 0;
+ (*dst)->desc_id = UINT_MAX;
+ (*dst)->fluid_id = UINT_MAX;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
void
-release_fluid(struct fluid* fluid)
+release_fluid
+ (struct fluid* fluid,
+ struct mem_allocator* allocator)
{
+ ASSERT(fluid && allocator);
str_release(&fluid->name);
+ MEM_RM(allocator, fluid);
}
res_T
@@ -147,18 +167,3 @@ end:
error:
goto end;
}
-
-res_T
-cp_fluid(struct fluid* dst, const struct fluid* src)
-{
- dst->rho = src->rho;
- dst->cp = src->cp;
- dst->tinit = src->tinit;
- dst->imposed_temperature = src->imposed_temperature;
- dst->t0 = src->t0;
- dst->is_outside = src->is_outside;
- dst->is_green = src->is_green;
- dst->desc_id = src->desc_id;
- dst->fluid_id = src->fluid_id;
- return str_copy(&dst->name, &src->name);
-}
diff --git a/src/stardis-fluid.h b/src/stardis-fluid.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@
#include <rsys/str.h>
struct stardis;
+struct mem_allocator;
/*******************************************************************************
* Fluid data
@@ -44,16 +45,15 @@ create_solver_fluid
(struct stardis* stardis,
const struct fluid* fluid_props);
-LOCAL_SYM void
-init_fluid(struct mem_allocator* allocator, struct fluid* dst);
+LOCAL_SYM res_T
+init_fluid(struct mem_allocator* allocator, struct fluid** dst);
LOCAL_SYM void
-release_fluid(struct fluid* fluid);
+release_fluid
+ (struct fluid* desc,
+ struct mem_allocator* allocator);
LOCAL_SYM res_T
str_print_fluid(struct str* str, const struct fluid* s);
-LOCAL_SYM res_T
-cp_fluid(struct fluid* dst, const struct fluid* src);
-
#endif
diff --git a/src/stardis-green-types.h.in b/src/stardis-green-types.h.in
@@ -0,0 +1,129 @@
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SDIS_GREEN_H
+#define SDIS_GREEN_H
+
+/* The number of the file format as presented thereafter */
+#define GREEN_FILE_FORMAT_VERSION @STARDIS_GREEN_TYPES_VERSION@
+
+/* The max length for a description name */
+#define DESC_NAME_MAX_LEN 63
+
+/* The string at the beginning of a binary Green file that identifies it */
+#define BIN_FILE_IDENT_STRING "GREEN_BIN_FILE:"
+
+/* The header of a binary Green file */
+struct green_file_header {
+ char green_string[sizeof(BIN_FILE_IDENT_STRING)];
+ unsigned file_format_version;
+ unsigned description_count;
+ unsigned solid_count;
+ unsigned fluid_count;
+ unsigned hbound_count;
+ unsigned tbound_count;
+ unsigned fbound_count;
+ unsigned sfconnect_count;
+ unsigned ssconnect_count;
+ size_t ok_count;
+ size_t failed_count;
+ double ambient_radiative_temperature;
+ double ambient_radiative_temperature_reference;
+ double time_range[2];
+};
+
+/* Different types of descriptions */
+enum green_description_type {
+ GREEN_MAT_SOLID,
+ GREEN_MAT_FLUID,
+ GREEN_BOUND_H,
+ GREEN_BOUND_T,
+ GREEN_BOUND_F,
+ GREEN_SOLID_FLUID_CONNECT,
+ GREEN_SOLID_SOLID_CONNECT
+};
+
+struct green_solid {
+ char name[DESC_NAME_MAX_LEN+1];
+ double conductivity;
+ double volumic_mass;
+ double calorific_capacity;
+ double volumic_power;
+ double initial_temperature;
+ double imposed_temperature;
+};
+
+struct green_fluid {
+ char name[DESC_NAME_MAX_LEN+1];
+ double volumic_mass;
+ double calorific_capacity;
+ double initial_temperature;
+ double imposed_temperature;
+};
+
+struct green_h_boundary {
+ char name[DESC_NAME_MAX_LEN+1];
+ double reference_temperature;
+ double emissivity;
+ double specular_fraction;
+ double convection_coefficient;
+ double imposed_temperature;
+};
+
+struct green_t_boundary {
+ char name[DESC_NAME_MAX_LEN+1];
+ double imposed_temperature;
+};
+
+struct green_f_boundary {
+ char name[DESC_NAME_MAX_LEN+1];
+ double imposed_flux;
+};
+
+struct green_solid_fluid_connect {
+ char name[DESC_NAME_MAX_LEN+1];
+ double reference_temperature;
+ double emissivity;
+ double specular_fraction;
+ double convection_coefficient;
+};
+
+struct green_solid_solid_connect {
+ char name[DESC_NAME_MAX_LEN+1];
+ double thermal_contact_resistance;
+};
+
+struct green_description {
+ enum green_description_type type;
+ union {
+ struct green_fluid fluid;
+ struct green_solid solid;
+ struct green_t_boundary t_boundary;
+ struct green_f_boundary f_boundary;
+ struct green_h_boundary h_boundary;
+ struct green_solid_fluid_connect sf_connect;
+ struct green_solid_solid_connect ss_connect;
+ } d;
+};
+
+/* The header of a Green sample */
+struct green_sample_header {
+ unsigned pw_count;
+ unsigned fx_count;
+ unsigned sample_end_description_id;
+ int at_initial;
+};
+
+#endif
diff --git a/src/stardis-intface.c b/src/stardis-intface.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -56,6 +56,16 @@ interface_get_flux
}
static double
+interface_get_ref_temperature
+ (const struct sdis_interface_fragment* frag,
+ struct sdis_data* data)
+{
+ const struct intface* interface_props = sdis_data_cget(data);
+ (void)frag;
+ return interface_props->ref_temperature;
+}
+
+static double
interface_get_emissivity
(const struct sdis_interface_fragment* frag,
struct sdis_data* data)
@@ -150,14 +160,14 @@ create_intface
if(front_defined) {
switch (descriptions[fd].type) {
case DESC_MAT_SOLID:
- id = descriptions[fd].d.solid.solid_id;
+ id = descriptions[fd].d.solid->solid_id;
solid_count++;
interface_props->front_medium_id = id;
front_med = media[id];
break;
case DESC_MAT_FLUID:
fluid_count++;
- id = descriptions[fd].d.fluid.fluid_id;
+ id = descriptions[fd].d.fluid->fluid_id;
interface_props->front_medium_id = id;
front_med = media[id];
fluid_side_shader = &interface_shader.front;
@@ -169,14 +179,14 @@ create_intface
if(back_defined) {
switch (descriptions[bd].type) {
case DESC_MAT_SOLID:
- id = descriptions[bd].d.solid.solid_id;
+ id = descriptions[bd].d.solid->solid_id;
solid_count++;
interface_props->back_medium_id = id;
back_med = media[id];
break;
case DESC_MAT_FLUID:
fluid_count++;
- id = descriptions[bd].d.fluid.fluid_id;
+ id = descriptions[bd].d.fluid->fluid_id;
interface_props->back_medium_id = id;
back_med = media[id];
/* Can overwrite fluid_side_shader. However it would imply two
@@ -222,9 +232,9 @@ create_intface
goto error;
}
type_checked = 1;
- ASSERT(connect->d.h_boundary.imposed_temperature >= 0);
+ ASSERT(connect->d.h_boundary->imposed_temperature >= 0);
interface_props->imposed_temperature
- = connect->d.h_boundary.imposed_temperature;
+ = connect->d.h_boundary->imposed_temperature;
ASSERT(fluid_side_shader);
fluid_side_shader->temperature = interface_get_temperature;
/* fall through */
@@ -234,7 +244,7 @@ create_intface
{
res = RES_BAD_ARG; goto error;
}
- ext_id = connect->d.h_boundary.mat_id; /* External material id */
+ ext_id = connect->d.h_boundary->mat_id; /* External material id */
ASSERT(ext_id < darray_media_ptr_size_get(&stardis->media));
ASSERT(sdis_medium_get_type(media[ext_id]) ==
(connect->type == DESC_BOUND_H_FOR_SOLID ? SDIS_FLUID : SDIS_SOLID));
@@ -242,15 +252,17 @@ create_intface
boundary_count++;
if(front_defined) back_med = media[ext_id];
else front_med = media[ext_id];
- interface_shader.convection_coef_upper_bound = connect->d.h_boundary.hc;
- interface_props->hc = connect->d.h_boundary.hc;
- interface_props->emissivity = connect->d.h_boundary.emissivity;
- interface_props->alpha = connect->d.h_boundary.specular_fraction;
- if(connect->d.h_boundary.hc > 0) {
+ interface_shader.convection_coef_upper_bound = connect->d.h_boundary->hc;
+ interface_props->hc = connect->d.h_boundary->hc;
+ interface_props->ref_temperature = connect->d.h_boundary->ref_temperature;
+ interface_props->emissivity = connect->d.h_boundary->emissivity;
+ interface_props->alpha = connect->d.h_boundary->specular_fraction;
+ if(connect->d.h_boundary->hc > 0) {
interface_shader.convection_coef = interface_get_convection_coef;
}
- if(connect->d.h_boundary.emissivity > 0) {
- ASSERT(fluid_side_shader);
+ ASSERT(fluid_side_shader);
+ fluid_side_shader->reference_temperature = interface_get_ref_temperature;
+ if(connect->d.h_boundary->emissivity > 0) {
fluid_side_shader->emissivity = interface_get_emissivity;
fluid_side_shader->specular_fraction = interface_get_alpha;
}
@@ -260,7 +272,7 @@ create_intface
res = RES_BAD_ARG;
goto error;
}
- ext_id = connect->d.t_boundary.mat_id; /* External material id */
+ ext_id = connect->d.t_boundary->mat_id; /* External material id */
ASSERT(ext_id < darray_media_ptr_size_get(&stardis->media));
ASSERT(sdis_medium_get_type(media[ext_id]) == SDIS_FLUID);
connection_count++;
@@ -278,11 +290,12 @@ create_intface
/* Set emissivity to 1 to allow radiative paths comming from
* a possible external fluid to 'see' the imposed T */
ASSERT(fluid_side_shader);
+ fluid_side_shader->reference_temperature = interface_get_ref_temperature;
fluid_side_shader->emissivity = interface_get_emissivity;
interface_props->emissivity = 1;
- ASSERT(connect->d.t_boundary.imposed_temperature >= 0);
+ ASSERT(connect->d.t_boundary->imposed_temperature >= 0);
interface_props->imposed_temperature
- = connect->d.t_boundary.imposed_temperature;
+ = connect->d.t_boundary->imposed_temperature;
break;
case DESC_BOUND_F_FOR_SOLID:
if(sdis_medium_get_type(def_medium) != SDIS_SOLID) {
@@ -292,14 +305,14 @@ create_intface
connection_count++;
boundary_count++;
if(front_defined) {
- back_med = media[connect->d.f_boundary.mat_id];
+ back_med = media[connect->d.f_boundary->mat_id];
interface_shader.front.flux = interface_get_flux;
} else {
- front_med = media[connect->d.f_boundary.mat_id];
+ front_med = media[connect->d.f_boundary->mat_id];
interface_shader.back.flux = interface_get_flux;
}
- ASSERT(connect->d.f_boundary.imposed_flux != SDIS_FLUX_NONE);
- interface_props->imposed_flux = connect->d.f_boundary.imposed_flux;
+ ASSERT(connect->d.f_boundary->imposed_flux != SDIS_FLUX_NONE);
+ interface_props->imposed_flux = connect->d.f_boundary->imposed_flux;
break;
case DESC_SOLID_FLUID_CONNECT:
/* Both front and back should be defined */
@@ -310,15 +323,17 @@ create_intface
ASSERT(front_defined && back_defined);
connection_count++;
solid_fluid_connection_count++;
- interface_shader.convection_coef_upper_bound = connect->d.sf_connect.hc;
- interface_props->hc = connect->d.sf_connect.hc;
- interface_props->emissivity = connect->d.sf_connect.emissivity;
- interface_props->alpha = connect->d.sf_connect.specular_fraction;
- if(connect->d.sf_connect.hc > 0) {
+ interface_shader.convection_coef_upper_bound = connect->d.sf_connect->hc;
+ interface_props->hc = connect->d.sf_connect->hc;
+ interface_props->ref_temperature = connect->d.sf_connect->ref_temperature;
+ interface_props->emissivity = connect->d.sf_connect->emissivity;
+ interface_props->alpha = connect->d.sf_connect->specular_fraction;
+ if(connect->d.sf_connect->hc > 0) {
interface_shader.convection_coef = interface_get_convection_coef;
}
- if(connect->d.sf_connect.emissivity > 0) {
- ASSERT(fluid_side_shader);
+ ASSERT(fluid_side_shader);
+ fluid_side_shader->reference_temperature = interface_get_ref_temperature;
+ if(connect->d.sf_connect->emissivity > 0) {
fluid_side_shader->emissivity = interface_get_emissivity;
fluid_side_shader->specular_fraction = interface_get_alpha;
}
@@ -332,8 +347,8 @@ create_intface
ASSERT(front_defined && back_defined);
connection_count++;
solid_solid_connection_count++;
- interface_props->tcr = connect->d.ss_connect.tcr;
- if(connect->d.ss_connect.tcr > 0) {
+ interface_props->tcr = connect->d.ss_connect->tcr;
+ if(connect->d.ss_connect->tcr > 0) {
interface_shader.thermal_contact_resistance = interface_get_tcr;
}
break;
diff --git a/src/stardis-intface.h b/src/stardis-intface.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@ struct dummies;
struct intface {
/* fluid - solid */
double hc;
+ double ref_temperature;
double emissivity;
double alpha;
/* solid - solid */
diff --git a/src/stardis-main.c b/src/stardis-main.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,10 @@
#include <stdlib.h>
#include <stdio.h>
+#ifdef STARDIS_ENABLE_MPI
+#include <mpi.h>
+#endif
+
int
main
(int argc,
@@ -44,12 +48,16 @@ main
time_current(&start);
+#ifdef STARDIS_ENABLE_MPI
+ ERR(init_mpi(&argc, &argv, log_err_fn, log_warn_fn));
+#endif
+
ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
allocator_initialized = 1;
ERR(logger_init(&allocator, &logger));
logger_initialized = 1;
- /* Active loggin for args pasing */
+ /* Active loggin for args parsing */
logger_set_stream(&logger, LOG_ERROR, log_err_fn, NULL);
logger_set_stream(&logger, LOG_WARNING, log_warn_fn, NULL);
logger_set_stream(&logger, LOG_OUTPUT, log_prt_fn, NULL);
@@ -119,6 +127,10 @@ exit:
}
mem_shutdown_proxy_allocator(&allocator);
}
+#ifdef STARDIS_ENABLE_MPI
+ finalize_mpi();
+#endif
+
return err;
error:
if(mode & COMPUTE_MODES)
diff --git a/src/stardis-output.c b/src/stardis-output.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
#include "stardis-solid.h"
#include "stardis-intface.h"
#include "stardis-app.h"
+#include "stardis-green-types.h"
#include <sdis.h>
@@ -67,6 +68,83 @@ enum enclosure_errors_t {
ENCLOSURE_WITH_UNDEF_MEDIUM = BIT(2)
};
+
+static res_T
+copy_desc_to_green_desc
+ (struct green_description* gdesc,
+ const struct darray_descriptions* descriptions,
+ const size_t idx)
+{
+ size_t sz;
+ const struct description* desc;
+ ASSERT(gdesc && descriptions);
+ sz = darray_descriptions_size_get(descriptions);
+ CHK(idx < sz);
+ desc = darray_descriptions_cdata_get(descriptions) + idx;
+ switch(desc->type) {
+ case DESC_MAT_SOLID:
+ gdesc->type = GREEN_MAT_SOLID;
+ strcpy(gdesc->d.solid.name, str_cget(&desc->d.solid->name));
+ gdesc->d.solid.conductivity = desc->d.solid->lambda;
+ gdesc->d.solid.volumic_mass = desc->d.solid->rho;
+ gdesc->d.solid.calorific_capacity = desc->d.solid->cp;
+ gdesc->d.solid.volumic_power = desc->d.solid->vpower;
+ gdesc->d.solid.initial_temperature = desc->d.solid->tinit;
+ gdesc->d.solid.imposed_temperature = desc->d.solid->imposed_temperature;
+ break;
+ case DESC_MAT_FLUID:
+ gdesc->type = GREEN_MAT_FLUID;
+ strcpy(gdesc->d.fluid.name, str_cget(&desc->d.fluid->name));
+ gdesc->d.fluid.volumic_mass = desc->d.fluid->rho;
+ gdesc->d.fluid.calorific_capacity = desc->d.fluid->cp;
+ gdesc->d.fluid.initial_temperature = desc->d.fluid->tinit;
+ gdesc->d.fluid.imposed_temperature = desc->d.fluid->imposed_temperature;
+ break;
+ case DESC_BOUND_H_FOR_FLUID:
+ case DESC_BOUND_H_FOR_SOLID:
+ gdesc->type = GREEN_BOUND_H;
+ strcpy(gdesc->d.h_boundary.name, str_cget(&desc->d.h_boundary->name));
+ gdesc->d.h_boundary.reference_temperature
+ = desc->d.h_boundary->ref_temperature;
+ gdesc->d.h_boundary.emissivity = desc->d.h_boundary->emissivity;
+ gdesc->d.h_boundary.specular_fraction
+ = desc->d.h_boundary->specular_fraction;
+ gdesc->d.h_boundary.convection_coefficient = desc->d.h_boundary->hc;
+ gdesc->d.h_boundary.imposed_temperature
+ = desc->d.h_boundary->imposed_temperature;
+ break;
+ case DESC_BOUND_T_FOR_SOLID:
+ gdesc->type = GREEN_BOUND_T;
+ strcpy(gdesc->d.t_boundary.name, str_cget(&desc->d.t_boundary->name));
+ gdesc->d.t_boundary.imposed_temperature
+ = desc->d.t_boundary->imposed_temperature;
+ break;
+ case DESC_BOUND_F_FOR_SOLID:
+ gdesc->type = GREEN_BOUND_F;
+ strcpy(gdesc->d.f_boundary.name, str_cget(&desc->d.f_boundary->name));
+ gdesc->d.f_boundary.imposed_flux
+ = desc->d.f_boundary->imposed_flux;
+ break;
+ case DESC_SOLID_FLUID_CONNECT:
+ gdesc->type = GREEN_SOLID_FLUID_CONNECT;
+ strcpy(gdesc->d.sf_connect.name, str_cget(&desc->d.sf_connect->name));
+ gdesc->d.sf_connect.reference_temperature
+ = desc->d.sf_connect->ref_temperature;
+ gdesc->d.sf_connect.emissivity = desc->d.sf_connect->emissivity;
+ gdesc->d.sf_connect.specular_fraction
+ = desc->d.sf_connect->specular_fraction;
+ gdesc->d.sf_connect.convection_coefficient = desc->d.sf_connect->hc;
+ break;
+ case DESC_SOLID_SOLID_CONNECT:
+ gdesc->type = GREEN_SOLID_SOLID_CONNECT;
+ strcpy(gdesc->d.ss_connect.name, str_cget(&desc->d.ss_connect->name));
+ gdesc->d.ss_connect.thermal_contact_resistance = desc->d.ss_connect->tcr;
+ break;
+ default: return RES_BAD_ARG;
+ }
+ return RES_OK;
+}
+
/*******************************************************************************
* Local Functions
******************************************************************************/
@@ -91,6 +169,7 @@ merge_flux_terms
data = sdis_interface_get_data(interf);
d__ = sdis_data_get(data);
desc_id = d__->desc_id;
+ CHK(desc_id < darray_descriptions_size_get(w_ctx->desc));
descs = darray_descriptions_cdata_get(w_ctx->desc);
switch (descs[desc_id].type) {
@@ -123,9 +202,11 @@ merge_power_terms
struct sdis_data* data = NULL;
enum sdis_medium_type type;
struct w_ctx* w_ctx = ctx;
+ size_t sz;
ASSERT(mdm && w_ctx);
+ sz = darray_descriptions_size_get(w_ctx->desc);
data = sdis_medium_get_data(mdm);
type = sdis_medium_get_type(mdm);
@@ -135,9 +216,10 @@ merge_power_terms
FATAL("Unexpected power term in fluid");
}
case SDIS_SOLID: {
- struct solid* d__ = sdis_data_get(data);
+ struct solid** psolid = sdis_data_get(data);
double* w;
- unsigned id = d__->desc_id;
+ unsigned id = (*psolid)->desc_id;
+ CHK(id < sz);
w = htable_weigth_find(&w_ctx->pw, &id);
if(w) *w += power_term;
else ERR(htable_weigth_set(&w_ctx->pw, &id, &power_term));
@@ -165,8 +247,8 @@ dump_path
FILE* stream = NULL;
char* name = NULL;
enum sdis_heat_path_flag status = SDIS_HEAT_PATH_NONE;
- size_t vcount_, name_sz;
- unsigned long i, vcount;
+ size_t vcount_, scount_, offset, name_sz, istrip;
+ unsigned long scount, vcount;
ASSERT(path && dump_ctx
&& dump_ctx->stardis
@@ -189,67 +271,121 @@ dump_path
res = RES_IO_ERR;
goto error;
}
+
+ /* Get counts */
+ ERR(sdis_heat_path_get_line_strips_count(path, &scount_));
+ if(scount > ULONG_MAX) goto abort;
+ scount = (unsigned long)scount_;
+ vcount_ = 0;
+ FOR_EACH(istrip, 0, scount_) {
+ size_t n;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &n));
+ vcount_+= n;
+ }
+ if(vcount > ULONG_MAX) goto abort;
+ vcount = (unsigned long)vcount_;
/* Header */
fprintf(stream, "# vtk DataFile Version 2.0\n");
fprintf(stream, "Heat path\n");
fprintf(stream, "ASCII\n");
fprintf(stream, "DATASET POLYDATA\n");
/* Write path positions */
- sdis_heat_path_get_vertices_count(path, &vcount_);
- ASSERT(vcount_ < ULONG_MAX);
- vcount = (unsigned long)vcount_;
fprintf(stream, "POINTS %lu double\n", vcount);
- FOR_EACH(i, 0, vcount) {
- struct sdis_heat_vertex vtx;
- ERR(sdis_heat_path_get_vertex(path, i, &vtx));
- fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P));
- }
- /* Write the segment of the path */
- fprintf(stream, "LINES %d %lu\n", 1, 1 + vcount);
- fprintf(stream, "%lu", vcount);
- FOR_EACH(i, 0, vcount) fprintf(stream, " %lu", i);
- fprintf(stream, "\n");
-
- /* Write path type */
- fprintf(stream, "CELL_DATA %d\n", 1);
- fprintf(stream, "SCALARS Path_Type unsigned_char 1\n");
- fprintf(stream, "LOOKUP_TABLE default\n");
- switch (status) {
- case SDIS_HEAT_PATH_SUCCESS: fprintf(stream, "0\n"); break;
- case SDIS_HEAT_PATH_FAILURE: fprintf(stream, "1\n"); break;
- default: FATAL("Unreachable code.\n"); break;
+ FOR_EACH(istrip, 0, scount_) {
+ size_t ivert, nverts;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P));
+ }
+ }
+ /* Write the strips of the path */
+ fprintf(stream, "LINES %lu %lu\n", scount, scount + vcount);
+ offset = 0;
+ FOR_EACH(istrip, 0, scount) {
+ size_t ivert, nverts;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ if(nverts > ULONG_MAX) goto abort;
+ fprintf(stream, "%lu", (unsigned long)nverts);
+ FOR_EACH(ivert, 0, nverts) {
+ if(ivert + offset > ULONG_MAX) goto abort;
+ fprintf(stream, " %lu", (unsigned long)(ivert + offset));
+ }
+ fprintf(stream, "\n");
+ offset += nverts;
}
+ /* Write path status on strips */
+ fprintf(stream, "CELL_DATA %lu\n", scount);
+ fprintf(stream, "SCALARS Path_Failure unsigned_char 1\n");
+ fprintf(stream, "LOOKUP_TABLE default\n");
+ FOR_EACH(istrip, 0, scount) {
+ switch (status) {
+ case SDIS_HEAT_PATH_SUCCESS: fprintf(stream, "0\n"); break;
+ case SDIS_HEAT_PATH_FAILURE: fprintf(stream, "1\n"); break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ }
fprintf(stream, "POINT_DATA %lu\n", vcount);
/* Write the type of the random walk vertices */
fprintf(stream, "SCALARS Vertex_Type unsigned_char 1\n");
fprintf(stream, "LOOKUP_TABLE default\n");
- FOR_EACH(i, 0, vcount) {
- struct sdis_heat_vertex vtx;
- ERR(sdis_heat_path_get_vertex(path, i, &vtx));
- ASSERT((size_t)vtx.type <= UCHAR_MAX);
- fprintf(stream, "%d\n", vtx.type);
+ FOR_EACH(istrip, 0, scount_) {
+ size_t ivert, nverts;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ if((size_t)vtx.type > UCHAR_MAX) goto abort;
+ switch(vtx.type) {
+ case SDIS_HEAT_VERTEX_CONDUCTION: fprintf(stream, "%d\n", 0); break;
+ case SDIS_HEAT_VERTEX_CONVECTION: fprintf(stream, "%d\n", 1); break;
+ case SDIS_HEAT_VERTEX_RADIATIVE: fprintf(stream, "%d\n", 2); break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ }
}
/* Write the weights of the random walk vertices */
fprintf(stream, "SCALARS Weight double 1\n");
fprintf(stream, "LOOKUP_TABLE default\n");
- FOR_EACH(i, 0, vcount) {
- struct sdis_heat_vertex vtx;
- ERR(sdis_heat_path_get_vertex(path, i, &vtx));
- fprintf(stream, "%g\n", vtx.weight);
+ FOR_EACH(istrip, 0, scount_) {
+ size_t ivert, nverts;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ fprintf(stream, "%g\n", vtx.weight);
+ }
+ }
+ /* Write the branch_id of the random walk vertices */
+ fprintf(stream, "SCALARS Branch_id int 1\n");
+ fprintf(stream, "LOOKUP_TABLE default\n");
+ FOR_EACH(istrip, 0, scount_) {
+ size_t ivert, nverts;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ fprintf(stream, "%d\n", vtx.branch_id);
+ }
}
- /* If computation time is not INF for every vertex,
+ /* If computation time is not INF,
* write the time of the random walk vertices */
- FOR_EACH(i, 0, vcount) {
- struct sdis_heat_vertex vtx;
- ERR(sdis_heat_path_get_vertex(path, i, &vtx));
- if(i == 0) {
- if(IS_INF(vtx.time)) break;
- fprintf(stream, "SCALARS Time double 1\n");
- fprintf(stream, "LOOKUP_TABLE default\n");
+ FOR_EACH(istrip, 0, scount_) {
+ size_t ivert, nverts;
+ ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct sdis_heat_vertex vtx;
+ ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx));
+ if(istrip == 0 && ivert == 0) {
+ if(IS_INF(vtx.time)) break;
+ fprintf(stream, "SCALARS Time double 1\n");
+ fprintf(stream, "LOOKUP_TABLE default\n");
+ }
+ if(IS_INF(vtx.time)) goto abort;
+ fprintf(stream, "%g\n", vtx.time);
}
- ASSERT(!IS_INF(vtx.time));
- fprintf(stream, "%g\n", vtx.time);
}
end:
@@ -258,6 +394,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -273,7 +412,7 @@ dump_vtk_image
ASSERT(buf && stream);
ERR(sdis_estimator_buffer_get_definition(buf, def));
- ASSERT(def[0] != 0 && def[1] != 0 && def[0] * def[1] <= ULONG_MAX);
+ if(def[0] == 0 || def[1] == 0 || def[0] * def[1] > ULONG_MAX) goto abort;
definition[0] = (unsigned long)def[0];
definition[1] = (unsigned long)def[1];
@@ -344,7 +483,7 @@ dump_vtk_image
size_t nfails;
ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator));
ERR(sdis_estimator_get_failure_count(estimator, &nfails));
- ASSERT(nfails <= ULONG_MAX);
+ if(nfails > ULONG_MAX) goto abort;
fprintf(stream, "%lu\n", (unsigned long)nfails);
}
}
@@ -354,6 +493,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -368,7 +510,7 @@ dump_ht_image
ASSERT(buf && stream);
ERR(sdis_estimator_buffer_get_definition(buf, def));
- ASSERT(def[0] <= ULONG_MAX && def[1] <= ULONG_MAX);
+ if(def[0] > ULONG_MAX || def[1] > ULONG_MAX) goto abort;
definition[0] = (unsigned long)def[0];
definition[1] = (unsigned long)def[1];
@@ -390,6 +532,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
#define FW(Ptr, Count) \
@@ -398,12 +543,6 @@ error:
goto error; \
}
-struct path_header {
- unsigned id;
- unsigned pcount, fcount;
- char at_initial;
-};
-
static FINLINE double
medium_get_t0
(struct sdis_medium* medium)
@@ -433,18 +572,20 @@ dump_sample_end
enum sdis_green_path_end_type end_type;
FILE* stream;
double elapsed;
+ size_t sz;
+ unsigned trad_id;
CHK(path && ctx);
stream = e_ctx->stream;
ERR(sdis_green_path_get_elapsed_time(path, &elapsed));
ERR(sdis_green_path_get_end_type(path, &end_type));
+ sz = darray_descriptions_size_get(e_ctx->desc);
+ if(sz > UINT_MAX) goto abort;
+ trad_id = (unsigned)sz;
if(end_type == SDIS_GREEN_PATH_END_RADIATIVE) {
- size_t ambient_id = darray_descriptions_size_get(e_ctx->desc);
- ASSERT(ambient_id <= UINT_MAX);
/* End, End ID, X, Y, Z, Elapsed time */
- fprintf(stream, "AMBIENT, %u, 0, 0, 0, %g\n",
- (unsigned)ambient_id, elapsed);
+ fprintf(stream, "TRAD, %u, 0, 0, 0, %g\n", trad_id, elapsed);
} else {
struct sdis_point pt = SDIS_POINT_NULL;
struct sdis_data* data = NULL;
@@ -471,19 +612,17 @@ dump_sample_end
data = sdis_medium_get_data(pt.data.mdmvert.medium);
pos = pt.data.mdmvert.vertex.P;
if(pt.data.mdmvert.vertex.P[0] == INF) {
- /* Radiative output (ambient temperature) */
- size_t sz = darray_descriptions_size_get(e_ctx->desc);
- ASSERT(sz <= UINT_MAX);
- id = (unsigned)sz; /* Ambient ID */
+ /* Radiative output (Trad) */
+ id = trad_id;
}
else if(type == SDIS_FLUID) {
- struct fluid* d__ = sdis_data_get(data);
- id = d__->desc_id;
+ struct fluid** pfluid = sdis_data_get(data);
+ id = (*pfluid)->desc_id;
} else {
- struct solid* d__ = sdis_data_get(data);
+ struct solid** psolid = sdis_data_get(data);
ASSERT(type == SDIS_SOLID);
- ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */
- id = d__->desc_id;
+ ASSERT(!(*psolid)->is_outside); /* FIXME: what if in external solid? */
+ id = (*psolid)->desc_id;
}
break;
default: FATAL("Unreachable code.\n"); break;
@@ -497,6 +636,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
static res_T
@@ -506,23 +648,24 @@ dump_sample
{
res_T res = RES_OK;
struct htable_weigth_iterator it, end;
- struct path_header header;
+ struct green_sample_header header;
struct w_ctx* w_ctx = ctx;
enum sdis_green_path_end_type end_type;
FILE* stream;
unsigned* ids = NULL;
double* weights = NULL;
size_t sz, i;
-
+ unsigned trad_id;
CHK(path && ctx);
stream = w_ctx->stream;
ERR(sdis_green_path_get_end_type(path, &end_type));
+ sz = darray_descriptions_size_get(w_ctx->desc);
+ if(sz > UINT_MAX) goto abort;
+ trad_id = (unsigned)sz;
if(end_type == SDIS_GREEN_PATH_END_RADIATIVE) {
- size_t ambient_id = darray_descriptions_size_get(w_ctx->desc);
- ASSERT(ambient_id <= UINT_MAX);
header.at_initial = 0;
- header.id = (unsigned)ambient_id;
+ header.sample_end_description_id = trad_id;
} else {
struct sdis_point pt = SDIS_POINT_NULL;
struct sdis_data* data = NULL;
@@ -547,7 +690,7 @@ dump_sample
d__ = sdis_data_get(data);
desc_id = d__->desc_id;
CHK(DESC_IS_T(descs[desc_id].type) || DESC_IS_H(descs[desc_id].type));
- header.id = desc_id;
+ header.sample_end_description_id = desc_id;
header.at_initial = 0;
break;
}
@@ -557,19 +700,17 @@ dump_sample
t0 = medium_get_t0(pt.data.mdmvert.medium);
header.at_initial = (pt.data.mdmvert.vertex.time <= t0);
if(pt.data.mdmvert.vertex.P[0] == INF) {
- /* Radiative output (ambient temperature) */
- sz = darray_descriptions_size_get(w_ctx->desc);
- ASSERT(sz <= UINT_MAX);
- header.id = (unsigned)sz; /* Ambient ID */
+ /* Radiative output (Trad) */
+ header.sample_end_description_id = trad_id;
}
else if(type == SDIS_FLUID) {
- struct fluid* d__ = sdis_data_get(data);
- header.id = d__->desc_id;
+ struct fluid** pfluid = sdis_data_get(data);
+ header.sample_end_description_id = (*pfluid)->desc_id;
} else {
- struct solid* d__ = sdis_data_get(data);
+ struct solid** psolid = sdis_data_get(data);
ASSERT(type == SDIS_SOLID);
- ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */
- header.id = d__->desc_id;
+ ASSERT(!(*psolid)->is_outside); /* FIXME: what if in external solid? */
+ header.sample_end_description_id = (*psolid)->desc_id;
}
break;
default: FATAL("Unreachable code.\n"); break;
@@ -582,17 +723,17 @@ dump_sample
ERR(sdis_green_path_for_each_power_term(path, merge_power_terms, w_ctx));
ERR(sdis_green_path_for_each_flux_term(path, merge_flux_terms, w_ctx));
sz = htable_weigth_size_get(&w_ctx->pw);
- ASSERT(sz <= UINT_MAX);
- header.pcount = (unsigned)sz;
+ if(sz > UINT_MAX) goto abort;
+ header.pw_count = (unsigned)sz;
sz = htable_weigth_size_get(&w_ctx->flux);
- ASSERT(sz <= UINT_MAX);
- header.fcount = (unsigned)sz;
+ if(sz > UINT_MAX) goto abort;
+ header.fx_count = (unsigned)sz;
/* Write path's header */
FW(&header, 1);
/* Allocate buffers */
- sz = header.pcount + header.fcount;
+ sz = header.pw_count + header.fx_count;
ids = MEM_CALLOC(w_ctx->alloc, sz, sizeof(*ids));
weights = MEM_CALLOC(w_ctx->alloc, sz, sizeof(*weights));
if(!ids || !weights) {
@@ -607,24 +748,26 @@ dump_sample
while(!htable_weigth_iterator_eq(&it, &end)) {
double* w = htable_weigth_iterator_data_get(&it);
unsigned* k = htable_weigth_iterator_key_get(&it);
+ CHK(*k <= trad_id);
ids[i] = *k;
weights[i] = *w;
htable_weigth_iterator_next(&it);
i++;
}
- CHK(i == header.pcount);
+ CHK(i == header.pw_count);
htable_weigth_begin(&w_ctx->flux, &it);
htable_weigth_end(&w_ctx->flux, &end);
while (!htable_weigth_iterator_eq(&it, &end)) {
double* w = htable_weigth_iterator_data_get(&it);
unsigned* k = htable_weigth_iterator_key_get(&it);
+ CHK(*k <= trad_id);
ids[i] = *k;
weights[i] = *w;
htable_weigth_iterator_next(&it);
i++;
}
- CHK(i == header.pcount + header.fcount);
+ CHK(i == header.pw_count + header.fx_count);
FW(ids, sz);
FW(weights, sz);
@@ -635,6 +778,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -644,95 +790,52 @@ dump_green_bin
FILE* stream)
{
res_T res = RES_OK;
- size_t ok_count, failed_count;
- size_t sz;
+ size_t sz, i;
struct w_ctx w_ctx;
int table_initialized = 0;
- unsigned i, szd;
- const struct description* descs;
- unsigned name_pool_sz = 0;
- char* name_pool = NULL;
- char* pool_ptr;
- const char green_string[] = "GREEN_BIN_FILE:";
- const unsigned file_fmt_version = 3;
/* The following type must be identical to its stardis-green counterpart! */
- struct bfile_green_counts {
- unsigned desc_count, smed_count, fmed_count, tbound_count, hbound_count,
- fbound_count, sfconnect_count, ssconnect_count, name_pool_sz;
- size_t ok_count, failed_count;
- } file_counts;
+ struct green_file_header header;
ASSERT(green && stardis && stream);
- ERR(sdis_green_function_get_paths_count(green, &ok_count));
- ERR(sdis_green_function_get_invalid_paths_count(green, &failed_count));
+ /* Init header */
+ strcpy(header.green_string, BIN_FILE_IDENT_STRING);
+ header.file_format_version = GREEN_FILE_FORMAT_VERSION;
+ header.solid_count = stardis->counts.smed_count;
+ header.fluid_count = stardis->counts.fmed_count;
+ header.tbound_count = stardis->counts.tbound_count;
+ header.hbound_count = stardis->counts.hbound_count;
+ header.fbound_count = stardis->counts.fbound_count;
+ header.sfconnect_count = stardis->counts.sfconnect_count;
+ header.ssconnect_count = stardis->counts.ssconnect_count;
+ ERR(sdis_green_function_get_paths_count(green, &header.ok_count));
+ ERR(sdis_green_function_get_invalid_paths_count(green, &header.failed_count));
sz = darray_descriptions_size_get(&stardis->descriptions);
- ASSERT(sz <= UINT_MAX);
- szd = (unsigned)sz;
- ASSERT(szd ==
+ if(sz > UINT_MAX) goto abort;
+ ASSERT(sz ==
(stardis->counts.smed_count + stardis->counts.fmed_count
+ stardis->counts.tbound_count + stardis->counts.hbound_count
+ stardis->counts.fbound_count + stardis->counts.sfconnect_count
+ stardis->counts.ssconnect_count));
- descs = darray_descriptions_cdata_get(&stardis->descriptions);
+ header.description_count = (unsigned)sz;
+ header.ambient_radiative_temperature = stardis->trad;
+ header.ambient_radiative_temperature_reference = stardis->trad_ref;
+ d2_set(header.time_range, stardis->time_range);
- /* Save names that do not fit inplace */
- FOR_EACH(i, 0, szd) {
- const struct description* desc = descs + i;
- const struct str* name = get_description_name(desc);
- const size_t len = str_len(name);
- ASSERT(name_pool_sz + len + 1 <= UINT_MAX);
- name_pool_sz += (unsigned)(len + 1);
- }
- pool_ptr = name_pool = MEM_ALLOC(stardis->allocator, name_pool_sz);
- if(!name_pool) {
- res = RES_MEM_ERR;
- goto error;
- }
- FOR_EACH(i, 0, szd) {
- const struct description* desc = descs + i;
- const struct str* name = get_description_name(desc);
- const size_t len = str_len(name);
- strcpy(pool_ptr, name->cstr);
- pool_ptr += len + 1;
- }
- ASSERT(pool_ptr == name_pool + name_pool_sz);
- /* Write Green string and file format version */
- FW(green_string, sizeof(green_string));
- FW(&file_fmt_version, 1);
-
- /* Write counts */
- file_counts.desc_count = szd;
- file_counts.smed_count = stardis->counts.smed_count;
- file_counts.fmed_count = stardis->counts.fmed_count;
- file_counts.tbound_count = stardis->counts.tbound_count;
- file_counts.hbound_count = stardis->counts.hbound_count;
- file_counts.fbound_count = stardis->counts.fbound_count;
- file_counts.sfconnect_count = stardis->counts.sfconnect_count;
- file_counts.ssconnect_count = stardis->counts.ssconnect_count;
- file_counts.name_pool_sz = name_pool_sz;
- file_counts.ok_count = ok_count;
- file_counts.failed_count = failed_count;
- FW(&file_counts, 1);
+ /* Write header */
+ FW(&header, 1);
/* Write descriptions*/
- FW(descs, szd);
-
- /* Write names */
- if(name_pool_sz)
- FW(name_pool, name_pool_sz);
-
- /* Write radiative temperatures */
- FW(&stardis->ambient_temp, 1);
- FW(&stardis->ref_temp, 1);
-
- /* Write time range */
- FW(&stardis->time_range, 2);
+ for(i = 0; i < sz; i++) {
+ struct green_description desc;
+ ERR(copy_desc_to_green_desc(&desc, &stardis->descriptions, i));
+ FW(&desc, 1);
+ }
w_ctx.alloc = stardis->allocator;
w_ctx.desc = &stardis->descriptions;
- htable_weigth_init(NULL, &w_ctx.pw);
- htable_weigth_init(NULL, &w_ctx.flux);
+ htable_weigth_init(stardis->allocator, &w_ctx.pw);
+ htable_weigth_init(stardis->allocator, &w_ctx.flux);
w_ctx.stream = stream;
table_initialized = 1;
@@ -740,12 +843,14 @@ dump_green_bin
ERR(sdis_green_function_for_each_path(green, dump_sample, &w_ctx));
end:
- MEM_RM(stardis->allocator, name_pool);
if(table_initialized) htable_weigth_release(&w_ctx.pw);
if(table_initialized) htable_weigth_release(&w_ctx.flux);
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -782,7 +887,7 @@ print_sample
enum sdis_medium_type type;
struct htable_weigth_iterator it, end;
unsigned desc_id;
- size_t pcount, fcount;
+ size_t pw_count, fx_count;
struct w_ctx* w_ctx = ctx;
const struct description* descs;
CHK(path && ctx);
@@ -792,7 +897,7 @@ print_sample
/* For each path, prints:
* # end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n
* with:
- * - end = end_type end_id; end_type = T | H | A | F | S
+ * - end = end_type end_id; end_type = T | H | R | F | S
* - power_term_i = power_type_i power_id_i factor_i
* - flux_term_i = flux_id_i factor_i
*/
@@ -823,42 +928,42 @@ print_sample
type = sdis_medium_get_type(pt.data.mdmvert.medium);
data = sdis_medium_get_data(pt.data.mdmvert.medium);
if(pt.data.mdmvert.vertex.P[0] == INF) {
- /* Radiative output (ambient temperature)*/
+ /* Radiative output (Trad)*/
size_t sz = darray_descriptions_size_get(w_ctx->desc);
- ASSERT(sz <= UINT_MAX);
- fprintf(w_ctx->stream, "A\t%u", (unsigned)sz);
+ if(sz > UINT_MAX) goto abort;
+ fprintf(w_ctx->stream, "R\t%u", (unsigned)sz);
}
else if(type == SDIS_FLUID) {
- struct fluid* d__ = sdis_data_get(data);
- desc_id = d__->desc_id;
- if(d__->is_outside)
+ struct fluid** pfluid = sdis_data_get(data);
+ desc_id = (*pfluid)->desc_id;
+ if((*pfluid)->is_outside)
/* If outside the model and in a fluid with known temperature,
* its a fluid attached to a H boundary */
fprintf(w_ctx->stream, "H\t%u", desc_id);
/* In a standard fluid with known temperature */
else fprintf(w_ctx->stream, "F\t%u", desc_id);
} else {
- struct solid* d__ = sdis_data_get(data);
+ struct solid** psolid = sdis_data_get(data);
ASSERT(type == SDIS_SOLID);
- ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */
- desc_id = d__->desc_id;
+ ASSERT(!(*psolid)->is_outside); /* FIXME: what if in external solid? */
+ desc_id = (*psolid)->desc_id;
fprintf(w_ctx->stream, "S\t%u", desc_id);
}
break;
default: FATAL("Unreachable code.\n"); break;
}
- ERR(sdis_green_function_get_power_terms_count(path, &pcount));
+ ERR(sdis_green_function_get_power_terms_count(path, &pw_count));
htable_weigth_clear(&w_ctx->pw);
htable_weigth_clear(&w_ctx->flux);
ERR(sdis_green_path_for_each_power_term(path, merge_power_terms, w_ctx));
ERR(sdis_green_path_for_each_flux_term(path, merge_flux_terms, w_ctx));
- fcount = htable_weigth_size_get(&w_ctx->flux);
+ fx_count = htable_weigth_size_get(&w_ctx->flux);
- ASSERT(pcount <= ULONG_MAX && fcount <= ULONG_MAX);
+ if(pw_count > ULONG_MAX || fx_count > ULONG_MAX) goto abort;
fprintf(w_ctx->stream, "\t%lu\t%lu",
- (unsigned long)pcount, (unsigned long)fcount);
+ (unsigned long)pw_count, (unsigned long)fx_count);
htable_weigth_begin(&w_ctx->pw, &it);
htable_weigth_end(&w_ctx->pw, &end);
@@ -883,6 +988,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -902,13 +1010,13 @@ dump_green_ascii
ASSERT(green && stardis && stream);
ERR(sdis_green_function_get_paths_count(green, &sz));
- ASSERT(sz <= UINT_MAX);
+ if(sz > UINT_MAX) goto abort;
ok_count = (unsigned)sz;
ERR(sdis_green_function_get_invalid_paths_count(green, &sz));
- ASSERT(sz <= UINT_MAX);
+ if(sz > UINT_MAX) goto abort;
failed_count = (unsigned)sz;
sz = darray_descriptions_size_get(&stardis->descriptions);
- ASSERT(sz <= UINT_MAX);
+ if(sz > UINT_MAX) goto abort;
szd = (unsigned)sz;
descs = darray_descriptions_cdata_get(&stardis->descriptions);
@@ -932,7 +1040,7 @@ dump_green_ascii
const struct description* desc = descs + i;
const struct solid* sl;
if(desc->type != DESC_MAT_SOLID) continue;
- sl = &desc->d.solid;
+ sl = desc->d.solid;
fprintf(stream, "%u\t%s\t%g\t%g\t%g\t%g",
i, str_cget(&sl->name), sl->lambda, sl->rho, sl->cp, sl->vpower);
if(sl->tinit >= 0) {
@@ -954,7 +1062,7 @@ dump_green_ascii
const struct description* desc = descs + i;
const struct fluid* fl;
if(desc->type != DESC_MAT_FLUID) continue;
- fl = &desc->d.fluid;
+ fl = desc->d.fluid;
if(fl->imposed_temperature >= 0) {
fprintf(stream, "%u\t%s\t%g\t%g",
i, str_cget(&fl->name), fl->rho, fl->cp);
@@ -982,23 +1090,23 @@ dump_green_ascii
FOR_EACH(i, 0, szd) {
const struct description* desc = descs + i;
const struct t_boundary* bd;
- bd = &desc->d.t_boundary;
+ bd = desc->d.t_boundary;
fprintf(stream, "%u\t%s\t%g\n",
i, str_cget(&bd->name), bd->imposed_temperature);
}
}
if(stardis->counts.hbound_count) {
fprintf(stream, "# H Boundaries\n");
- fprintf(stream, "# ID Name emissivity specular_fraction hc T_env\n");
+ fprintf(stream, "# ID Name ref_temperature emissivity specular_fraction hc T_env\n");
FOR_EACH(i, 0, szd) {
const struct description* desc = descs + i;
const struct h_boundary* bd;
if(desc->type != DESC_BOUND_H_FOR_SOLID
&& desc->type != DESC_BOUND_H_FOR_FLUID) continue;
- bd = &desc->d.h_boundary;
- fprintf(stream, "%u\t%s\t%g\t%g\t%g\t%g\n",
- i, str_cget(&bd->name), bd->emissivity, bd->specular_fraction,
- bd->hc, bd->imposed_temperature);
+ bd = desc->d.h_boundary;
+ fprintf(stream, "%u\t%s\t%g\t%g\t%g\t%g\t%g\n",
+ i, str_cget(&bd->name), bd->ref_temperature, bd->emissivity,
+ bd->specular_fraction, bd->hc, bd->imposed_temperature);
}
}
if(stardis->counts.fbound_count) {
@@ -1008,29 +1116,29 @@ dump_green_ascii
const struct description* desc = descs + i;
const struct f_boundary* bd;
if(desc->type != DESC_BOUND_F_FOR_SOLID) continue;
- bd = &desc->d.f_boundary;
+ bd = desc->d.f_boundary;
fprintf(stream, "%u\t%s\t%g\n",
i, str_cget(&bd->name), bd->imposed_flux);
}
}
- /* Radiative Temperatures */
+ /* Radiative Temperature */
fprintf(stream, "# Radiative Temperatures\n");
- fprintf(stream, "# ID Amb_Temp Lin_Temp\n");
+ fprintf(stream, "# ID Trad Trad_Ref\n");
fprintf(stream, "%u\t%g\t%g\n",
- szd, stardis->ambient_temp, stardis->ref_temp);
+ szd, stardis->trad, stardis->trad_ref);
fprintf(stream, "# Samples\n");
fprintf(stream,
"# end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n\n");
- fprintf(stream, "# end = end_type end_id; end_type = T | H | A | F | S\n");
+ fprintf(stream, "# end = end_type end_id; end_type = T | H | R | F | S\n");
fprintf(stream, "# power_term_i = power_id_i factor_i\n");
fprintf(stream, "# flux_term_i = flux_id_i factor_i\n");
w_ctx.alloc = stardis->allocator;
w_ctx.desc = &stardis->descriptions;
- htable_weigth_init(NULL, &w_ctx.pw);
- htable_weigth_init(NULL, &w_ctx.flux);
+ htable_weigth_init(stardis->allocator, &w_ctx.pw);
+ htable_weigth_init(stardis->allocator, &w_ctx.flux);
w_ctx.stream = stream;
table_initialized = 1;
@@ -1044,6 +1152,9 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -1347,6 +1458,9 @@ print_computation_time
ASSERT(stardis && start && compute_start && compute_end);
+ /* Only master prints or reads estimators */
+ ASSERT(!stardis->mpi_initialized || stardis->mpi_rank == 0);
+
time_sub(&tmp, compute_start, start);
time_dump(&tmp, flag, NULL, buf, sizeof(buf));
logger_print(stardis->logger, LOG_OUTPUT,
@@ -1387,10 +1501,13 @@ print_single_MC_result
ASSERT(estimator && stardis && stream);
+ /* Only master prints or reads estimators */
+ ASSERT(!stardis->mpi_initialized || stardis->mpi_rank == 0);
+
/* Fetch the estimation data */
ERR(sdis_estimator_get_temperature(estimator, &result));
ERR(sdis_estimator_get_failure_count(estimator, &nfailures_));
- ASSERT(nfailures_ <= ULONG_MAX && stardis->samples <= ULONG_MAX);
+ if(nfailures_ > ULONG_MAX || stardis->samples > ULONG_MAX) goto abort;
nfailures = (unsigned long)nfailures_;
nsamples = (unsigned long)stardis->samples;
if(nfailures == nsamples) {
@@ -1570,14 +1687,18 @@ end:
return res;
error:
goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
-void
+res_T
dump_map
(const struct stardis* stardis,
const struct darray_estimators* estimators,
FILE* stream)
{
+ res_T res = RES_OK;
unsigned i, vcount, tcount, last_v = 0;
const size_t* idx;
size_t sz;
@@ -1586,10 +1707,13 @@ dump_map
ASSERT(stardis && estimators && stream);
+ /* Only master prints or reads estimators */
+ ASSERT(!stardis->mpi_initialized || stardis->mpi_rank == 0);
+
est = darray_estimators_cdata_get(estimators);
idx = darray_size_t_cdata_get(&stardis->compute_surface.primitives);
sz = darray_size_t_size_get(&stardis->compute_surface.primitives);
- ASSERT(sz <= UINT_MAX);
+ if(sz > UINT_MAX) goto abort;
szp = (unsigned)sz;
SG3D(geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount));
SG3D(geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount));
@@ -1598,7 +1722,7 @@ dump_map
for(i = 0; i < szp; ++i) {
unsigned t;
unsigned indices[3];
- ASSERT(idx[i] <= UINT_MAX);
+ if(idx[i] > UINT_MAX) goto abort;
t = (unsigned)idx[i];
SG3D(geometry_get_unique_triangle_vertices(stardis->geometry.sg3d, t,
indices));
@@ -1621,7 +1745,7 @@ dump_map
for(i = 0; i < szp; ++i) {
unsigned t;
unsigned indices[3];
- ASSERT(idx[i] <= UINT_MAX);
+ if(idx[i] > UINT_MAX) goto abort;
t = (unsigned)idx[i];
SG3D(geometry_get_unique_triangle_vertices(stardis->geometry.sg3d, t,
indices));
@@ -1647,7 +1771,7 @@ dump_map
for(i = 0; i < szp; ++i) {
size_t nfails;
SDIS(estimator_get_failure_count(est[i], &nfails));
- ASSERT(nfails <= UINT_MAX);
+ if(nfails > UINT_MAX) goto abort;
fprintf(stream, "%u\n", (unsigned)nfails);
}
fprintf(stream, "SCALARS computation_time_estimate float 1\n");
@@ -1664,6 +1788,13 @@ dump_map
SDIS(estimator_get_realisation_time(est[i], &time));
fprintf(stream, "%f\n", time.SE);
}
+end:
+ return res;
+error:
+ goto end;
+abort:
+ res = RES_BAD_ARG;
+ goto error;
}
res_T
@@ -1676,6 +1807,10 @@ dump_compute_region_at_the_end_of_vtk
unsigned tsz, i;
size_t j, psz;
ASSERT(stardis && stream);
+
+ /* Only master prints or reads estimators */
+ ASSERT(!stardis->mpi_initialized || stardis->mpi_rank == 0);
+
psz = darray_size_t_size_get(&stardis->compute_surface.primitives);
ASSERT(psz == darray_sides_size_get(&stardis->compute_surface.sides));
@@ -1761,6 +1896,9 @@ dump_model_as_c_chunks
ASSERT(stardis && stream);
+ /* Only master prints or reads estimators */
+ ASSERT(!stardis->mpi_initialized || stardis->mpi_rank == 0);
+
prefix = str_cget(&stardis->chunks_prefix);
ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount));
ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount));
diff --git a/src/stardis-output.h b/src/stardis-output.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -97,7 +97,7 @@ print_single_MC_result
struct stardis* stardis,
FILE* stream);
-extern void
+extern res_T
dump_map
(const struct stardis* stardis,
const struct darray_estimators* estimators,
diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,12 +17,11 @@
#include "stardis-parsing.h"
#include "stardis-app.h"
#include "stardis-default.h"
-#include "stardis-version.h"
+#include "stardis-green-types.h"
#include <rsys/cstr.h>
#include <rsys/double2.h>
#include <rsys/double3.h>
-#include <sdis_version.h>
#include <rsys/logger.h>
#include <getopt.h>
@@ -34,79 +33,14 @@
#include <strings.h> /* strcasecmp */
#else
#define strcasecmp(s1, s2) _stricmp((s1), (s2))
+#define strdup(tok) _strdup(tok)
+#define strtok_r(str, delim, save) strtok_s((str), (delim), (save))
#endif
/*******************************************************************************
* Local Functions
******************************************************************************/
-static char**
-split_line
- (char* a_str,
- const char a_delim)
-{
- char** result = 0;
- size_t chunks_count;
- char* tmp = a_str;
- char delim[2];
- char* tok_ctx = NULL;
-
- ASSERT(a_str);
-
- delim[0] = a_delim;
- delim[1] = 0;
-
- /* if a_str starts with initial useless delimiters remove them */
- while(*a_str == a_delim) a_str++;
-
- /* if a_str ends with final useless delimiters remove them */
- tmp = a_str + strlen(a_str) - 1;
- while(*tmp == a_delim && tmp >= a_str) { *tmp = '\0'; tmp--; }
-
- if(tmp >= a_str) chunks_count = 1;
- else return NULL;
-
- tmp = a_str;
- while(*tmp) {
- int delim_found = 0;
- while(*tmp == a_delim) { delim_found = 1; tmp++; }
- if(delim_found) chunks_count++;
- tmp++;
- }
-
- /* Add space for terminating null string so caller
- knows where the list of returned strings ends. */
- result = malloc(sizeof(char*) * (1 + chunks_count));
- if(result) {
- size_t idx = 0;
- char* token = strtok_r(a_str, delim, &tok_ctx);
-
- while(token) {
- ASSERT(idx <= chunks_count);
-#ifdef COMPILER_CL
- *(result + idx++) = _strdup(token);
-#else
- *(result + idx++) = strdup(token);
-#endif
- token = strtok_r(NULL, delim, &tok_ctx);
- }
- ASSERT(idx == chunks_count);
- *(result + idx) = 0;
- }
- return result;
-}
-
-void
-print_version
- (FILE* stream)
-{
- ASSERT(stream);
- fprintf(stream,
- "Stardis version %i.%i.%i built on stardis solver version %i.%i.%i\n",
- STARDIS_APP_VERSION_MAJOR, STARDIS_APP_VERSION_MINOR, STARDIS_APP_VERSION_PATCH,
- Stardis_VERSION_MAJOR, Stardis_VERSION_MINOR, Stardis_VERSION_PATCH);
-}
-
void
add_geom_ctx_indices
(const unsigned itri,
@@ -313,834 +247,6 @@ error:
* Public Functions
******************************************************************************/
-res_T
-init_args
- (struct logger* logger,
- struct mem_allocator* allocator,
- struct args** out_args)
-{
- res_T res = RES_OK;
- struct args* args = NULL;
- ASSERT(logger && allocator && out_args);
-
- args = calloc(sizeof(struct args), 1);
- if(!args) {
- res = RES_MEM_ERR;
- goto error;
- }
-
- args->logger = logger;
- args->allocator = allocator;
- darray_str_init(allocator, &args->model_files);
- /* Set default values */
- args->samples = STARDIS_DEFAULT_SAMPLES_COUNT;
- args->nthreads = SDIS_NTHREADS_DEFAULT;
- d2(args->pos_and_time+3,
- STARDIS_DEFAULT_COMPUTE_TIME, STARDIS_DEFAULT_COMPUTE_TIME);
- args->ambient_temp = STARDIS_DEFAULT_AMBIENT_TEMP;
- args->ref_temp = STARDIS_DEFAULT_REFERENCE_TEMP;
- args->verbose = STARDIS_DEFAULT_VERBOSE_LEVEL;
-
-end:
- *out_args = args;
- return res;
-error:
- if(args) release_args(args);
- args = NULL;
- goto end;
-}
-
-void
-release_args(struct args* args)
-{
- ASSERT(args);
- darray_str_release(&args->model_files);
- free(args);
-}
-
-char
-mode_option
- (const int m)
-{
- int found = 0;
- char res = '?';
- if(m & MODE_DUMP_C_CHUNKS) { found++; res = 'c'; }
- if(m & MODE_DUMP_VTK) { found++; res = 'd'; }
- if(m & MODE_DUMP_PATHS) { found++; res = 'D'; }
- if(m & MODE_EXTENDED_RESULTS) { found++; res = 'e'; }
- if(m & MODE_FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; }
- if(m & MODE_GREEN) { found++; res = 'g'; }
- if(m & MODE_BIN_GREEN) { found++; res = 'G'; }
- if(m & MODE_DUMP_HELP) { found++; res = 'h'; }
- if(m & MODE_MEDIUM_COMPUTE) { found++; res = 'm'; }
- if(m & MODE_PROBE_COMPUTE) { found++; res = 'p'; }
- if(m & MODE_PROBE_COMPUTE_ON_INTERFACE) { found++; res = 'P'; }
- if(m & MODE_IR_COMPUTE) { found++; res = 'R'; }
- if(m & MODE_BOUNDARY_COMPUTE) { found++; res = 's'; }
- if(m & MODE_MAP_COMPUTE) { found++; res = 'S'; }
- if(m & MODE_VERBOSITY) { found++; res = 'V'; }
- if(m & MODE_DUMP_VERSION) { found++; res = 'v'; }
- ASSERT(found == 1);
- return res;
-}
-
-void
-print_multiple_modes
- (char* buf,
- const size_t sz,
- const int modes,
- const int dont) /* Modes in dont are not printed */
-{
- int b = 0, fst = 1;
- int m = UNDEF_MODE;
- size_t left = sz;
- ASSERT(buf);
- do {
- m = BIT(b++);
- if(m & dont) continue;
- if(m & modes) {
- size_t n =
- (size_t)snprintf(buf, left, (fst ? "-%c" : ", -%c"), mode_option(m));
- if(n >= left) FATAL("Buffer is too small.");
- left -= n;
- buf += n;
- fst = 0;
- }
- } while(m < modes);
-}
-
-void
-short_help
- (FILE* stream,
- const char* prog)
-{
- const char* name;
- ASSERT(stream && prog);
-
-#ifdef COMPILER_GCC
- name = strrchr(prog, '/');
-#else
- name = strrchr(prog, '\\');
-#endif
-
- name = name ? name + 1 : prog;
- fprintf(stream,
- "Usage: %s [OPTIONS]\n"
- "\nSolve coupled thermal systems under the linear assumption.\n"
- "Refer to stardis(1) man page for more information.\n\n",
- name);
- print_version(stream);
-
- fprintf(stream, "\nMandatory options\n");
- fprintf(stream, "-------------------\n");
-
- fprintf(stream, "\n -M <FILE>\n");
- fprintf(stream, " Read a text file that contains (partial) description of the model.\n");
-
- fprintf(stream, "\nExclusive options\n");
- fprintf(stream, "-------------------\n");
-
- fprintf(stream, "\n -F STL_FILE[,TIME-RANGE]\n");
- fprintf(stream, " Compute the mean flux on a given 2D region at a given time.\n");
-
- fprintf(stream, "\n -m MEDIUM_NAME[,TIME-RANGE]\n");
- fprintf(stream, " Compute the mean temperature in a given medium at a given time.\n");
-
- fprintf(stream, "\n -p X,Y,Z[,TIME-RANGE]\n");
- fprintf(stream, " Compute the temperature at the given probe.\n");
-
- fprintf(stream, "\n -P X,Y,Z[,TIME-RANGE]\n");
- fprintf(stream, " Compute the temperature at the given probe on an interface.\n");
-
- fprintf(stream, "\n -R [RENDERING_OPTIONS]\n");
- fprintf(stream, " Compute an infra-red image of the model.\n");
-
- fprintf(stream, "\n -s STL_FILE[,TIME-RANGE]\n");
- fprintf(stream, " Compute the mean temperature on a given 2D region.\n");
-
- fprintf(stream, "\n -S STL_FILE[,TIME-RANGE]\n");
- fprintf(stream, " Compute the by-triangle mean temperature on a given 2D region.\n");
-
- fprintf(stream, "\nOther options\n");
- fprintf(stream, "-------------------\n");
-
- fprintf(stream, "\n -a AMBIENT_TEMP\n");
- fprintf(stream, " Set the ambient radiative temperature.\n");
-
- fprintf(stream, "\n -c NAMES_PREFIX\n");
- fprintf(stream, " Dump the geometry and property ids to stdout as C chunks.\n");
-
- fprintf(stream, "\n -d\n");
- fprintf(stream, " Dump the geometry to stdout in VTK format along with various properties.\n");
-
- fprintf(stream, "\n -D TYPE,FILE_NAMES_PREFIX\n");
- fprintf(stream, " Write thermal paths of the given TYPE in VTK format.\n");
-
- fprintf(stream, "\n -e\n");
- fprintf(stream, " Use extended format to output Monte-Carlo results.\n");
-
- fprintf(stream, "\n -g\n");
- fprintf(stream, " Change the computation to produce the green function.\n");
-
- fprintf(stream, "\n -G BIN_FILE_NAME[,CSV_FILE_NAME]\n");
- fprintf(stream, " Change the computation to produce the green function and possibly end of paths information.\n");
-
- fprintf(stream, "\n -h\n");
- fprintf(stream, " Print this help and exit.\n");
-
- fprintf(stream, "\n -n SAMPLE_COUNT\n");
- fprintf(stream, " Set the number of Monte-Carlo samples.\n");
-
- fprintf(stream, "\n -r REFERENCE_TEMP\n");
- fprintf(stream, " Set the temperature used for the linearization of the radiative transfer.\n");
-
- fprintf(stream, "\n -t NUM_OF_THREADS\n");
- fprintf(stream, " Hint on the number of threads.\n");
-
- fprintf(stream, "\n -v\n");
- fprintf(stream, " Print version information and exit.\n");
-
- fprintf(stream, "\n -V LEVEL\n");
- fprintf(stream, " Set the verbosity level.\n");
-
- fprintf(stream, "\n -x <FILE>\n");
- fprintf(stream, " Use a random generator's state read from a file.\n");
-
- fprintf(stream, "\n -X <FILE>\n");
- fprintf(stream, " Save the final random generator's state in a file.\n");
-
- fprintf(stream,
-"\nCopyright (C) 2018-2021 |Meso|Star> <contact@meso-star.com>.\n"
-"stardis is free software released under the GNU GPL license, version 3 or later.\n"
-"You are free to change or redistribute it under certain conditions\n"
-"<http://gnu.org/licenses/gpl.html>.\n");
-
-}
-
-#define FREE_AARRAY(ARRAY) \
-if(ARRAY) {\
- int i__ = 0; \
- for(i__=0; *((ARRAY)+i__);i__++){\
- free((ARRAY)[i__]);\
- }\
- free(ARRAY);\
- (ARRAY) = NULL;\
-}
-
-/* Workaround for a gcc warning when GET_OPTIONAL_TIME_RANGE used with Rank=0 */
-static FINLINE int is_less(size_t a, size_t b) { return a < b; }
-
-/* Get a time range from a coma-separated list of doubles
- * The first Rank values are mandatory, followed by an optional time range
- * that can be a single time */
-#define GET_OPTIONAL_TIME_RANGE(Src, Rank, Dst, Logger, OptionString, Option, FullSrc) \
- res = cstr_to_list_double((Src), ',', (Dst), &len, (Rank)+2); \
- if(res != RES_OK \
- || is_less(len, (Rank)) \
- || (len == (Rank)+1 && (Dst)[(Rank)] < 0) \
- || (len == (Rank)+2 && ((Dst)[0] < 0 || (Dst)[(Rank)] > (Dst)[(Rank)+1])) \
- || len > (Rank)+2) \
- { \
- if(res == RES_OK) res = RES_BAD_ARG; \
- logger_print((Logger), LOG_ERROR, \
- "Invalid argument for option "OptionString": %s\n", \
- (Option), (FullSrc)); \
- goto error; \
- } else { \
- if(len == (Rank)+1) (Dst)[(Rank)+1] = (Dst)[(Rank)];\
- }
-
- /* Get a string followed by an optional time range */
-#define GET_STR_AND_OPTIONAL_TIME_RANGE(Str, Time) \
- ptr = strchr(optarg, ','); /* First ',' */ \
- if(ptr) { /* Time range provided */ \
- GET_OPTIONAL_TIME_RANGE(ptr+1, 0, (Time), args->logger, "-%c", opt, optarg); \
- *ptr = '\0'; \
- } \
- (Str) = optarg;
-
-/* Get a position followed by an optional time range */
-#define GET_POS_AND_OPTIONAL_TIME_RANGE(Src, Dst, FullSrc) \
- GET_OPTIONAL_TIME_RANGE((Src), 3, (Dst), args->logger, "-%c", opt, (FullSrc));
-
-res_T
-parse_args
- (const int argc,
- char** argv,
- struct args* args,
- struct mem_allocator* allocator)
-{
- int opt = 0, n_used = 0;
- size_t len = 0;
- const char option_list[] = "a:c:dD:eF:gG:hm:M:n:p:P:r:R:s:S:t:vV:x:X:";
- char buf[128];
- struct str keep;
- char** line = NULL;
- res_T res = RES_OK;
-
- ASSERT(argv && args);
-
- str_init(allocator, &keep);
- opterr = 0; /* No default error messages */
- while((opt = getopt(argc, argv, option_list)) != -1) {
- switch (opt) {
-
- case '?': /* Unreconised option */
- {
- char* ptr = strchr(option_list, optopt);
- res = RES_BAD_ARG;
- if(ptr && ptr[1] == ':') {
- logger_print(args->logger, LOG_ERROR,
- "Missing argument for option -%c\n",
- optopt);
- } else {
- logger_print(args->logger, LOG_ERROR, "Invalid option -%c\n", optopt);
- }
- goto error;
- }
-
- case 'a':
- res = cstr_to_double(optarg, &args->ambient_temp);
- if(res != RES_OK
- || args->ambient_temp < 0)
- {
- if(res == RES_OK) res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Invalid argument for option -%c: %s\n",
- opt, optarg);
- goto error;
- }
- break;
-
- case 'c':
- if(args->mode & USE_STDOUT_MODES) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_C_CHUNKS);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used in conjunction with other dump options (%s).\n",
- (char)opt, buf);
- goto error;
- }
- args->chunks_prefix = optarg;
- args->mode |= MODE_DUMP_C_CHUNKS;
- break;
-
- case 'd':
- if(args->mode & USE_STDOUT_MODES) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_VTK);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used in conjunction with other dump options (%s).\n",
- (char)opt, buf);
- goto error;
- }
- args->mode |= MODE_DUMP_VTK;
- break;
-
- case 'D': {
- char* ptr = strrchr(optarg, ',');
- if(!ptr || ptr != strchr(optarg, ','))
- res = RES_BAD_ARG; /* Single ',' expected */
- else {
- args->paths_filename = ptr + 1;
- *ptr = '\0';
- }
- if(res == RES_OK) {
- if(0 == strcasecmp(optarg, "all")) {
- args->dump_paths = DUMP_ALL;
- }
- else if(0 == strcasecmp(optarg, "error")) {
- args->dump_paths = DUMP_ERROR;
- }
- else if(0 == strcasecmp(optarg, "success")) {
- args->dump_paths = DUMP_SUCCESS;
- }
- }
- if(res != RES_OK) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Invalid argument for option -%c: %s\n",
- opt, optarg);
- goto error;
- }
- args->mode |= MODE_DUMP_PATHS;
- break;
- }
-
- case 'e':
- args->mode |= MODE_EXTENDED_RESULTS;
- break;
-
- /*case 'F': see 's' */
-
- case 'g':
- if(args->mode & MODE_BIN_GREEN) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(MODE_BIN_GREEN));
- goto error;
- }
- args->mode |= MODE_GREEN;
- break;
-
- case 'G': {
- char* ptr = strrchr(optarg, ',');
- if(ptr && ptr != strchr(optarg, ','))
- res = RES_BAD_ARG; /* Expecting 1 or 0 ',' */
- if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- res = RES_BAD_ARG;
- if(args->mode & MODE_BIN_GREEN)
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used twice.\n",
- (char)opt);
- else
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(MODE_GREEN));
- goto error;
- }
- args->mode |= MODE_BIN_GREEN;
- if(ptr) {
- args->end_paths_filename = ptr + 1;
- *ptr = '\0';
- }
- args->bin_green_filename = optarg;
- break;
- }
-
- case 'h':
- if(args->mode & USE_STDOUT_MODES) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_HELP);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used in conjunction with other dump options (%s).\n",
- (char)opt, buf);
- goto error;
- }
- args->mode |= MODE_DUMP_HELP;
- break;
-
- case 'm': {
- char* ptr;
- if(args->mode & EXCLUSIVE_MODES) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(args->mode));
- goto error;
- }
- args->mode |= MODE_MEDIUM_COMPUTE;
- GET_STR_AND_OPTIONAL_TIME_RANGE(args->medium_name, args->pos_and_time + 3);
- break;
- }
-
- case 'M': {
- struct str name;
- str_init(args->allocator, &name);
- ERR(str_set(&name, optarg));
- ERR(darray_str_push_back(&args->model_files, &name));
- str_release(&name);
- break;
- }
- case 'n': {
- unsigned long n;
- res = cstr_to_ulong(optarg, &n);
- if(res != RES_OK
- || n == 0)
- {
- if(res == RES_OK) res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Invalid argument for option -%c: %s\n",
- opt, optarg);
- goto error;
- }
- args->samples = n;
- n_used = 1;
- break;
- }
-
- case 'p':
- if(args->mode & EXCLUSIVE_MODES) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(args->mode));
- goto error;
- }
- args->mode |= MODE_PROBE_COMPUTE;
- GET_POS_AND_OPTIONAL_TIME_RANGE(optarg, args->pos_and_time, optarg);
- break;
-
- case 'P':
- if(args->mode & EXCLUSIVE_MODES) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(args->mode));
- goto error;
- }
- args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE;
-
- ERR(str_set(&keep, optarg));
- line = split_line(optarg, ':');
- if(!line) {
- res = RES_MEM_ERR;
- str_release(&keep);
- goto error;
- }
-
- /* We expect 1 or 2 parts in line */
- if(!line[0] || (line[1] && line[2])) {
- logger_print((args->logger), LOG_ERROR,
- "Invalid argument for option ""-%c"": %s\n",
- opt, str_cget(&keep));
- str_release(&keep);
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* First part is pos and optional time, optional second part is a
- * medium name (OK if NULL) */
- GET_POS_AND_OPTIONAL_TIME_RANGE(line[0], args->pos_and_time,
- str_cget(&keep));
- if(line[1])
- args->medium_name = optarg + strlen(line[0]) + 1;
-
- break;
-
- case 'r':
- res = cstr_to_double(optarg, &args->ref_temp);
- if(res != RES_OK
- || args->ref_temp < 0)
- {
- if(res == RES_OK) res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Invalid argument for option -%c: %s\n",
- opt, optarg);
- goto error;
- }
- break;
-
- case 'R':
- if(args->mode & EXCLUSIVE_MODES) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(args->mode));
- goto error;
- }
- args->mode |= MODE_IR_COMPUTE;
- args->camera = optarg;
- break;
-
- case 's':
- case 'S':
- case 'F': {
- char *ptr;
- if(args->mode & EXCLUSIVE_MODES) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Options -%c and -%c are exclusive.\n",
- (char)opt, mode_option(args->mode));
- goto error;
- }
- switch (opt) {
- case 's':
- args->mode |= MODE_BOUNDARY_COMPUTE;
- break;
- case 'S':
- args->mode |= MODE_MAP_COMPUTE;
- break;
- case 'F':
- args->mode |= MODE_FLUX_BOUNDARY_COMPUTE;
- break;
- }
- GET_STR_AND_OPTIONAL_TIME_RANGE(args->solve_filename, args->pos_and_time + 3);
- break;
- }
-
- case 't':
- res = cstr_to_uint(optarg, &args->nthreads);
- if(res != RES_OK
- || args->nthreads <= 0)
- {
- if(res == RES_OK) res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Invalid argument for option -%c: %s\n",
- opt, optarg);
- goto error;
- }
- break;
-
- case 'v':
- if(args->mode & USE_STDOUT_MODES) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_VERSION);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used in conjunction with other dump options (%s).\n",
- (char)opt, buf);
- goto error;
- }
- args->mode |= MODE_DUMP_VERSION;
- break;
-
- case 'V':
- res = cstr_to_int(optarg, &args->verbose);
- if(res != RES_OK
- || args->verbose < 0
- || args->verbose > 3)
- {
- if(res == RES_OK) res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Invalid argument for option -%c: %s\n",
- opt, optarg);
- goto error;
- }
- break;
-
- case 'x':
- if(!(args->mode & RANDOM_RW_MODES)) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), RANDOM_RW_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c can only be used in conjunction with one of the following options: %s.\n",
- (char)opt, buf);
- goto error;
- }
- args->rndgen_state_in_filename = optarg;
- break;
-
- case 'X':
- if(!(args->mode & RANDOM_RW_MODES)) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), RANDOM_RW_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c can only be used in conjunction with one of the following options: %s.\n",
- (char)opt, buf);
- goto error;
- }
- args->rndgen_state_out_filename = optarg;
- break;
- }
- }
-
- if(argc > optind) {
- int i;
- for(i = optind; i < argc; i++) {
- logger_print(args->logger, LOG_ERROR, "Unexpected argument: %s.\n", argv[i]);
- }
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!darray_str_size_get(&args->model_files)
- && !(args->mode & SHORT_EXIT_MODES)) {
- logger_print(args->logger, LOG_ERROR,
- "Missing mandatory argument: -M <model_file_name>\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(args->mode == UNDEF_MODE) {
- print_multiple_modes(buf, sizeof(buf), EXCLUSIVE_MODES | USE_STDOUT_MODES, 0);
- logger_print(args->logger, LOG_WARNING,
- "Nothing to do.\nOne of the following options should be used: %s\n",
- buf);
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)
- && !(args->mode & GREEN_COMPATIBLE_MODES))
- {
- print_multiple_modes(buf, sizeof(buf), GREEN_COMPATIBLE_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c can only be used in conjunction with: %s\n",
- mode_option(args->mode & (MODE_BIN_GREEN | MODE_GREEN)), buf);
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(args->mode & MODE_IR_COMPUTE && n_used) {
- logger_print(args->logger, LOG_ERROR,
- "The -n option has no effect in rendering mode;"
- " use rendering's SPP suboption instead.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(args->mode & MODE_DUMP_PATHS) {
- if(!(args->mode & COMPUTE_MODES)) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c can only be used in conjunction with an option"
- " that samples heat paths (%s).\n",
- mode_option(MODE_DUMP_PATHS), buf);
- goto error;
- }
- if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used in conjunction with -%c nor -%c.\n",
- mode_option(MODE_DUMP_PATHS), mode_option(MODE_GREEN)
- , mode_option(MODE_BIN_GREEN));
- goto error;
- }
- }
-
- if(args->mode & MODE_EXTENDED_RESULTS) {
- if(!(args->mode & EXT_COMPATIBLE_MODES)) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), EXT_COMPATIBLE_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -%c can only be used in conjunction with an option"
- " that computes a single Monte-Carlo (%s).\n",
- mode_option(MODE_EXTENDED_RESULTS), buf);
- goto error;
- }
- if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) {
- res = RES_BAD_ARG;
- logger_print(args->logger, LOG_ERROR,
- "Option -%c cannot be used in conjunction with -%c nor -%c.\n",
- mode_option(MODE_EXTENDED_RESULTS), mode_option(MODE_GREEN)
- , mode_option(MODE_BIN_GREEN));
- goto error;
- }
- }
-
- if(args->rndgen_state_in_filename && !(args->mode & COMPUTE_MODES)) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -x can only be used in conjunction with an option"
- " that launch a MC computation (%s).\n",
- buf);
- goto error;
- }
-
- if(args->rndgen_state_out_filename && !(args->mode & COMPUTE_MODES)) {
- res = RES_BAD_ARG;
- print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0);
- logger_print(args->logger, LOG_ERROR,
- "Option -X can only be used in conjunction with an option"
- " that launch a MC computation (%s).\n",
- buf);
- goto error;
- }
-
-end:
- FREE_AARRAY(line);
- str_release(&keep);
- return res;
-error:
- logger_print(args->logger, LOG_ERROR, "Use option -h to print help.\n");
- goto end;
-}
-
-
-res_T
-parse_camera
- (struct logger* logger,
- char* cam_param,
- struct stardis* stardis)
-{
- char** line = NULL;
- char** opt = NULL;
- struct camera* cam;
- struct str keep;
- int i = 0;
- res_T res = RES_OK;
-
- ASSERT(cam_param && stardis);
- cam = &stardis->camera;
- line = split_line(cam_param, ':');
- if(!line) {
- res = RES_MEM_ERR;
- goto error;
- }
-
- str_init(stardis->allocator, &keep);
- for(i = 0; *(line + i); i++) {
- size_t len = 0;
- ERR(str_set(&keep, line[i]));
- opt = split_line(line[i], '=');
- if(!opt[0] || !opt[1] || opt[2]) { /* We expect 2 parts */
- if(res == RES_OK) res = RES_BAD_ARG;
- logger_print((logger), LOG_ERROR,
- "Invalid option syntax: %s\n", str_cget(&keep));
- goto error;
- }
- if(strcasecmp(opt[0], "T") == 0) {
- GET_OPTIONAL_TIME_RANGE(opt[1], 0, cam->time_range, logger, "%s", opt[0],
- str_cget(&keep));
- }
- else if(strcasecmp(opt[0], "FILE") == 0) {
- ERR(str_set(&cam->file_name, opt[1]));
- }
- else if(strcasecmp(opt[0], "FMT") == 0) {
- if(strcasecmp(opt[1], "VTK") == 0)
- cam->fmt = STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK;
- else if(strcasecmp(opt[1], "HT") == 0)
- cam->fmt = STARDIS_RENDERING_OUTPUT_FILE_FMT_HT;
- else {
- logger_print(logger, LOG_ERROR,
- "Unexpected value for rendering option %s: %s.\n",
- opt[0], opt[1]);
- res = RES_BAD_ARG;
- goto error;
- }
- }
- else if(strcasecmp(opt[0], "FOV") == 0) {
- ERR(cstr_to_double(opt[1], &cam->fov));
- }
- else if(strcasecmp(opt[0], "UP") == 0) {
- ERR(cstr_to_list_double(opt[1], ',', cam->up, &len, 3));
- }
- else if(strcasecmp(opt[0], "TGT") == 0) {
- ERR(cstr_to_list_double(opt[1], ',', cam->tgt, &len, 3));
- cam->auto_look_at = 0;
- }
- else if(strcasecmp(opt[0], "POS") == 0) {
- ERR(cstr_to_list_double(opt[1], ',', cam->pos, &len, 3));
- cam->auto_look_at = 0;
- }
- else if(strcasecmp(opt[0], "IMG") == 0) {
- unsigned img_sz[2];
- ERR(cstr_to_list_uint(opt[1], 'x', img_sz, &len, 2));
- cam->img_width = img_sz[0];
- cam->img_height = img_sz[1];
- }
- else if(strcasecmp(opt[0], "SPP") == 0) {
- ERR(cstr_to_uint(opt[1], &cam->spp));
- } else {
- logger_print(logger, LOG_ERROR,
- "Unexpected option for rendering mode: %s.\n",
- opt[0]);
- res = RES_BAD_ARG;
- goto error;
- }
- FREE_AARRAY(opt);
- }
-
-end:
- FREE_AARRAY(line);
- FREE_AARRAY(opt);
-#undef FREE_AARRAY
-
- str_release(&keep);
- return res;
-error:
- logger_print(logger, LOG_ERROR, "Error parsing camera options.\n");
- logger_print(logger, LOG_ERROR, "Use the -h option to get help.\n");
- goto end;
-}
-
-#undef GET_STR_AND_OPTIONAL_TIME_RANGE
-#undef GET_POS_AND_OPTIONAL_TIME_RANGE
-#undef GET_OPTIONAL_TIME_RANGE
-
static res_T
description_set_name
(struct stardis* stardis,
@@ -1152,7 +258,9 @@ description_set_name
const char* keywords[] = {
"AUTO", "BACK", "BOTH", "FLUID", "FRONT", "F_BOUNDARY_FOR_SOLID",
"H_BOUNDARY_FOR_FLUID", "H_BOUNDARY_FOR_SOLID", "SCALE", "SOLID",
- "SOLID_FLUID_CONNECTION", "T_BOUNDARY_FOR_SOLID", "UNKNOWN" };
+ "SOLID_FLUID_CONNECTION", "SOLID_SOLID_CONNECTION", "TRAD",
+ "T_BOUNDARY_FOR_SOLID", "UNKNOWN" };
+ const char* reason = NULL;
int i;
ASSERT(name && tk);
@@ -1162,21 +270,31 @@ description_set_name
if(RES_OK == cstr_to_double(tk, &foo)) {
/* A number is not a sensible choice for a name! */
res = RES_BAD_ARG;
+ reason = "number";
goto error;
}
FOR_EACH(i, 0, sizeof(keywords) / sizeof(*keywords)) {
if(0 == strcasecmp(tk, keywords[i])) {
/* A keyword is not a sensible choice for a name! */
res = RES_BAD_ARG;
+ reason = "reserved keyword";
goto error;
}
}
+ if(str_len(name) > DESC_NAME_MAX_LEN) {
+ /* Due to Green export limitations, names are limited in length */
+ res = RES_BAD_ARG;
+ reason = "too long";
+ goto error;
+ }
/* Name is OK */
end:
return res;
error:
- logger_print(stardis->logger, LOG_ERROR, "Invalid name: %s\n", tk);
+ ASSERT(reason != NULL);
+ logger_print(stardis->logger, LOG_ERROR, "Invalid name (%s): %s\n",
+ reason, tk);
goto end;
}
@@ -1184,34 +302,34 @@ static struct description*
find_description_by_name
(struct stardis* stardis,
const struct str* name,
- size_t* out_id)
+ const struct description* self)
{
size_t i;
- ASSERT(stardis && name);
+ ASSERT(stardis && name && self);
FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) {
struct description* desc
= darray_descriptions_data_get(&stardis->descriptions) + i;
+ if(self == desc) continue;
if(str_eq(name, get_description_name(desc))) {
- if(out_id) *out_id = i;
return desc;
}
}
return NULL;
}
-/* H_BOUNDARY_FOR_SOLID Name emissivity specular_fraction hc T_env STL_filenames
- * H_BOUNDARY_FOR_FLUID Name emissivity specular_fraction hc T_env STL_filenames */
+/* H_BOUNDARY_FOR_SOLID Name ref_temperature emissivity specular_fraction hc T_env STL_filenames
+ * H_BOUNDARY_FOR_FLUID Name ref_temperature emissivity specular_fraction hc T_env STL_filenames */
static res_T
process_h
(struct stardis* stardis,
- struct dummies* dummies,
const enum description_type type,
char** tok_ctx)
{
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct h_boundary* h_boundary;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1221,36 +339,45 @@ process_h
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz+1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_h(stardis->allocator, &desc->d.h_boundary);
-
+ ERR(init_h(stardis->allocator, &desc->d.h_boundary));
+ h_boundary = desc->d.h_boundary;
desc->type = type;
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "h boundary name");
- ERR(description_set_name(stardis, &desc->d.h_boundary.name, tk));
- if(find_description_by_name(stardis, &desc->d.h_boundary.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &h_boundary->name, tk));
+ if(find_description_by_name(stardis, &h_boundary->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
+ CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "ref_temperature");
+ res = cstr_to_double(tk, &h_boundary->ref_temperature);
+ if(res != RES_OK
+ || h_boundary->ref_temperature < 0)
+ {
+ logger_print(stardis->logger, LOG_ERROR, "Invalid reference temperature: %s\n", tk);
+ if(res == RES_OK) res = RES_BAD_ARG;
+ goto end;
+ }
+ stardis->t_range[0] = MMIN(stardis->t_range[0], h_boundary->ref_temperature);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], h_boundary->ref_temperature);
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "emissivity");
- res = cstr_to_double(tk, &desc->d.h_boundary.emissivity);
+ res = cstr_to_double(tk, &h_boundary->emissivity);
if(res != RES_OK
- || desc->d.h_boundary.emissivity < 0
- || desc->d.h_boundary.emissivity > 1)
+ || h_boundary->emissivity < 0
+ || h_boundary->emissivity > 1)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "specular fraction");
- res = cstr_to_double(tk, &desc->d.h_boundary.specular_fraction);
+ res = cstr_to_double(tk, &h_boundary->specular_fraction);
if(res != RES_OK
- || desc->d.h_boundary.specular_fraction < 0
- || desc->d.h_boundary.specular_fraction > 1)
+ || h_boundary->specular_fraction < 0
+ || h_boundary->specular_fraction > 1)
{
logger_print(stardis->logger, LOG_ERROR,
"Invalid specular fraction: %s\n", tk);
@@ -1258,42 +385,45 @@ process_h
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc");
- res = cstr_to_double(tk, &desc->d.h_boundary.hc);
+ res = cstr_to_double(tk, &h_boundary->hc);
if(res != RES_OK
- || desc->d.h_boundary.hc < 0)
+ || h_boundary->hc < 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature");
- res = cstr_to_double(tk, &desc->d.h_boundary.imposed_temperature);
+ res = cstr_to_double(tk, &h_boundary->imposed_temperature);
if(res != RES_OK
- || desc->d.h_boundary.imposed_temperature < 0)
+ || h_boundary->imposed_temperature < 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
+ stardis->t_range[0] = MMIN(stardis->t_range[0], h_boundary->imposed_temperature);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], h_boundary->imposed_temperature);
if(type == DESC_BOUND_H_FOR_FLUID)
- desc->d.h_boundary.mat_id = get_dummy_solid_id(stardis, dummies);
+ ERR(get_dummy_solid_id(stardis, &h_boundary->mat_id));
else {
- struct fluid fluid_props;
- init_fluid(stardis->allocator, &fluid_props);
- fluid_props.fluid_id = allocate_stardis_medium_id(stardis);
- desc->d.h_boundary.mat_id = fluid_props.fluid_id;
+ struct fluid* fluid = NULL;
+ ERR(init_fluid(stardis->allocator, &fluid));
+ fluid->fluid_id = allocate_stardis_medium_id(stardis);
+ h_boundary->mat_id = fluid->fluid_id;
+ h_boundary->possible_external_fluid = fluid;
ASSERT(sz <= UINT_MAX);
- fluid_props.desc_id = (unsigned)sz;
- fluid_props.imposed_temperature
- = desc->d.h_boundary.imposed_temperature;
- fluid_props.is_outside = 1;
- fluid_props.is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
- ERR(create_solver_fluid(stardis, &fluid_props));
+ fluid->desc_id = (unsigned)sz;
+ fluid->imposed_temperature
+ = h_boundary->imposed_temperature;
+ fluid->is_outside = 1;
+ fluid->is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
+ ERR(create_solver_fluid(stardis, fluid));
logger_print(stardis->logger, LOG_OUTPUT,
"External fluid created: T=%g (it is medium %u)\n",
- fluid_props.imposed_temperature,
- fluid_props.fluid_id);
+ fluid->imposed_temperature,
+ fluid->fluid_id);
}
ASSERT(sz <= UINT_MAX);
@@ -1309,12 +439,12 @@ error:
static res_T
process_t
(struct stardis* stardis,
- struct dummies* dummies,
char** tok_ctx)
{
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct t_boundary* t_boundary;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1324,16 +454,15 @@ process_t
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_t(stardis->allocator, &desc->d.t_boundary);
-
+ ERR(init_t(stardis->allocator, &desc->d.t_boundary));
+ t_boundary = desc->d.t_boundary;
desc->type = DESC_BOUND_T_FOR_SOLID;
- desc->d.t_boundary.mat_id = get_dummy_fluid_id(stardis, dummies);
+
+ ERR(get_dummy_fluid_id(stardis, &t_boundary->mat_id));
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature boundary name");
- ERR(description_set_name(stardis, &desc->d.t_boundary.name, tk));
- if(find_description_by_name(stardis, &desc->d.t_boundary.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &t_boundary->name, tk));
+ if(find_description_by_name(stardis, &t_boundary->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
@@ -1341,14 +470,16 @@ process_t
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature");
- res = cstr_to_double(tk, &desc->d.t_boundary.imposed_temperature);
+ res = cstr_to_double(tk, &t_boundary->imposed_temperature);
if(res != RES_OK
- || desc->d.t_boundary.imposed_temperature < 0)
+ || t_boundary->imposed_temperature < 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
+ stardis->t_range[0] = MMIN(stardis->t_range[0], t_boundary->imposed_temperature);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], t_boundary->imposed_temperature);
ASSERT(sz <= UINT_MAX);
ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx));
@@ -1363,12 +494,12 @@ error:
static res_T
process_flx
(struct stardis* stardis,
- struct dummies* dummies,
char** tok_ctx)
{
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct f_boundary* f_boundary;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1378,16 +509,15 @@ process_flx
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_f(stardis->allocator, &desc->d.f_boundary);
-
+ ERR(init_f(stardis->allocator, &desc->d.f_boundary));
+ f_boundary = desc->d.f_boundary;
desc->type = DESC_BOUND_F_FOR_SOLID;
- desc->d.f_boundary.mat_id = get_dummy_fluid_id(stardis, dummies);
+
+ ERR(get_dummy_fluid_id(stardis, &f_boundary->mat_id));
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "flux boundary name");
- ERR(description_set_name(stardis, &desc->d.f_boundary.name, tk));
- if(find_description_by_name(stardis, &desc->d.f_boundary.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &f_boundary->name, tk));
+ if(find_description_by_name(stardis, &f_boundary->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
@@ -1395,14 +525,22 @@ process_flx
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "flux");
- res = cstr_to_double(tk, &desc->d.f_boundary.imposed_flux);
+ res = cstr_to_double(tk, &f_boundary->imposed_flux);
if(res != RES_OK
- || desc->d.f_boundary.imposed_flux == SDIS_FLUX_NONE) {
+ || f_boundary->imposed_flux == SDIS_FLUX_NONE) {
/* Flux can be < 0 but not undefined */
if(res == RES_OK) res = RES_BAD_ARG;
logger_print(stardis->logger, LOG_ERROR, "Invalid flux: %s\n", tk);
goto end;
}
+ if(f_boundary->imposed_flux != 0 && stardis->picard_order > 1) {
+ logger_print(stardis->logger, LOG_ERROR,
+ "Cannot have a flux defined at a boundary (here %f) if Picard order "
+ "is not 1 (here order is %u)\n",
+ f_boundary->imposed_flux, stardis->picard_order);
+ res = RES_BAD_ARG;
+ goto end;
+ }
ASSERT(sz <= UINT_MAX);
ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx));
@@ -1413,7 +551,7 @@ error:
goto end;
}
-/* SOLID_FLUID_CONNECTION Name emissivity specular_fraction hc STL_filenames */
+/* SOLID_FLUID_CONNECTION Name ref_temperature emissivity specular_fraction hc STL_filenames */
static res_T
process_sfc
(struct stardis* stardis,
@@ -1422,6 +560,7 @@ process_sfc
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct solid_fluid_connect* sf_connect;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1431,40 +570,50 @@ process_sfc
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_sf(stardis->allocator, &desc->d.sf_connect);
+ ERR(init_sf(stardis->allocator, &desc->d.sf_connect));
+ sf_connect = desc->d.sf_connect;
+ desc->type = DESC_SOLID_FLUID_CONNECT;
/* Use a medium ID even if there is no medium here
* As other cases use media IDs as unique IDs for read_sides_and_files calls
* we continue the trend to ensure connection ID is OK */
- desc->type = DESC_SOLID_FLUID_CONNECT;
- desc->d.sf_connect.connection_id = allocate_stardis_medium_id(stardis);
+ sf_connect->connection_id = allocate_stardis_medium_id(stardis);
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid fluid connection name");
- ERR(description_set_name(stardis, &desc->d.sf_connect.name, tk));
- if(find_description_by_name(stardis, &desc->d.sf_connect.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &sf_connect->name, tk));
+ if(find_description_by_name(stardis, &sf_connect->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
+ CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "ref_temperature");
+ res = cstr_to_double(tk, &sf_connect->ref_temperature);
+ if(res != RES_OK
+ || sf_connect->ref_temperature < 0)
+ {
+ logger_print(stardis->logger, LOG_ERROR, "Invalid reference temperature: %s\n", tk);
+ if(res == RES_OK) res = RES_BAD_ARG;
+ goto end;
+ }
+ stardis->t_range[0] = MMIN(stardis->t_range[0], sf_connect->ref_temperature);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], sf_connect->ref_temperature);
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "emissivity");
- res = cstr_to_double(tk, &desc->d.sf_connect.emissivity);
+ res = cstr_to_double(tk, &sf_connect->emissivity);
if(res != RES_OK
- || desc->d.sf_connect.emissivity < 0
- || desc->d.h_boundary.emissivity > 1)
+ || sf_connect->emissivity < 0
+ || sf_connect->emissivity > 1)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "specular fraction");
- res = cstr_to_double(tk, &desc->d.sf_connect.specular_fraction);
+ res = cstr_to_double(tk, &sf_connect->specular_fraction);
if(res != RES_OK
- || desc->d.sf_connect.specular_fraction < 0
- || desc->d.sf_connect.specular_fraction > 1)
+ || sf_connect->specular_fraction < 0
+ || sf_connect->specular_fraction > 1)
{
logger_print(stardis->logger, LOG_ERROR,
"Invalid specular fraction: %s\n", tk);
@@ -1472,9 +621,9 @@ process_sfc
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc");
- res = cstr_to_double(tk, &desc->d.sf_connect.hc);
+ res = cstr_to_double(tk, &sf_connect->hc);
if(res != RES_OK
- || desc->d.sf_connect.hc < 0)
+ || sf_connect->hc < 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
@@ -1499,6 +648,7 @@ process_ssc
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct solid_solid_connect* ss_connect;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1508,19 +658,18 @@ process_ssc
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_ss(stardis->allocator, &desc->d.ss_connect);
+ ERR(init_ss(stardis->allocator, &desc->d.ss_connect));
+ ss_connect = desc->d.ss_connect;
+ desc->type = DESC_SOLID_SOLID_CONNECT;
/* Use a medium ID even if there is no medium here
* As other cases use media IDs as unique IDs for read_sides_and_files calls
* we continue the trend to ensure connection ID is OK */
- desc->type = DESC_SOLID_SOLID_CONNECT;
- desc->d.ss_connect.connection_id = allocate_stardis_medium_id(stardis);
+ ss_connect->connection_id = allocate_stardis_medium_id(stardis);
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid solid connection name");
- ERR(description_set_name(stardis, &desc->d.ss_connect.name, tk));
- if(find_description_by_name(stardis, &desc->d.ss_connect.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &ss_connect->name, tk));
+ if(find_description_by_name(stardis, &ss_connect->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
@@ -1528,19 +677,19 @@ process_ssc
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "contact resistance");
- res = cstr_to_double(tk, &desc->d.ss_connect.tcr);
+ res = cstr_to_double(tk, &ss_connect->tcr);
if(res != RES_OK
- || desc->d.ss_connect.tcr < 0)
+ || ss_connect->tcr < 0)
{
logger_print(stardis->logger, LOG_ERROR,
"Invalid contact resistance: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
- else if(desc->d.ss_connect.tcr == 0) {
+ else if(ss_connect->tcr == 0) {
logger_print(stardis->logger, LOG_WARNING,
"Solid-solid connection %s: defining a contact resistance to 0 has "
- "no effect\n", str_cget(&desc->d.ss_connect.name));
+ "no effect\n", str_cget(&ss_connect->name));
}
ASSERT(sz <= UINT_MAX);
@@ -1638,6 +787,7 @@ process_solid
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct solid* solid;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1647,20 +797,19 @@ process_solid
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_solid(stardis->allocator, &desc->d.solid);
-
+ ERR(init_solid(stardis->allocator, &desc->d.solid));
+ solid = desc->d.solid;
desc->type = DESC_MAT_SOLID;
- desc->d.solid.solid_id = allocate_stardis_medium_id(stardis);
- desc->d.solid.is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
- desc->d.solid.is_outside = 0;
+
+ solid->solid_id = allocate_stardis_medium_id(stardis);
+ solid->is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
+ solid->is_outside = 0;
ASSERT(sz <= UINT_MAX);
- desc->d.solid.desc_id = (unsigned)sz;
+ solid->desc_id = (unsigned)sz;
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid name");
- ERR(description_set_name(stardis, &desc->d.solid.name, tk));
- if(find_description_by_name(stardis, &desc->d.solid.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &solid->name, tk));
+ if(find_description_by_name(stardis, &solid->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
@@ -1668,60 +817,74 @@ process_solid
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "lambda");
- res = cstr_to_double(tk, &desc->d.solid.lambda);
+ res = cstr_to_double(tk, &solid->lambda);
if(res != RES_OK
- || desc->d.solid.lambda <= 0)
+ || solid->lambda <= 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid lambda: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "rho");
- res = cstr_to_double(tk, &desc->d.solid.rho);
+ res = cstr_to_double(tk, &solid->rho);
if(res != RES_OK
- || desc->d.solid.rho <= 0)
+ || solid->rho <= 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "cp");
- res = cstr_to_double(tk, &desc->d.solid.cp);
+ res = cstr_to_double(tk, &solid->cp);
if(res != RES_OK
- || desc->d.solid.cp <= 0)
+ || solid->cp <= 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
- ERR(read_delta(stardis, &desc->d.solid.delta, tok_ctx));
+ ERR(read_delta(stardis, &solid->delta, tok_ctx));
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Tinit");
- res = cstr_to_double(tk, &desc->d.solid.tinit);
+ res = cstr_to_double(tk, &solid->tinit);
if(res != RES_OK
- || desc->d.solid.tinit < 0)
+ || solid->tinit < 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
- ERR(read_imposed_temperature(stardis, &desc->d.solid.imposed_temperature,
+ stardis->t_range[0] = MMIN(stardis->t_range[0], solid->tinit);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], solid->tinit);
+ ERR(read_imposed_temperature(stardis, &solid->imposed_temperature,
tok_ctx));
- if(desc->d.solid.imposed_temperature >= 0
- && desc->d.solid.imposed_temperature != desc->d.solid.tinit)
+ if(solid->imposed_temperature >= 0
+ && solid->imposed_temperature != solid->tinit)
{
logger_print(stardis->logger, LOG_ERROR,
"Imposed temperature, if defined, must match initial temperature "
"(initial: %g; imposed: %g)\n",
- desc->d.solid.tinit, desc->d.solid.imposed_temperature); res = RES_BAD_ARG;
+ solid->tinit, solid->imposed_temperature);
+ res = RES_BAD_ARG;
goto end;
}
+ if(solid->imposed_temperature >= 0)
+ stardis->t_range[0] = MMIN(stardis->t_range[0], solid->imposed_temperature);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], solid->imposed_temperature);
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "volumic power");
- res = cstr_to_double(tk, &desc->d.solid.vpower);
+ res = cstr_to_double(tk, &solid->vpower);
if(res != RES_OK) {
/* VPower can be < 0 */
logger_print(stardis->logger, LOG_ERROR, "Invalid volumic power: %s\n", tk);
goto end;
}
+ if(solid->vpower != 0 && stardis->picard_order > 1) {
+ logger_print(stardis->logger, LOG_ERROR,
+ "Cannot have volumic power (here %f) if Picard order is not 1 "
+ "(here order is %u)\n",
+ solid->vpower, stardis->picard_order);
+ res = RES_BAD_ARG;
+ goto end;
+ }
/* Actual solid creation is defered until geometry is read to allow
* enclosure shape VS delta analysis (and auto delta computation) */
@@ -1744,6 +907,7 @@ process_fluid
char* tk = NULL;
struct description* desc;
size_t sz;
+ struct fluid* fluid;
res_T res = RES_OK;
ASSERT(stardis && tok_ctx);
@@ -1753,20 +917,19 @@ process_fluid
sz = darray_descriptions_size_get(&stardis->descriptions);
ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1));
desc = darray_descriptions_data_get(&stardis->descriptions) + sz;
- init_fluid(stardis->allocator, &desc->d.fluid);
-
+ ERR(init_fluid(stardis->allocator, &desc->d.fluid));
+ fluid = desc->d.fluid;
desc->type = DESC_MAT_FLUID;
- desc->d.fluid.fluid_id = allocate_stardis_medium_id(stardis);
- desc->d.fluid.is_outside = 0;
- desc->d.fluid.is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
+
+ fluid->fluid_id = allocate_stardis_medium_id(stardis);
+ fluid->is_outside = 0;
+ fluid->is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
ASSERT(sz <= UINT_MAX);
- desc->d.fluid.desc_id = (unsigned)sz;
+ fluid->desc_id = (unsigned)sz;
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "fluid name");
- ERR(description_set_name(stardis, &desc->d.fluid.name, tk));
- if(find_description_by_name(stardis, &desc->d.fluid.name, NULL)
- != desc)
- {
+ ERR(description_set_name(stardis, &fluid->name, tk));
+ if(find_description_by_name(stardis, &fluid->name, desc)) {
logger_print(stardis->logger, LOG_ERROR,
"Name already used: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
@@ -1774,46 +937,51 @@ process_fluid
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "rho");
- res = cstr_to_double(tk, &desc->d.fluid.rho);
+ res = cstr_to_double(tk, &fluid->rho);
if(res != RES_OK
- || desc->d.fluid.rho <= 0)
+ || fluid->rho <= 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "cp");
- res = cstr_to_double(tk, &desc->d.fluid.cp);
+ res = cstr_to_double(tk, &fluid->cp);
if(res != RES_OK
- || desc->d.fluid.cp <= 0)
+ || fluid->cp <= 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Tinit");
- res = cstr_to_double(tk, &desc->d.fluid.tinit);
+ res = cstr_to_double(tk, &fluid->tinit);
if(res != RES_OK
- || desc->d.fluid.tinit < 0)
+ || fluid->tinit < 0)
{
logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", tk);
if(res == RES_OK) res = RES_BAD_ARG;
goto end;
}
-
- ERR(read_imposed_temperature(stardis, &desc->d.fluid.imposed_temperature,
+ stardis->t_range[0] = MMIN(stardis->t_range[0], fluid->tinit);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], fluid->tinit);
+ ERR(read_imposed_temperature(stardis, &fluid->imposed_temperature,
tok_ctx));
- if(desc->d.fluid.imposed_temperature >= 0
- && desc->d.fluid.imposed_temperature != desc->d.fluid.tinit)
+ if(fluid->imposed_temperature >= 0
+ && fluid->imposed_temperature != fluid->tinit)
{
logger_print(stardis->logger, LOG_ERROR,
"Imposed temperature, if defined, must match initial temperature "
"(initial: %g; imposed: %g)\n",
- desc->d.fluid.tinit, desc->d.fluid.imposed_temperature); res = RES_BAD_ARG;
+ fluid->tinit, fluid->imposed_temperature);
+ res = RES_BAD_ARG;
goto end;
}
+ if(fluid->imposed_temperature >= 0)
+ stardis->t_range[0] = MMIN(stardis->t_range[0], fluid->imposed_temperature);
+ stardis->t_range[1] = MMAX(stardis->t_range[1], fluid->imposed_temperature);
- ERR(create_solver_fluid(stardis, &desc->d.fluid));
+ ERR(create_solver_fluid(stardis, fluid));
ASSERT(sz <= UINT_MAX);
ERR(read_sides_and_files(stardis, 0, (unsigned)sz, tok_ctx));
@@ -1858,15 +1026,61 @@ error:
goto end;
}
+/* TRAD Trad Trad_ref */
+static res_T
+process_radiative
+ (struct stardis* stardis,
+ char** tok_ctx)
+{
+ char* tk = NULL;
+ res_T res = RES_OK;
+
+ ASSERT(stardis && tok_ctx);
+
+ if(stardis->trad_def) {
+ logger_print(stardis->logger, LOG_ERROR,
+ "TRAD cannot be specified twice\n");
+ res = RES_BAD_ARG;
+ goto end;
+ }
+ CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Trad");
+ res = cstr_to_double(tk, &stardis->trad);
+ if(res != RES_OK
+ || stardis->trad < 0)
+ {
+ logger_print(stardis->logger, LOG_ERROR,
+ "Invalid Trad: %s\n", tk);
+ if(res == RES_OK) res = RES_BAD_ARG;
+ goto end;
+ }
+ CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Trad reference");
+ res = cstr_to_double(tk, &stardis->trad_ref);
+ if(res != RES_OK
+ || stardis->trad_ref < 0)
+ {
+ logger_print(stardis->logger, LOG_ERROR,
+ "Invalid Trad reference: %s\n", tk);
+ if(res == RES_OK) res = RES_BAD_ARG;
+ goto end;
+ }
+ stardis->trad_def = 1;
+
+end:
+ return res;
+error:
+ goto end;
+}
+
/* Read medium or boundary line; should be one of:
* SOLID Name lambda rho cp delta Tinit Timposed volumic_power STL_filenames
* FLUID Name rho cp Tinit Timposed STL_filenames
- * H_BOUNDARY_FOR_SOLID Name emissivity specular_fraction hc T_env STL_filenames
- * H_BOUNDARY_FOR_FLUID Name emissivity specular_fraction hc T_env STL_filenames
+ * H_BOUNDARY_FOR_SOLID Name ref_temperature emissivity specular_fraction hc T_env STL_filenames
+ * H_BOUNDARY_FOR_FLUID Name ref_temperature emissivity specular_fraction hc T_env STL_filenames
* T_BOUNDARY_FOR_SOLID Name T STL_filenames
* F_BOUNDARY_FOR_SOLID Name F STL_filenames
- * SOLID_FLUID_CONNECTION Name emissivity specular_fraction hc STL_filenames
+ * SOLID_FLUID_CONNECTION Name ref_temperature emissivity specular_fraction hc STL_filenames
* SCALE scale_factor
+ * TRAD Trad Trad_ref
*
* STL_filenames = { { FRONT | BACK | BOTH } STL_filename }+
*/
@@ -1874,8 +1088,7 @@ res_T
process_model_line
(const char* file_name,
char* line,
- struct stardis* stardis,
- struct dummies* dummies)
+ struct stardis* stardis)
{
res_T res = RES_OK;
struct str keep;
@@ -1888,13 +1101,13 @@ process_model_line
CHK_TOK(strtok_r(line, " \t", &tok_ctx), "model line type");
if(0 == strcasecmp(tk, "H_BOUNDARY_FOR_SOLID"))
- ERR(process_h(stardis, dummies, DESC_BOUND_H_FOR_SOLID, &tok_ctx));
+ ERR(process_h(stardis, DESC_BOUND_H_FOR_SOLID, &tok_ctx));
else if(0 == strcasecmp(tk, "H_BOUNDARY_FOR_FLUID"))
- ERR(process_h(stardis, dummies, DESC_BOUND_H_FOR_FLUID, &tok_ctx));
+ ERR(process_h(stardis, DESC_BOUND_H_FOR_FLUID, &tok_ctx));
else if(0 == strcasecmp(tk, "T_BOUNDARY_FOR_SOLID"))
- ERR(process_t(stardis, dummies, &tok_ctx));
+ ERR(process_t(stardis, &tok_ctx));
else if(0 == strcasecmp(tk, "F_BOUNDARY_FOR_SOLID"))
- ERR(process_flx(stardis, dummies, &tok_ctx));
+ ERR(process_flx(stardis, &tok_ctx));
else if(0 == strcasecmp(tk, "SOLID_FLUID_CONNECTION"))
ERR(process_sfc(stardis, &tok_ctx));
else if(0 == strcasecmp(tk, "SOLID_SOLID_CONNECTION"))
@@ -1905,6 +1118,8 @@ process_model_line
ERR(process_fluid(stardis, &tok_ctx));
else if(0 == strcasecmp(tk, "SCALE"))
ERR(process_scale(stardis, &tok_ctx));
+ else if(0 == strcasecmp(tk, "TRAD"))
+ ERR(process_radiative(stardis, &tok_ctx));
else {
logger_print(stardis->logger, LOG_ERROR,
"Unknown description type: %s\n", tk);
@@ -1922,46 +1137,68 @@ error:
goto end;
}
-unsigned
+res_T
get_dummy_solid_id
(struct stardis* stardis,
- struct dummies* dummies)
+ unsigned* id)
{
- struct solid dummy;
- if(dummies->dummy_solid)
- return dummies->dummy_solid_id;
+ res_T res = RES_OK;
+ struct solid* dummy = NULL;
+ struct dummies* dummies;
+ ASSERT(stardis && id);
+ dummies = &stardis->dummies;
+ if(dummies->dummy_solid) {
+ *id = dummies->dummy_solid_id;
+ goto end;
+ }
+ ERR(init_solid(stardis->allocator, &dummy));
+ dummies->stardis_solid = dummy;
dummies->dummy_solid_id = allocate_stardis_medium_id(stardis);
- init_solid(stardis->allocator, &dummy);
- dummy.solid_id = dummies->dummy_solid_id;
- dummy.is_outside = 1;
- dummy.is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
- create_solver_solid(stardis, &dummy);
+ dummy->solid_id = dummies->dummy_solid_id;
+ dummy->is_outside = 1;
+ dummy->is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
+ create_solver_solid(stardis, dummy);
dummies->dummy_solid
= darray_media_ptr_data_get(&stardis->media)[dummies->dummy_solid_id];
logger_print(stardis->logger, LOG_OUTPUT,
"Dummy solid created: (it is medium %u)\n",
dummies->dummy_solid_id);
- return dummies->dummy_solid_id;
+ *id = dummies->dummy_solid_id;
+end:
+ return res;
+error:
+ goto end;
}
-unsigned
+res_T
get_dummy_fluid_id
(struct stardis* stardis,
- struct dummies* dummies)
+ unsigned* id)
{
- struct fluid dummy;
- if(dummies->dummy_fluid)
- return dummies->dummy_fluid_id;
+ res_T res = RES_OK;
+ struct fluid* dummy = NULL;
+ struct dummies* dummies;
+ ASSERT(stardis && id);
+ dummies = &stardis->dummies;
+ if(dummies->dummy_fluid) {
+ *id = dummies->dummy_fluid_id;
+ goto end;
+ }
+ ERR(init_fluid(stardis->allocator, &dummy));
+ dummies->stardis_fluid = dummy;
dummies->dummy_fluid_id = allocate_stardis_medium_id(stardis);
- init_fluid(stardis->allocator, &dummy);
- dummy.fluid_id = dummies->dummy_fluid_id;
- dummy.is_outside = 1;
- dummy.is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
- create_solver_fluid(stardis, &dummy);
+ dummy->fluid_id = dummies->dummy_fluid_id;
+ dummy->is_outside = 1;
+ dummy->is_green = stardis->mode & (MODE_BIN_GREEN | MODE_GREEN);
+ create_solver_fluid(stardis, dummy);
dummies->dummy_fluid
= darray_media_ptr_data_get(&stardis->media)[dummies->dummy_fluid_id];
logger_print(stardis->logger, LOG_OUTPUT,
"Dummy fluid created: (it is medium %u)\n",
dummies->dummy_fluid_id);
- return dummies->dummy_fluid_id;
+ *id = dummies->dummy_fluid_id;
+end:
+ return res;
+error:
+ goto end;
}
diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,89 +37,6 @@ struct dummies;
goto error;\
} (void)0
-#ifdef COMPILER_CL
-#define strtok_r strtok_s
-#endif
-
-enum stardis_mode {
- /* Ordered so that print_multiple_modes() prints in alphabetical order */
- UNDEF_MODE = 0,
- MODE_DUMP_C_CHUNKS = BIT(0), /* -c */
- MODE_DUMP_PATHS = BIT(1), /* -D */
- MODE_DUMP_VTK = BIT(2), /* -d */
- MODE_EXTENDED_RESULTS = BIT(3), /* -e */
- MODE_FLUX_BOUNDARY_COMPUTE = BIT(4), /* -F */
- MODE_BIN_GREEN = BIT(5), /* -G */
- MODE_GREEN = BIT(6), /* -g */
- MODE_DUMP_HELP = BIT(7), /* -h */
- MODE_MEDIUM_COMPUTE = BIT(8), /* -m */
- MODE_PROBE_COMPUTE_ON_INTERFACE = BIT(9), /* -P */
- MODE_PROBE_COMPUTE = BIT(10), /* -p */
- MODE_IR_COMPUTE = BIT(11), /* -R */
- MODE_MAP_COMPUTE = BIT(12), /* -S */
- MODE_BOUNDARY_COMPUTE = BIT(13), /* -s */
- MODE_VERBOSITY = BIT(14), /* -V */
- MODE_DUMP_VERSION = BIT(15), /* -v */
-
- GREEN_COMPATIBLE_MODES
- = MODE_PROBE_COMPUTE | MODE_PROBE_COMPUTE_ON_INTERFACE | MODE_MEDIUM_COMPUTE
- | MODE_BOUNDARY_COMPUTE,
-
- SURFACE_COMPUTE_MODES
- = MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE | MODE_MAP_COMPUTE,
-
- EXT_COMPATIBLE_MODES
- = GREEN_COMPATIBLE_MODES | MODE_MEDIUM_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE,
-
- REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES | MODE_MEDIUM_COMPUTE,
-
- COMPUTE_MODES = GREEN_COMPATIBLE_MODES | MODE_IR_COMPUTE | SURFACE_COMPUTE_MODES,
-
- EXCLUSIVE_MODES = COMPUTE_MODES,
-
- SHORT_EXIT_MODES = MODE_DUMP_HELP | MODE_DUMP_VERSION,
-
- USE_STDOUT_MODES
- = MODE_DUMP_C_CHUNKS | MODE_DUMP_VTK | MODE_DUMP_HELP | MODE_DUMP_VERSION
- | MODE_IR_COMPUTE | MODE_GREEN,
-
- RANDOM_RW_MODES
- = MODE_PROBE_COMPUTE | MODE_PROBE_COMPUTE_ON_INTERFACE | MODE_MEDIUM_COMPUTE
- | MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE
-};
-
-STATIC_ASSERT(GREEN_COMPATIBLE_MODES == (COMPUTE_MODES & GREEN_COMPATIBLE_MODES),
- Cannot_have_a_GREEN_COMPATIBLE_MODE_that_is_not_a_COMPUTE_MODE);
-
-enum dump_path_type {
- DUMP_NONE = 0,
- DUMP_SUCCESS = BIT(0),
- DUMP_ERROR = BIT(1),
- DUMP_ALL = DUMP_SUCCESS | DUMP_ERROR
-};
-
-struct args {
- struct logger* logger;
- struct mem_allocator* allocator;
- struct darray_str model_files;
- char* medium_name;
- char* solve_filename;
- char* bin_green_filename;
- char* end_paths_filename;
- char* paths_filename;
- char* rndgen_state_in_filename;
- char* rndgen_state_out_filename;
- char* chunks_prefix;
- size_t samples;
- unsigned nthreads;
- double pos_and_time[5];
- enum stardis_mode mode;
- double ambient_temp, ref_temp;
- char* camera;
- enum dump_path_type dump_paths;
- int verbose;
-};
-
/* Same ctx used for both media and interface add (some unused parts) */
struct add_geom_ctx {
struct sstl_desc stl_desc;
@@ -148,63 +65,19 @@ add_geom_ctx_position
void* context);
extern LOCAL_SYM res_T
-init_args
- (struct logger* logger,
- struct mem_allocator* mem,
- struct args** args);
-
-extern LOCAL_SYM void
-release_args
- (struct args* args);
-
-extern char
-mode_option
- (const int m);
-
-extern void
-print_multiple_modes
- (char* buf,
- const size_t sz,
- const int modes,
- const int dont);
-
-extern void
-print_version
- (FILE* stream);
-
-extern void
-short_help
- (FILE* stream,
- const char* prog);
-
-extern res_T
-parse_args
- (const int argc,
- char** argv,
- struct args* args,
- struct mem_allocator* allocator);
-
-extern res_T
-parse_camera
- (struct logger* logger,
- char* cam_param,
- struct stardis* stardis);
-
-extern LOCAL_SYM res_T
process_model_line
(const char* file_name,
char* line,
- struct stardis* stardis,
- struct dummies* dummies);
+ struct stardis* stardis);
-extern LOCAL_SYM unsigned
+extern LOCAL_SYM res_T
get_dummy_solid_id
(struct stardis* stardis,
- struct dummies* dummies);
+ unsigned* id);
-extern LOCAL_SYM unsigned
+extern LOCAL_SYM res_T
get_dummy_fluid_id
(struct stardis* stardis,
- struct dummies* dummies);
+ unsigned* id);
#endif /*ARGS_H*/
diff --git a/src/stardis-solid.c b/src/stardis-solid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
#include <sdis.h>
+#include <rsys/mem_allocator.h>
+
#include <limits.h>
/*******************************************************************************
@@ -30,9 +32,9 @@ solid_get_calorific_capacity
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
+ const struct solid* const* solid_props = sdis_data_cget(data);
(void)vtx;
- return solid_props->cp;
+ return (*solid_props)->cp;
}
static double
@@ -40,9 +42,9 @@ solid_get_thermal_conductivity
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
+ const struct solid* const* solid_props = sdis_data_cget(data);
(void)vtx;
- return solid_props->lambda;
+ return (*solid_props)->lambda;
}
static double
@@ -50,9 +52,9 @@ solid_get_volumic_mass
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
+ const struct solid* const* solid_props = sdis_data_cget(data);
(void)vtx;
- return solid_props->rho;
+ return (*solid_props)->rho;
}
static double
@@ -60,9 +62,9 @@ solid_get_delta
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
+ const struct solid* const* solid_props = sdis_data_cget(data);
(void)vtx;
- return solid_props->delta;
+ return (*solid_props)->delta;
}
#if Stardis_VERSION_MINOR == 3
@@ -71,8 +73,8 @@ solid_get_delta_boundary
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
- return solid_props->delta;
+ const struct solid* const* solid_props = sdis_data_cget(data);
+ return (*solid_props)->delta;
}
#endif
@@ -81,21 +83,21 @@ solid_get_temperature
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
- if(solid_props->imposed_temperature >= 0)
+ const struct solid* const* solid_props = sdis_data_cget(data);
+ if((*solid_props)->imposed_temperature >= 0)
/* If there is an imposed temp, it is imposed regardless of time */
- return solid_props->imposed_temperature;
- if(vtx->time <= solid_props->t0) {
+ return (*solid_props)->imposed_temperature;
+ if(vtx->time <= (*solid_props)->t0) {
/* If time is <= t0: use tinit */
- if(solid_props->tinit < 0) {
- if(str_is_empty(&solid_props->name)) {
+ if((*solid_props)->tinit < 0) {
+ if(str_is_empty(&(*solid_props)->name)) {
FATAL("solid_get_temperature: getting undefined Tinit\n");
} else {
VFATAL("solid_get_temperature: getting undefined Tinit (solid '%s')\n",
- ARG1(str_cget(&solid_props->name)));
+ ARG1(str_cget(&(*solid_props)->name)));
}
}
- return solid_props->tinit;
+ return (*solid_props)->tinit;
}
return -1; /* Unknown temperature */
}
@@ -105,9 +107,9 @@ solid_get_power
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
- const struct solid* solid_props = sdis_data_cget(data);
+ const struct solid* const* solid_props = sdis_data_cget(data);
(void)vtx;
- return solid_props->vpower;
+ return (*solid_props)->vpower;
}
/*******************************************************************************
@@ -122,14 +124,14 @@ create_solver_solid
res_T res = RES_OK;
struct sdis_solid_shader solid_shader = SDIS_SOLID_SHADER_NULL;
struct sdis_data* data = NULL;
- struct solid* props;
+ const struct solid** props;
/* Could be less restrictive if green output included positions/dates */
ASSERT(stardis && solid_props);
solid_shader.calorific_capacity = solid_get_calorific_capacity;
solid_shader.thermal_conductivity = solid_get_thermal_conductivity;
solid_shader.volumic_mass = solid_get_volumic_mass;
- solid_shader.delta_solid = solid_get_delta;
+ solid_shader.delta = solid_get_delta;
#if Stardis_VERSION_MINOR == 3
solid_shader.delta_boundary = solid_get_delta_boundary;
#endif
@@ -138,13 +140,12 @@ create_solver_solid
NULL, &data));
props = sdis_data_get(data); /* Fetch the allocated memory space */
- init_solid(stardis->allocator, props);
- cp_solid(props, solid_props);
+ *props = solid_props;
if(solid_props->vpower != 0) solid_shader.volumic_power = solid_get_power;
if(solid_props->solid_id >= darray_media_ptr_size_get(&stardis->media)) {
ERR(darray_media_ptr_resize(&stardis->media, solid_props->solid_id + 1));
}
- ASSERT(darray_media_ptr_data_get(&stardis->media)[solid_props->solid_id] == NULL);
+ ASSERT(!darray_media_ptr_data_get(&stardis->media)[solid_props->solid_id]);
ERR(sdis_solid_create(stardis->dev, &solid_shader, data,
darray_media_ptr_data_get(&stardis->media) + solid_props->solid_id));
@@ -155,28 +156,46 @@ error:
goto end;
}
-void
-init_solid(struct mem_allocator* allocator, struct solid* dst)
+res_T
+init_solid(struct mem_allocator* allocator, struct solid** dst)
{
- str_init(allocator, &dst->name);
- dst->lambda = 1;
- dst->rho = 1;
- dst->cp = 1;
- dst->delta = 1;
- dst->tinit = -1;
- dst->imposed_temperature = -1;
- dst->vpower = 0;
- dst->t0 = 0;
- dst->is_outside = 0;
- dst->is_green = 0;
- dst->desc_id = UINT_MAX;
- dst->solid_id = UINT_MAX;
+ res_T res = RES_OK;
+ int str_initialized = 0;
+ ASSERT(allocator && dst && *dst == NULL);
+ *dst = MEM_ALLOC(allocator, sizeof(struct solid));
+ if(! *dst) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ str_init(allocator, &(*dst)->name);
+ (*dst)->lambda = 1;
+ (*dst)->rho = 1;
+ (*dst)->cp = 1;
+ (*dst)->delta = 1;
+ (*dst)->tinit = -1;
+ (*dst)->imposed_temperature = -1;
+ (*dst)->vpower = 0;
+ (*dst)->t0 = 0;
+ (*dst)->is_outside = 0;
+ (*dst)->is_green = 0;
+ (*dst)->desc_id = UINT_MAX;
+ (*dst)->solid_id = UINT_MAX;
+end:
+ return res;
+error:
+ if(str_initialized) str_release(&(*dst)->name);
+ if(*dst) MEM_RM(allocator, *dst);
+ goto end;
}
void
-release_solid(struct solid* solid)
+release_solid
+ (struct solid* solid,
+ struct mem_allocator* allocator)
{
+ ASSERT(solid && allocator);
str_release(&solid->name);
+ MEM_RM(allocator, solid);
}
res_T
@@ -201,21 +220,3 @@ end:
error:
goto end;
}
-
-res_T
-cp_solid(struct solid* dst, const struct solid* src)
-{
- dst->lambda = src->lambda;
- dst->rho = src->rho;
- dst->cp = src->cp;
- dst->delta = src->delta;
- dst->tinit = src->tinit;
- dst->imposed_temperature = src->imposed_temperature;
- dst->vpower = src->vpower;
- dst->t0 = src->t0;
- dst->is_outside = src->is_outside;
- dst->is_green = src->is_green;
- dst->desc_id = src->desc_id;
- dst->solid_id = src->solid_id;
- return str_copy(&dst->name, &src->name);
-}
diff --git a/src/stardis-solid.h b/src/stardis-solid.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
#include <rsys/str.h>
struct stardis;
+struct mem_allocator;
/*******************************************************************************
* Solid data
@@ -40,17 +41,16 @@ struct solid {
unsigned solid_id;
};
-LOCAL_SYM void
-init_solid(struct mem_allocator* allocator, struct solid* dst);
+LOCAL_SYM res_T
+init_solid(struct mem_allocator* allocator, struct solid** dst);
LOCAL_SYM void
-release_solid(struct solid* solid);
-
-LOCAL_SYM res_T
-str_print_solid(struct str* str, const struct solid* s);
+release_solid
+ (struct solid* desc,
+ struct mem_allocator* allocator);
LOCAL_SYM res_T
-cp_solid(struct solid* dst, const struct solid* src);
+str_print_solid(struct str* str, const struct solid* solid);
LOCAL_SYM res_T
create_solver_solid
diff --git a/stardis-green-types/stardis-green-types-config-version.cmake.in b/stardis-green-types/stardis-green-types-config-version.cmake.in
@@ -0,0 +1,22 @@
+# Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+SET(PACKAGE_VERSION @STARDIS_GREEN_TYPES_VERSION@)
+
+IF (${PACKAGE_FIND_VERSION_MAJOR} EQUAL @STARDIS_GREEN_TYPES_VERSION@)
+ SET(PACKAGE_VERSION_COMPATIBLE 1)
+ELSE()
+ SET(PACKAGE_VERSION_UNSUITABLE 1)
+ENDIF()
diff --git a/stardis-green-types/stardis-green-types-config.cmake b/stardis-green-types/stardis-green-types-config.cmake
@@ -0,0 +1,28 @@
+# Copyright (C) 2013-2017, 2021 Vincent Forest (vaplv@free.fr)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 3.1)
+include(SelectLibraryConfigurations)
+
+# Try to find stardis-green-types
+
+# Look for stardis-green-types header
+find_path(SGT_INCLUDE_DIR stardis-green-types.h)
+
+# Check the package
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(stardis-green-types DEFAULT_MSG
+ SGT_INCLUDE_DIR)
+