stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

commit b8e8125c6eaee35ff6799433920e960f2b100613
parent 4dc240f2e294a0896a02921fe72c1838a775090c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 24 Apr 2023 17:10:18 +0200

Merge branch 'release_0.9'

Diffstat:
MREADME.md | 41+++++++++++++++++++++++++++++++++++------
Mcmake/CMakeLists.txt | 51++++++++++++++++++++++++++++++++++++++++++++++-----
Mcmake/doc/CMakeLists.txt | 2+-
Mcmake/stardis-green-types/CMakeLists.txt | 2+-
Acmake/stardis-prog-properties/CMakeLists.txt | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdoc/stardis-input.5.txt | 316++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mdoc/stardis-output.5.txt | 47+++++++++++++++++++++++++----------------------
Mdoc/stardis.1.txt.in | 8+++++---
Msrc/stardis-app.c | 284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/stardis-app.h | 697+++++--------------------------------------------------------------------------
Msrc/stardis-args.c | 5+++--
Msrc/stardis-args.h | 15+++++++--------
Msrc/stardis-compute.c | 347+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/stardis-compute.h | 9++++-----
Msrc/stardis-default.h.in | 2+-
Asrc/stardis-description.c | 294+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-description.h | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-fbound-prog.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-fbound-prog.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-fbound.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-fbound.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-fluid-prog.c | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-fluid-prog.h | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-fluid.c | 13++++++-------
Msrc/stardis-fluid.h | 10+++++-----
Msrc/stardis-green-types.h.in | 2++
Asrc/stardis-hbound-prog.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hbound-prog.h | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hbound.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hbound.h | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hfbound-prog.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hfbound-prog.h | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hfbound.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-hfbound.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-intface.c | 532++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/stardis-intface.h | 19++++++++++++++-----
Msrc/stardis-main.c | 5+++--
Msrc/stardis-output.c | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/stardis-output.h | 34+++++++++++++++++-----------------
Msrc/stardis-parsing.c | 1701+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/stardis-parsing.h | 51+++++++++++++++++++++++++--------------------------
Asrc/stardis-prog-properties.h.in | 584+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-program.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-program.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-sfconnect-prog.c | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-sfconnect-prog.h | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-sfconnect.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-sfconnect.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-solid-prog.c | 205+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-solid-prog.h | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-solid.c | 17++++++++---------
Msrc/stardis-solid.h | 12++++++------
Asrc/stardis-ssconnect-prog.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-ssconnect-prog.h | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-ssconnect.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-ssconnect.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-tbound-prog.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-tbound-prog.h | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-tbound.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-tbound.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-version.h.in | 2+-
Mstardis-green-types/stardis-green-types-config-version.cmake.in | 2+-
Mstardis-green-types/stardis-green-types-config.cmake | 2+-
Astardis-prog-properties/stardis-prog-properties-config-version.cmake.in | 22++++++++++++++++++++++
Astardis-prog-properties/stardis-prog-properties-config.cmake | 28++++++++++++++++++++++++++++
65 files changed, 6589 insertions(+), 1508 deletions(-)

diff --git a/README.md b/README.md @@ -9,7 +9,6 @@ and exposes some of the main features of the solver in an easy to use way. Using stardis is a practical way of carrying out thermal studies on CAD models which can be exported from Salomé or other similar software. - ## How to build Stardis relies on the [CMake](http://www.cmake.org) and the @@ -26,8 +25,6 @@ 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. Then install the RCMake package as well as all the aforementioned prerequisites. Finally generate the project from @@ -36,7 +33,39 @@ variable the install directories of its dependencies. ## Release notes -## Version 0.8 +### Version 0.9 + +#### Programmable properties + +Until now, physical properties as well as boundary and connection conditions +were constant in time and space. In this version, they can be programmed, i.e. +they are variables returned by functions implemented in user-defined libraries +and submitted as dynamically loaded input libraries when Stardis starts. User +libraries must also provide create/release functions that are invoked at +start-up to allow users to load their data and build the internal data +structures required by their libraries at run-time. + +The `stardis-input` file format has been updated to provide a set of new +`_PROG` suffixed keywords used to define these programmed properties and +conditions (e.g. `T_BOUNDARY_FOR_SOLID_PROG` or `H_BOUNDARY_FOR_FLUID_PROG`) + +#### Miscellaneous + +- Addition of the keyword `HF_BOUNDARY_FOR_SOLID` which allows to impose a flux + on a boundary with another condition. For example, a net flux can be defined + in addition to a convective exchange and a radiative transfer. +- Correct the definition of a net flux as a boundary condition: it might not be + defined on the right side of the interface. +- Correct the "subpath type" data of the output paths: as we attach the segment + type to the vertices, we need to locate the type changes along the path on + zero length segments, otherwise the colouring will show a misleading colour + gradient. +- Replace the Mersenne Twister random number generator with Threefry: the + former is much less efficient at rejecting random numbers than the latter, + which is designed for this purpose, a feature on which parallel random number + generations depend heavily + +### 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 @@ -104,7 +133,7 @@ Fix debug build. ### Version 0.3.1 -Add radiative transfer computations. To achieve this, media gain 2 new parameters: +Add radiative transfer computations. To achieve this, media gain 2 new parameters: - emissivity; - `specular_fraction`. @@ -126,7 +155,7 @@ Add radiative transfer computations. To achieve this, media gain 2 new parameter ## License -Copyright (C) 2018-2021 |Meso|Star> (<contact@meso-star.com>). Stardis is free +Copyright (C) 2018-2023 |Méso|Star> (<contact@meso-star.com>). Stardis is free software released under the GPL v3+ license: GNU GPL version 3 or later. You are welcome to redistribute it under certain conditions; refer to the COPYING file for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +# Copyright (C) 2018-2023 |Méso|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 @@ -18,6 +18,7 @@ project(stardis C) set(SDIS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) set(SDIS_SGT_DIR ${PROJECT_SOURCE_DIR}/../stardis-green-types) +set(SDIS_PRG_DIR ${PROJECT_SOURCE_DIR}/../stardis-prog-properties) option(ENABLE_MPI @@ -62,7 +63,7 @@ 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 8) +set(SDIS_VERSION_MINOR 9) set(SDIS_VERSION_PATCH 0) set(SDIS_VERSION ${SDIS_VERSION_MAJOR}.${SDIS_VERSION_MINOR}.${SDIS_VERSION_PATCH}) @@ -73,12 +74,17 @@ configure_file(${SDIS_SOURCE_DIR}/stardis-version.h.in ${CMAKE_CURRENT_BINARY_DIR}/stardis-version.h @ONLY) set(STARDIS_GREEN_TYPES_VERSION "4") +set(STARDIS_PROG_PROPERTIES_VERSION "1") 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_SOURCE_DIR}/stardis-prog-properties.h.in + ${CMAKE_CURRENT_BINARY_DIR}/stardis-prog-properties/stardis-prog-properties.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) +configure_file(${SDIS_PRG_DIR}/stardis-prog-properties-config-version.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/stardis-prog-properties/stardis-prog-properties-config-version.cmake @ONLY) ############################################################################### # Check dependencies @@ -88,7 +94,7 @@ find_package(RSys 0.12 REQUIRED) find_package(StarGeom3D 0.1 REQUIRED) find_package(Star3D 0.8 REQUIRED) find_package(StarEnc3D 0.5 REQUIRED) -find_package(Stardis 0.13 REQUIRED) +find_package(Stardis 0.14 REQUIRED) find_package(StarSTL 0.3 REQUIRED) find_package(StarSP 0.13 REQUIRED) if(MSVC) @@ -110,7 +116,8 @@ include_directories( ${StarSTL_INCLUDE_DIR} ${StarSP_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types) + ${CMAKE_CURRENT_BINARY_DIR}/stardis-green-types + ${CMAKE_CURRENT_BINARY_DIR}/stardis-prog-properties) if(MSVC) include_directories(${MuslGetopt_INCLUDE_DIR}) endif() @@ -136,6 +143,7 @@ if(NOT STARDIS_DOC STREQUAL "NONE") endif() add_subdirectory(stardis-green-types) +add_subdirectory(stardis-prog-properties) ############################################################################### # Configure and define targets @@ -144,24 +152,57 @@ set(SDIS_FILES_SRC stardis-app.c stardis-args.c stardis-compute.c + stardis-description.c stardis-fluid.c + stardis-fluid-prog.c + stardis-fbound.c + stardis-fbound-prog.c + stardis-hbound.c + stardis-hbound-prog.c + stardis-hfbound.c + stardis-hfbound-prog.c stardis-intface.c stardis-main.c stardis-output.c stardis-parsing.c - stardis-solid.c) + stardis-program.c + stardis-sfconnect.c + stardis-sfconnect-prog.c + stardis-ssconnect.c + stardis-ssconnect-prog.c + stardis-solid.c + stardis-solid-prog.c + stardis-tbound.c + stardis-tbound-prog.c) set(SDIS_FILES_INC stardis-app.h stardis-args.h stardis-compute.h + stardis-description.h stardis-default.h.in stardis-fluid.h + stardis-fluid-prog.h + stardis-fbound.h + stardis-fbound-prog.h stardis-green-types.h.in + stardis-hbound.h + stardis-hbound-prog.h + stardis-hfbound.h + stardis-hfbound-prog.h stardis-intface.h stardis-output.h stardis-parsing.h + stardis-program.h + stardis-prog-properties.h.in + stardis-sfconnect.h + stardis-sfconnect-prog.h + stardis-ssconnect.h + stardis-ssconnect-prog.h stardis-solid.h + stardis-solid-prog.h + stardis-tbound.h + stardis-tbound-prog.h stardis-version.h.in) set(SDIS_FILES_DOC COPYING README.md) diff --git a/cmake/doc/CMakeLists.txt b/cmake/doc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com) +# Copyright (C) 2018-2023 |Méso|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/cmake/stardis-green-types/CMakeLists.txt b/cmake/stardis-green-types/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2021 |Meso|Star> (contact@meso-star.com) +# Copyright (C) 2018-2023 |Méso|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/cmake/stardis-prog-properties/CMakeLists.txt b/cmake/stardis-prog-properties/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright (C) 2018-2023 |Méso|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_SPROG_DIR ${PROJECT_SOURCE_DIR}/../stardis-prog-properties) + +################################################################################ +# Copy stardis-prog-properties CMake files +################################################################################ +set(SPROG_NAMES + stardis-prog-properties-config) + +set(SPROG_FILES) +foreach(_name IN LISTS SPROG_NAMES) + set(_src ${STARDIS_SPROG_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 SPROG_FILES ${_dst}) +endforeach() +add_custom_target(stardis-prog-cmake ALL DEPENDS ${SPROG_FILES}) + +################################################################################ +# Install stardis-prog-properties CMake Files +################################################################################ +list(APPEND SPROG_FILES ${CMAKE_CURRENT_BINARY_DIR}/stardis-prog-properties-config-version.cmake) + +install(FILES ${SPROG_FILES} + DESTINATION lib/cmake/stardis-prog-properties) + +################################################################################ +# Install stardis-prog-properties header Files +################################################################################ +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/stardis-prog-properties.h + DESTINATION include/stardis/) diff --git a/doc/stardis-input.5.txt b/doc/stardis-input.5.txt @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 |Meso|Star> +// Copyright (C) 2018-2023 |Méso|Star> // // 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,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. +:sharp: # + :toc: stardis-input(5) @@ -28,40 +30,40 @@ DESCRIPTION thermal system. It relies on a line-based ad-hoc syntax. A thermal system is composed of lines of text, each one describing either a +program (an user-provided shared object), a medium (solid or fluid) frontier, a boundary (limit condition or connection -between two media), or the scale of the geometry. In the medium or boundary +between two media), the scale of the whole geometry, or the radiative +temperature around the system. In the medium or boundary cases, description lines include a list of file names that constitute the -limit or boundary. The current version of *stardis* only accepts triangle -mesh geometry files in *STL* format. If a scale is specified, it defines the +limit or boundary. The current version of *stardis(1)* only accepts triangle +mesh geometry files in *STL* format. If a scale is specified, it defines the scaling factor to apply to the geometry to have it expressed in meters (e.g. 1e-3 if the geometry is in mm). -A medium limit or a boundary description can be split accross files and a +A medium limit or a boundary description can be split across files and a single file or description line can describe more than one frontier (more than -one connex region). The main semantic constraint on descriptions is that any -enclosure must be defined by a single description line, to ensure that any -part in the system is made from a single medium. +one connex region). The main semantic constraint on descriptions is that +enclosures must be defined by a single description line, to ensure that every +constitutive part of the system is made from a single medium. Finally, description lines can be submitted to the *stardis*(1) program in -any order and can be split accross more than one file, through multiple use +any order, with the exception of programs that must be defined before use, +and can be split across more than one file, through multiple use of option *-M*. -UNITS ------ -Any physical quantity involved in descriptions is expected in the -International System of Units (second, metre, kilogram, kelvin, watt, joule); -the same applies to *stardis(1)* outputs as described in *stardis-output(5)*. - -However, the geometry provided to *stardis*(1) can be described in any unit, -multiple of meters or not, as long as the scaling factor is provided. - -TINIT VS TIMPOSED ------------------ -Media's descriptions, either solids or fluids, include two possible -temperatures: initial and imposed. If imposed temperature is set (that is not -"UNKNOWN"), initial temperature must be defined at the same value. As a -consequence, one cannot define a medium with an imposed temperature that -changes at t=0. +LINE SPLITTING +-------------- +When a description line is parsed, the first step is to split it in different +parts. *stardis(1)* relies on the wordexp POSIX library for this step. As a +consequence the very rules that apply at this stage all come from the wordexp +rules: environment variables can be used and are substituted, including inside +arithmetic expressions, text inside quote pairs is considered a single item, +whitespace characters can be escaped so that the current item continues past it +(see *wordexp(3)* for details). + +Note however that both the use of undefined environment variables and the use +of command substitution will be reported as an error as these features are not +enabled in *stardis(1)*. GRAMMAR ------- @@ -69,8 +71,8 @@ In what follows, some lines end in *\*. This is used as a convenience to continue a description next line. However, this trick cannot be used in actual description files and actual description lines must be kept single-line. Also, text appearing between quote marks has to be used verbatim in the input, -except the quote characters. Finally, text introduced by the *#* character in -descriptions, when not verbatim, is a comment and is not part of the +except the quote characters. Finally, text introduced by the *{sharp}* character +in descriptions, when not verbatim, is a comment and is not part of the description. [verse] @@ -80,118 +82,209 @@ _______ <description-lines> ::= <description-line> [ <description-lines> ] -<description-line> ::= [ <medium-frontier> ] [ <comment> ] +<description-line> ::= [ <program> ] [ <comment> ] + | [ <medium-frontier> ] [ <comment> ] | [ <medium-boundary> ] [ <comment> ] | [ <media-connection> ] [ <comment> ] - | [ <scaling-factor> ] [ <comment> ] # at most once - | [ <radiative-temps> ] [ <comment > ] # at most once + | [ <scaling-factor> ] [ <comment> ] {sharp} at most once + | [ <radiative-temps> ] [ <comment > ] {sharp} at most once ------------------------------------- -<medium-frontier> ::= <solid-frontier> - | <fluid-frontier> +<program> ::= "PROGRAM" <prog-name> <library-path> [ <lib-arguments> ] + +<medium-frontier> ::= <solid-frontier> + | <fluid-frontier> + | <prog-solid-frontier> + | <prog-fluid-frontier> + +<medium-boundary> ::= <t-bound-for-solid> + | <h-bound-for-solid> + | <h-bound-for-fluid> + | <f-bound-for-solid> + | <hf-bound-for-solid> + | <prog-t-bound-for-solid> + | <prog-h-bound-for-solid> + | <prog-h-bound-for-fluid> + | <prog-hf-bound-for-fluid> + | <prog-f-bound-for-solid> + +<media-connection> ::= <solid-fluid-connect> + | <solid-solid-connect> + | <prog-solid-fluid-connect> + | <prog-solid-solid-connect> + +<comment> ::= "{sharp}" Any text introduced by the {sharp} character + +<solid-frontier> ::= "SOLID" <medium-name> <lambda> <rho> <cp> <delta> \ + <initial-temperature> <imposed-temperature> \ + <volumic-power> <triangle-sides> + +<fluid-frontier> ::= "FLUID" <medium-name> <rho> <cp> \ + <initial-temperature> <imposed-temperature> \ + <triangle-sides> + +<t-bound-for-solid> ::= "T_BOUNDARY_FOR_SOLID" <bound-name> <temperature> \ + <triangles> + +<h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID" <bound-name> <Tref> <emissivity> \ + <specular-fraction> <hc> <outside-temperature> \ + <triangles> -<medium-boundary> ::= <t-bound-for-solid> - | <h-bound-for-solid> - | <h-bound-for-fluid> - | <f-bound-for-solid> +<hf-bound-for-solid> ::= "HF_BOUNDARY_FOR_SOLID" <bound-name> <Tref> <emissivity> \ + <specular-fraction> <hc> <outside-temperature> <flux> \ + <triangles> -<media-connection> ::= <solid-fluid-connect> - | <solid-solid-connect> +<h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID" <bound-name> <Tref> <emissivity> \ + <specular-fraction> <hc> <outside-temperature> \ + <triangles> -<comment> ::= "#" Any text introduced by the # character +<f-bound-for-solid> ::= "F_BOUNDARY_FOR_SOLID" <bound-name> <flux> <triangles> -<scaling_factor> ::= REAL # scaling factor to apply to the geometry - # in ]0 INF) +<solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION" <connect-name> <Tref>\ + <emissivity> <specular-fraction> <hc> <triangles> -<solid-frontier> ::= "SOLID" <medium-name> <lambda> <rho> <cp> <delta> \ - <initial-temperature> <imposed-temperature> \ - <volumic-power> <triangle-sides> +<solid-solid-connect> ::= "SOLID_SOLID_CONNECTION" <connect-name> \ + <contact-resistance> <triangles> -<fluid-frontier> ::= "FLUID" <medium-name> <rho> <cp> \ - <initial-temperature> <imposed-temperature> \ - <triangle-sides> +<prog-solid-frontier> ::= "SOLID_PROG" <medium-name> <prog-name> <triangle-sides> \ + [ "PROG_PARAMS" [ <desc-arguments> ] ] -<t-bound-for-solid> ::= "T_BOUNDARY_FOR_SOLID" <bound-name> <temperature> \ - <triangles> +<prog-fluid-frontier> ::= "FLUID_PROG" <medium-name> <prog-name> <triangle-sides> \ + [ "PROG_PARAMS" [ <desc-arguments> ] ] +<prog-t-bound-for-solid> ::= "T_BOUNDARY_FOR_SOLID_PROG" <bound-name> <prog-name> \ + <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID" <bound-name> <Tref> <emissivity> \ - <specular-fraction> <hc> <outside-temperature> \ - <triangles> +<prog-h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID_PROG" <bound-name> <prog-name> \ + <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID" <bound-name> <Tref> <emissivity> \ - <specular-fraction> <hc> <outside-temperature> \ - <triangles> +<prog-hf-bound-for-solid> ::= "HF_BOUNDARY_FOR_SOLID_PROG" <bound-name> <prog-name> \ + <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<f-bound-for-solid> ::= "F_BOUNDARY_FOR_SOLID" <bound-name> <flux> <triangles> +<prog-h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID_PROG" <bound-name> <prog-name> \ + <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION" <bound-name> <Tref> <emissivity> \ - <specular-fraction> <hc> <triangles> +<prog-f-bound-for-solid> ::= "F_BOUNDARY_FOR_SOLID_PROG" <bound-name> <prog-name> \ + <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<solid-solid-connect> ::= "SOLID_SOLID_CONNECTION" <bound-name> \ - <contact-resistance> <triangles> +<prog-solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION_PROG" <connect-name> \ + <prog-name> <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<scaling-factor> ::= "SCALE" <scaling_factor> [ <comment> ] +<prog-solid-solid-connect> ::= "SOLID_SOLID_CONNECTION_PROG" <connect-name> \ + <prog-name> <triangle-sides> [ "PROG_PARAMS" [ <desc-arguments> ] ] -<radiative-temps> ::= "TRAD" <radiative-temp> <radiative-temp-ref> +<scaling-factor> ::= "SCALE" <scale> [ <comment> ] + +<radiative-temps> ::= "TRAD" <radiative-temp> <radiative-temp-ref> ------------------------------------- -<medium-name> ::= STRING # no space allowed, must not be parsable as a - # number, including INF and others +<prog-name> ::= STRING {sharp} must not be a keyword nor a number, + {sharp} including INF and others + +<library-path> ::= FILEPATH {sharp} the path can be absolute + {sharp} or relative to the running directory and must be valid + +<lib-arguments> ::= STRING {sharp} if not empty, the whole string is send to the + {sharp} stardis_create_library_data() optional function + {sharp} it is an error to provide arguments to a program if + {sharp} the associated library doesn't define this function + {sharp} note that the {sharp} character consistently ends + {sharp} arguments by starting a comment -<lambda> ::= REAL # conductivity in W/(m.K); in ]0, INF) +<medium-name> ::= STRING {sharp} must not be a keyword nor a number, + {sharp} including INF and others -<rho> ::= REAL # volumic mass,in kg/m3; in ]0, INF) +<lambda> ::= REAL {sharp} conductivity in W/(m.K), in ]0, INF) -<cp> ::= REAL # capacity, in J/(kg.K) or kg.m2/(s2.K) - # in ]0, INF) +<rho> ::= REAL {sharp} volumic mass,in kg/m3, in ]0, INF) -<delta> ::= "AUTO" # delta is automatically set to V/6A (V and A - # being respectively the solid volume and its - # boundary area) - | REAL # delta*scaling_factor in m; in [0, INF) +<cp> ::= REAL {sharp} capacity, in J/(kg.K) or kg.m2/(s2.K) + {sharp} in ]0, INF) -<initial-temperature> ::= REAL # in K; in [0, INF) +<delta> ::= "AUTO" {sharp} delta is automatically set to V/6A (V and A + {sharp} being respectively the solid volume and its + {sharp} boundary area) + | REAL {sharp} delta*scaling_factor in m, in [0, INF) -<imposed-temperature> ::= "UNKNOWN" # temperature has to be solved - | REAL # in K; in [0, INF) +<initial-temperature> ::= REAL {sharp} in K, in [0, INF) -<outside-temperature> ::= REAL # in K; in [0, INF) +<imposed-temperature> ::= "UNKNOWN" {sharp} temperature has to be solved + | REAL {sharp} in K, in [0, INF) -<volumic-power> ::= REAL # in W/m3; in (-INF , INF) +<outside-temperature> ::= REAL {sharp} in K, in [0, INF) + +<volumic-power> ::= REAL {sharp} in W/m3, in (-INF , INF) <triangle-sides> ::= <side-specifier> <file-name> [ <triangle-sides> ] -<bound-name> ::= STRING # no space allowed +<bound-name> ::= STRING {sharp} must not be a keyword nor a number, + {sharp} including INF and others + +<connect-name> ::= STRING {sharp} must not be a keyword nor a number, + {sharp} including INF and others -<Tref> ::= REAL # in [0, inf) +<Tref> ::= REAL {sharp} in K, in [0, inf) -<emissivity> ::= REAL # in [0, 1] +<emissivity> ::= REAL {sharp} in [0, 1] -<specular-fraction> ::= REAL # in [0, 1] +<specular-fraction> ::= REAL {sharp} in [0, 1] -<hc> ::= REAL # in W/(m2.K); in [0, INF) +<hc> ::= REAL {sharp} in W/(m2.K), in [0, INF) -<contact-resistance> ::= REAL # in m2.K/W in [0, INF) +<contact-resistance> ::= REAL {sharp} in m2.K/W, in [0, INF) -<flux> ::= REAL # in W/m2; in (-INF , INF) +<flux> ::= REAL {sharp} in W/m2, in (-INF , INF) <triangles> ::= <file-name> [ <triangles> ] -<radiative-temp> ::= REAL # in [0, inf) +<scale> ::= REAL {sharp} scaling factor to apply to the geometry + {sharp} in ]0 INF) + +<desc-arguments> ::= STRING {sharp} the whole string is send to the stardis_create_data() + {sharp} function when the description is created + {sharp} note that the '{sharp}' character consistently ends + {sharp} arguments by starting a comment -<radiative-temp-ref> ::= REAL # in [0, inf) +<radiative-temp> ::= REAL {sharp} in K, in [0, inf) + +<radiative-temp-ref> ::= REAL {sharp} in K, in [0, inf) ------------------------------------- <side-specifier> ::= "FRONT" | "BACK" | "BOTH" -<file-name> ::= STRING # no space allowed +<file-name> ::= STRING ______________ +PROGRAMS +-------- +Programs are user-provided shared objects (compiled libraries). They allow to +provide *stardis(1)* with user defined properties. Depending on the type of +description they are used with, programs must export a given list of +mandatory functions. They can also export some other optional functions. +The exact list with names and types can be found in the stardis-prog.h public +header file that is installed at the same time as the *stardis(1)* binary. + +UNITS +----- +Any physical quantity involved in descriptions is expected in the +International System of Units (second, metre, kilogram, kelvin, watt, joule); +the same applies to *stardis(1)* outputs as described in *stardis-output(5)*. + +However, the geometry provided to *stardis*(1) can be described in any unit, +multiple of meters or not, as long as the scaling factor is provided. + +TINIT VS TIMPOSED +----------------- +Media's descriptions, either solids or fluids, include two possible +temperatures: initial and imposed. If imposed temperature is set (that is not +"UNKNOWN"), initial temperature must be defined at the same value. In other +words, one cannot define a medium with an imposed temperature that changes at +t=0. + TRIANGLE SIDES -------------- Side descriptions in side specifiers rely on the following convention: we @@ -202,34 +295,43 @@ used with the FRONT side specifier to describe inside medium. NAMES ----- -Names, either file names, medium names or boundary names, are a sequence of -one or ore ASCII characters, including numbers and special characters like -*.* *_* *-* as one may consider using in standard file names, *without any -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 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. Finally, description names cannot be longer than -63 characters. +Names, either file names or description names (program names, medium names or +boundary names), are a sequence of one or ore ASCII characters, including +numbers and special characters like *.* *_* *-* as one may consider using in +standard file names. Description +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. Additionally, description names cannot be parsable as a number, nor be one +of the keywords defined by the present grammar (AUTO, BACK, BOTH, FLUID, +FLUID_PROG, FRONT, F_BOUNDARY_FOR_SOLID, F_BOUNDARY_FOR_SOLID_PROG, +H_BOUNDARY_FOR_FLUID, H_BOUNDARY_FOR_FLUID_PROG, H_BOUNDARY_FOR_SOLID, +H_BOUNDARY_FOR_SOLID_PROG, PROGRAM, PROG_PARAMS, SCALE, SOLID, SOLID_PROG, +SOLID_FLUID_CONNECTION, SOLID_FLUID_CONNECTION_PROG, SOLID_SOLID_CONNECTION, +SOLID_SOLID_CONNECTION_PROG, TRAD, T_BOUNDARY_FOR_SOLID, +T_BOUNDARY_FOR_SOLID_PROG, UNKNOWN) or their lowercase counterparts. +Finally, description names cannot be longer than 63 characters. EXAMPLES -------- -Define a solid named Cube with a h boundary. The cube geometry is read from +Define a solid named *Cube 1*, a h boundary, and their radiative environment. +The cube geometry is read from 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, while the reference temperature for radiative -transfer linearization in the Picard algorithm is set to 300°K. -. +0.05. The initial temperature of the cube is 0°K, its temperature is unknown +(*stardis(1)* needs to solve it), and its volumic power is 2.5 W/m3. +The boundary properties are emissivity=0, specular-fraction=0, h=10 and +external-temperature = 100°K. +The cube radiative environment is at 300°K. +Finally, when the Picard method linearises radiative transfer involving the HdT +boundary, the reference temperature is set to 310°K, while it is set to 330°K +when linearisation involves the radiative environment. ....... -SOLID Cube 0.1 25 2 0.05 0 0 FRONT cube.stl -H_BOUNDARY_FOR_SOLID HdT 300 0 0 10 100 cube.stl +SOLID Cube\ 1 0.1 25 2 0.05 0 UNKNOWN 2.5 FRONT cube.stl +H_BOUNDARY_FOR_SOLID HdT 310 0 0 10 100 cube.stl +TRAD 300 330 ....... SEE ALSO -------- *stardis*(1) +*wordexp*(3) diff --git a/doc/stardis-output.5.txt b/doc/stardis-output.5.txt @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 |Meso|Star> +// Copyright (C) 2018-2023 |Méso|Star> // // 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 @@ -351,7 +351,7 @@ _______ <f-bound> ::= <green-id> <name> <flux> -<name> ::= STRING # no space allowed +<name> ::= STRING <lambda> ::= REAL # in ]0, INF) @@ -596,22 +596,25 @@ _______ | "4" # H_BOUNDARY_FOR_SOLID between 2 defined media | "5" # H_BOUNDARY_FOR_SOLID between 2 undefined media | "6" # H_BOUNDARY_FOR_SOLID enclosing a fluid - | "7" # T_BOUNDARY_FOR_SOLID between 2 defined media - | "8" # T_BOUNDARY_FOR_SOLID between 2 undefined media - | "9" # T_BOUNDARY_FOR_SOLID enclosing a fluid - | "10" # F_BOUNDARY_FOR_FLUID between 2 defined media - | "11" # F_BOUNDARY_FOR_FLUID between 2 undefined media - | "12" # F_BOUNDARY_FOR_SOLID enclosing a fluid - | "13" # SOLID_FLUID_CONNECTION between 2 solids - | "14" # SOLID_FLUID_CONNECTION between 2 fluids - | "15" # SOLID_FLUID_CONNECTION used as boundary - | "16" # SOLID_FLUID_CONNECTION between 2 undefined + | "7" # HF_BOUNDARY_FOR_SOLID between 2 defined media + | "8" # HF_BOUNDARY_FOR_SOLID between 2 undefined media + | "9" # HF_BOUNDARY_FOR_SOLID enclosing a fluid + | "10" # T_BOUNDARY_FOR_SOLID between 2 defined media + | "11" # T_BOUNDARY_FOR_SOLID between 2 undefined media + | "12" # T_BOUNDARY_FOR_SOLID enclosing a fluid + | "13" # F_BOUNDARY_FOR_FLUID between 2 defined media + | "14" # F_BOUNDARY_FOR_FLUID between 2 undefined media + | "15" # F_BOUNDARY_FOR_SOLID enclosing a fluid + | "16" # SOLID_FLUID_CONNECTION between 2 solids + | "17" # SOLID_FLUID_CONNECTION between 2 fluids + | "18" # SOLID_FLUID_CONNECTION used as boundary + | "19" # SOLID_FLUID_CONNECTION between 2 undefined # media - | "17" # no connexion between 2 fluids - | "18" # no connexion between a solid and a fluid - | "19" # no boundary around a fluid - | "20" # no boundary around a solid - | "21" # invalid part of a compute surface + | "20" # no connexion between 2 fluids + | "21" # no connexion between a solid and a fluid + | "22" # no boundary around a fluid + | "23" # no boundary around a solid + | "24" # invalid part of a compute surface <trg-prop-conflicts> # #triangles statuses <real3> ::= REAL REAL REAL @@ -827,9 +830,9 @@ _______ "LOOKUP_TABLE default" <path-failures> "POINT_DATA" #vertices - "SCALARS Vertex_Type unsigned_char 1" + "SCALARS Segment_Type unsigned_char 1" "LOOKUP_TABLE default" - <vertices-types> + <segments-types> "SCALARS Weight double 1" "LOOKUP_TABLE default" <weights> @@ -847,8 +850,8 @@ _______ <heat-strips> ::= <heat-strip> <heat-strips> # #strips strips -<vertices-types> ::= <vertice-type> - <vertices-types> # #vertices types +<segments-types> ::= <segment-type> + <segments-types> # #segments types <weights> ::= <weight> <weights> # #vertices weights @@ -869,7 +872,7 @@ _______ <heat-strip> ::= #strip_vertices <vtx_idx 1> ... <vtx_idx #strip_vertices> -<vertice-type> ::= "0" # CONDUCTION +<segment-type> ::= "0" # CONDUCTION | "1" # CONVECTION | "2" # RADIATIVE diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 |Meso|Star> +// Copyright (C) 2018-2023 |Méso|Star> // // 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 @@ -102,7 +102,9 @@ MANDATORY OPTIONS ----------------- *-M* _file_:: Read a text file containing a possibly partial description of the system. - Can include both media enclosures and boundary conditions, in any order. + Can include programs, media enclosures and boundary conditions. Media and + boundaries can appear in any order, but programs must be defined before their + first reference. Refer to *stardis-input(5)* for details. Can be used more than once if the description is split across different files. @@ -350,7 +352,7 @@ ends are written to the *probe_ends.csv* file: COPYRIGHT --------- -Copyright &copy; 2018-2020 |Meso|Star>. License GPLv3+: GNU GPL +Copyright &copy; 2018-2023 |Méso|Star>. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. This is free software. You are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -18,18 +18,22 @@ #endif #include "stardis-app.h" -#include "stardis-output.h" +#include "stardis-args.h" +#include "stardis-description.h" +#include "stardis-default.h" +#include "stardis-parsing.h" #include "stardis-compute.h" #include "stardis-intface.h" -#include "stardis-fluid.h" #include "stardis-solid.h" +#include "stardis-fluid.h" +#include "stardis-program.h" #include <star/senc3d.h> #include <star/sg3d_sencXd_helper.h> #include <star/sg3d_sdisXd_helper.h> #include <rsys/str.h> -#include <rsys/text_reader.h> +#include <rsys/library.h> #include <rsys/logger.h> #include <rsys/double2.h> #include <rsys/double3.h> @@ -47,64 +51,6 @@ static const struct counts COUNTS_NULL = COUNTS_NULL__; /******************************************************************************* * Local Functions ******************************************************************************/ -static res_T -read_model - (const struct darray_str* model_files, - struct stardis* stardis) -{ - res_T res = RES_OK; - const struct str* files = NULL; - size_t i; - FILE* f = NULL; - struct txtrdr* txtrdr = NULL; - - 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); - f = fopen(name, "r"); - if(!f) { - logger_print(stardis->logger, LOG_ERROR, - "Cannot open model file '%s'\n", - name); - res = RES_IO_ERR; - goto error; - } - txtrdr_stream(stardis->allocator, f, name, '#', &txtrdr); - for(;;) { - char* line; - ERR(txtrdr_read_line(txtrdr)); - line = txtrdr_get_line(txtrdr); - if(!line) break; - ERR(process_model_line(name, line, stardis)); - } - txtrdr_ref_put(txtrdr); - txtrdr = NULL; - fclose(f); - f = NULL; - } - if(stardis->scale_factor <= 0) - 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: - return res; -error: - if(f) fclose(f); - if(txtrdr) txtrdr_ref_put(txtrdr); - goto exit; -} - static struct sdis_interface* geometry_get_interface (const size_t itri, void* ctx) @@ -135,6 +81,7 @@ check_delta_and_create_solid /* Due to previous errors, senc3d_scn can be unavailable */ unsigned e, ecount = 0; const unsigned desc_id = solid->desc_id; + double solid_volume = 0; /* The enclosures where created using description ids */ ERR(senc3d_scene_get_enclosure_count_by_medium(stardis->senc3d_scn, @@ -150,6 +97,7 @@ check_delta_and_create_solid ERR(senc3d_scene_get_enclosure_by_medium(stardis->senc3d_scn, desc_id, e, &enc)); ERR(senc3d_enclosure_get_header(enc, &header)); + solid_volume += header.volume; if(header.is_infinite) { /* External solid, volume is negative and no delta walk expected */ external = 1; @@ -190,6 +138,12 @@ check_delta_and_create_solid solid->delta, delta_range[0]); } } + /* Print power */ + if(solid->vpower != SDIS_VOLUMIC_POWER_NONE && solid->vpower != 0) { + logger_print(stardis->logger, LOG_OUTPUT, + "Power of the Solid '%s': %g W\n", + str_cget(&solid->name), solid_volume * solid->vpower); + } } } } @@ -271,7 +225,7 @@ stardis_init struct str str; unsigned i, vcount, tcount, ocount, count; int is_for_compute; - struct sdis_device_create_args dev_args; + struct sdis_device_create_args dev_args = SDIS_DEVICE_CREATE_ARGS_DEFAULT; ASSERT(args && logger && allocator && stardis); @@ -372,6 +326,9 @@ stardis_init ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount)); ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount)); + logger_print(stardis->logger, LOG_OUTPUT, + "Read %u unique triangles.\n", tcount); + ERR(sg3d_geometry_validate_properties(stardis->geometry.sg3d, validate_properties, stardis)); ERR(sg3d_geometry_get_unique_triangles_with_properties_conflict_count( @@ -428,17 +385,26 @@ stardis_init } } - /* Create solids and log model information */ + /* Create solids, finalize program data, and log model information */ for(i = 0; i < darray_descriptions_size_get(&stardis->descriptions); i++) { struct description* desc = darray_descriptions_data_get(&stardis->descriptions) + i; if(desc->type == DESC_MAT_SOLID) { tmp_res = check_delta_and_create_solid(stardis, desc); - if(tmp_res != RES_OK && is_for_compute) { - res = tmp_res; - goto error; + } else if(desc->type == DESC_PROGRAM && desc->d.program->finalize) { + enum stardis_return_status rs; + rs = desc->d.program->finalize(desc->d.program->prog_data); + switch(rs) { + case STARDIS_SUCCESS: tmp_res = RES_OK; break; + case STARDIS_FAILURE: tmp_res = RES_BAD_ARG; break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } } + if(tmp_res != RES_OK && is_for_compute) { + res = tmp_res; + goto error; + } ERR(str_print_description(&str, i, desc)); logger_print(stardis->logger, LOG_OUTPUT, "%s\n", str_cget(&str)); } @@ -523,8 +489,16 @@ stardis_release str_release(&stardis->bin_green_filename); str_release(&stardis->end_paths_filename); str_release(&stardis->chunks_prefix); + /* release non-PROGRAM descritions first */ FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) { struct description* d = darray_descriptions_data_get(&stardis->descriptions) +i; + if(d->type == DESC_PROGRAM) continue; + release_description(d, stardis->allocator); + } + /* release PROGRAM descritions */ + FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) { + struct description* d = darray_descriptions_data_get(&stardis->descriptions) +i; + if(d->type != DESC_PROGRAM) continue; release_description(d, stardis->allocator); } darray_descriptions_release(&stardis->descriptions); @@ -547,6 +521,14 @@ stardis_release } } +unsigned +allocate_stardis_medium_id + (struct stardis* stardis) +{ + ASSERT(stardis); + return stardis->next_medium_id++; +} + res_T init_enclosures (struct stardis* stardis) @@ -556,6 +538,7 @@ init_enclosures struct senc3d_device* senc_dev = NULL; ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tsz)); + ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vsz)); ERR(senc3d_device_create(stardis->logger, stardis->allocator, stardis->nthreads, stardis->verbose, &senc_dev)); @@ -577,9 +560,9 @@ error: if(properties[(Rank)] == SG3D_UNSPECIFIED_PROPERTY) undef_count++;\ else {\ ASSERT(properties[(Rank)] < darray_descriptions_size_get(&stardis->descriptions));\ - ASSERT(DESC_IS_MEDIUM(descs[properties[(Rank)]].type));\ - if(descs[properties[(Rank)]].type == DESC_MAT_SOLID) solid_count++;\ - else fluid_count++;\ + ASSERT(DESC_IS_MEDIUM(descs+properties[(Rank)]));\ + if(DESC_IS_SOLID(descs+properties[(Rank)])) { solid_count++; }\ + else { ASSERT(DESC_IS_FLUID(descs+properties[(Rank)])); fluid_count++; }\ }\ } @@ -616,6 +599,7 @@ validate_properties intface = descs + properties[SG3D_INTFACE]; switch (intface->type) { case DESC_BOUND_H_FOR_FLUID: + case DESC_BOUND_H_FOR_FLUID_PROG: if(!(solid_count == 0 && fluid_count == 1)) { if(solid_count + fluid_count == 2) *properties_conflict_status = BOUND_H_FOR_FLUID_BETWEEN_2_DEFS; @@ -628,6 +612,7 @@ validate_properties } break; case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_SOLID_PROG: if(!(solid_count == 1 && fluid_count == 0)) { if(solid_count + fluid_count == 2) *properties_conflict_status = BOUND_H_FOR_SOLID_BETWEEN_2_DEFS; @@ -639,7 +624,21 @@ validate_properties goto end; } break; + case DESC_BOUND_HF_FOR_SOLID: + case DESC_BOUND_HF_FOR_SOLID_PROG: + if(!(solid_count == 1 && fluid_count == 0)) { + if(solid_count + fluid_count == 2) + *properties_conflict_status = BOUND_HF_FOR_SOLID_BETWEEN_2_DEFS; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = BOUND_HF_FOR_SOLID_BETWEEN_2_UNDEFS; + else if(fluid_count == 1) + *properties_conflict_status = BOUND_HF_FOR_SOLID_ENCLOSING_FLUID; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_SOLID_PROG: if(!(solid_count == 1 && fluid_count == 0)) { if(solid_count + fluid_count == 2) *properties_conflict_status = BOUND_T_FOR_SOLID_BETWEEN_2_DEFS; @@ -652,6 +651,7 @@ validate_properties } break; case DESC_BOUND_F_FOR_SOLID: + case DESC_BOUND_F_FOR_SOLID_PROG: if(!(solid_count == 1 && fluid_count == 0)) { if(solid_count + fluid_count == 2) *properties_conflict_status = BOUND_F_FOR_SOLID_BETWEEN_2_DEFS; @@ -664,6 +664,7 @@ validate_properties } break; case DESC_SOLID_FLUID_CONNECT: + case DESC_SOLID_FLUID_CONNECT_PROG: if(solid_count != 1 || fluid_count != 1) { if(solid_count == 2) *properties_conflict_status = SFCONNECT_BETWEEN_2_SOLIDS; @@ -678,6 +679,7 @@ validate_properties } break; case DESC_SOLID_SOLID_CONNECT: + case DESC_SOLID_SOLID_CONNECT_PROG: if(solid_count != 2) { /*if(soli_count == 1 && fluid_count == 1)*/ /**properties_conflict_status = SSCONNECT_BETWEEN_SOLID_AND_FLUID;*/ @@ -718,3 +720,145 @@ end: } #undef COUNT_SIDE + +res_T +init_geometry + (struct logger* logger, + struct mem_allocator* allocator, + const int verbose, + struct geometry* geom) +{ + res_T res = RES_OK; + struct sg3d_device* sg3d_dev = NULL; + + ASSERT(allocator && geom); + + geom->sg3d = NULL; + darray_interface_ptrs_init(allocator, &geom->interfaces); + darray_interface_ptrs_init(allocator, &geom->interf_bytrg); + ERR(sg3d_device_create(logger, allocator, verbose, &sg3d_dev)); + ERR(sg3d_geometry_create(sg3d_dev, &geom->sg3d)); + +exit: + if(sg3d_dev) SG3D(device_ref_put(sg3d_dev)); + return res; +error: + release_geometry(geom); + goto exit; +} + +void +release_geometry + (struct geometry* geom) +{ + size_t i; + struct sdis_interface + ** intf = darray_interface_ptrs_data_get(&geom->interfaces); + if(geom->sg3d) SG3D(geometry_ref_put(geom->sg3d)); + for(i = 0; i < darray_interface_ptrs_size_get(&geom->interfaces); ++i) + SDIS(interface_ref_put(intf[i])); + darray_interface_ptrs_release(&geom->interfaces); + darray_interface_ptrs_release(&geom->interf_bytrg); +} + +void +init_camera + (struct mem_allocator* alloc, struct camera* cam) +{ + ASSERT(alloc && cam); + d3(cam->pos, STARDIS_DEFAULT_RENDERING_POS); + d3(cam->tgt, STARDIS_DEFAULT_RENDERING_TGT); + d3(cam->up, STARDIS_DEFAULT_RENDERING_UP); + cam->fmt = STARDIS_DEFAULT_RENDERING_OUTPUT_FILE_FMT; + cam->fov = STARDIS_DEFAULT_RENDERING_FOV; + cam->spp = STARDIS_DEFAULT_RENDERING_SPP; + cam->img_width = STARDIS_DEFAULT_RENDERING_IMG_WIDTH; + cam->img_height = STARDIS_DEFAULT_RENDERING_IMG_HEIGHT; + d2(cam->time_range, STARDIS_DEFAULT_RENDERING_TIME); + cam->auto_look_at = 1; + str_init(alloc, &cam->file_name); +} + +void +release_camera + (struct camera* cam) +{ + ASSERT(cam); + str_release(&cam->file_name); +} + +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 + fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg); +#endif +} + +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 + fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg); +#endif +} + +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 + fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg); +#endif +} + diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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,28 +16,20 @@ #ifndef STARDIS_APP_H #define STARDIS_APP_H -#include "stardis-args.h" -#include "stardis-parsing.h" -#include "stardis-default.h" -#include "stardis-solid.h" -#include "stardis-fluid.h" +#include "stardis-description.h" -#include <star/sstl.h> #include <star/sg3d.h> #include <rsys/rsys.h> -#include <rsys/float3.h> #include <rsys/double2.h> #include <rsys/double3.h> #include <rsys/dynamic_array_size_t.h> +#include <rsys/dynamic_array_uint.h> #include <rsys/dynamic_array.h> #include <rsys/str.h> #include <sdis.h> -#include <limits.h> -#include <stdarg.h> - #ifdef STARDIS_ENABLE_MPI #include <mpi.h> #endif @@ -47,30 +39,23 @@ struct logger; struct mem_allocator; struct sdis_medium; +struct args; +struct solid; +struct fluid; + /* Utility macros */ #define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0 -#define STR_APPEND_PRINTF(Accum, Fmt, Args) \ -{ \ - struct str tmp; \ - str_init((Accum)->allocator, &tmp); \ - res = str_printf(&tmp, Fmt COMMA_##Args LIST_##Args); \ - if(res == RES_OK) res = str_append((Accum), str_cget(&tmp)); \ - str_release(&tmp); \ - if(res != RES_OK) goto error; \ -} (void)0 - - -#define VFATAL(Fmt, Args) \ - { \ - fprintf(stderr, Fmt COMMA_##Args LIST_##Args); \ - ASSERT(0); \ - abort(); \ +#define VFATAL(Fmt, Args) \ + { \ + fprintf(stderr, Fmt COMMA_##Args LIST_##Args); \ + ASSERT(0); \ + abort(); \ } (void)0 #define DELTA_AUTO INF /* Placeholder until actual value is substituted */ -#define UNKNOWN_MEDIUM_TEMPERATURE -1 /* Unknown for stadis solver is -1 */ +#define UNKNOWN_MEDIUM_TEMPERATURE -1 /* Unknown for stardis solver is -1 */ enum properties_conflict_t { NO_PROPERTY_CONFLICT, @@ -80,6 +65,9 @@ enum properties_conflict_t { BOUND_H_FOR_SOLID_BETWEEN_2_DEFS, BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS, BOUND_H_FOR_SOLID_ENCLOSING_FLUID, + BOUND_HF_FOR_SOLID_BETWEEN_2_DEFS, + BOUND_HF_FOR_SOLID_BETWEEN_2_UNDEFS, + BOUND_HF_FOR_SOLID_ENCLOSING_FLUID, BOUND_T_FOR_SOLID_BETWEEN_2_DEFS, BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS, BOUND_T_FOR_SOLID_ENCLOSING_FLUID, @@ -98,31 +86,6 @@ enum properties_conflict_t { PROPERTIES_CONFLICT_COUNT__ }; -/* Different types of descriptions */ -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, - DESC_SOLID_SOLID_CONNECT, - DESCRIPTION_TYPE_COUNT__, - DESC_OUTSIDE -}; - -#define DESC_IS_H(D) \ - ((D) == DESC_BOUND_H_FOR_SOLID || (D) == DESC_BOUND_H_FOR_FLUID) -#define DESC_IS_T(D) \ - ((D) == DESC_BOUND_T_FOR_SOLID) -#define DESC_IS_F(D) \ - ((D) == DESC_BOUND_F_FOR_SOLID) -#define DESC_IS_MEDIUM(D) \ - ((D) == DESC_MAT_SOLID || (D) == DESC_MAT_FLUID) -#define DESC_IS_BOUNDARY(D) \ - (DESC_IS_H(D) || DESC_IS_T(D) || DESC_IS_F(D)) - #define DARRAY_NAME interface_ptrs #define DARRAY_DATA struct sdis_interface* #include <rsys/dynamic_array.h> @@ -160,518 +123,18 @@ struct geometry { struct darray_interface_ptrs interfaces; }; -static INLINE void -release_geometry(struct geometry* geom) -{ - size_t i; - struct sdis_interface - ** intf = darray_interface_ptrs_data_get(&geom->interfaces); - if(geom->sg3d) SG3D(geometry_ref_put(geom->sg3d)); - for(i = 0; i < darray_interface_ptrs_size_get(&geom->interfaces); ++i) - SDIS(interface_ref_put(intf[i])); - darray_interface_ptrs_release(&geom->interfaces); - darray_interface_ptrs_release(&geom->interf_bytrg); -} +void +release_geometry + (struct geometry* geom); -static INLINE res_T +res_T init_geometry (struct logger* logger, struct mem_allocator* allocator, const int verbose, - struct geometry* geom) -{ - res_T res = RES_OK; - struct sg3d_device* sg3d_dev = NULL; - - ASSERT(allocator && geom); - - geom->sg3d = NULL; - darray_interface_ptrs_init(allocator, &geom->interfaces); - darray_interface_ptrs_init(allocator, &geom->interf_bytrg); - ERR(sg3d_device_create(logger, allocator, verbose, &sg3d_dev)); - ERR(sg3d_geometry_create(sg3d_dev, &geom->sg3d)); - -exit: - if(sg3d_dev) SG3D(device_ref_put(sg3d_dev)); - return res; -error: - release_geometry(geom); - goto exit; -} - -/******************************************************************************/ - -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 geometry* geom); /******************************************************************************/ - -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 res_T -init_h - (struct mem_allocator* allocator, - struct h_boundary** dst) -{ - 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, - 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 -str_print_h_boundary - (struct str* str, - const struct h_boundary* b, - const enum description_type type) -{ - res_T res = RES_OK; - ASSERT(str && b && DESC_IS_H(type)); - STR_APPEND_PRINTF(str, - "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; -} - -struct t_boundary { - struct str name; - double imposed_temperature; - unsigned mat_id; -}; - -static FINLINE res_T -init_t - (struct mem_allocator* allocator, - struct t_boundary** dst) -{ - 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, - struct mem_allocator* allocator) -{ - ASSERT(bound && allocator); - str_release(&bound->name); - MEM_RM(allocator, bound); -} - -static res_T -str_print_t_boundary - (struct str* str, - const struct t_boundary* b) -{ - res_T res = RES_OK; - ASSERT(str && b); - STR_APPEND_PRINTF(str, "T boundary for solid '%s': T=%g ", - ARG2( str_cget(&b->name), b->imposed_temperature ) ); - - STR_APPEND_PRINTF(str, "(using medium %u as external medium)", - ARG1( b->mat_id ) ); -end: - return res; -error: - goto end; -} - -struct f_boundary { - struct str name; - double imposed_flux; - unsigned mat_id; -}; - -static FINLINE res_T -init_f - (struct mem_allocator* allocator, - struct f_boundary** dst) -{ - 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, - struct mem_allocator* allocator) -{ - ASSERT(bound && allocator); - str_release(&bound->name); - MEM_RM(allocator, bound); -} - -static res_T -str_print_f_boundary - (struct str* str, - const struct f_boundary* b) -{ - res_T res = RES_OK; - ASSERT(str && b); - STR_APPEND_PRINTF(str, - "F boundary for SOLID '%s': flux=%g (using medium %u as external medium)", - ARG3( str_cget(&b->name), b->imposed_flux, b->mat_id ) ); -end: - return res; -error: - goto end; -} - -struct solid_fluid_connect { - struct str name; - double ref_temperature; - double emissivity; - double specular_fraction; - double hc; - unsigned connection_id; -}; - -static FINLINE void -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 res_T -init_sf - (struct mem_allocator* allocator, - struct solid_fluid_connect** dst) -{ - 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 -str_print_sf_connect - (struct str* str, - const struct solid_fluid_connect* c) -{ - 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, "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; -} - -struct solid_solid_connect { - struct str name; - double tcr; - unsigned connection_id; -}; - -static FINLINE void -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 res_T -init_ss - (struct mem_allocator* allocator, - struct solid_solid_connect** dst) -{ - 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 -str_print_ss_connect - (struct str* str, - const struct solid_solid_connect* c) -{ - 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 ) ); -end: - return res; -error: - goto end; -} - -static FINLINE res_T -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, - struct mem_allocator* allocator) -{ - ASSERT(desc && allocator); - switch (desc->type) { - case DESC_MAT_SOLID: - release_solid(desc->d.solid, allocator); - break; - case DESC_MAT_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, allocator); - break; - case DESC_BOUND_T_FOR_SOLID: - release_t_boundary(desc->d.t_boundary, allocator); - break; - case DESC_BOUND_F_FOR_SOLID: - release_f_boundary(desc->d.f_boundary, allocator); - break; - case DESC_SOLID_FLUID_CONNECT: - release_sf_connect(desc->d.sf_connect, allocator); - break; - case DESC_SOLID_SOLID_CONNECT: - release_ss_connect(desc->d.ss_connect, allocator); - break; - default: - FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); - } -} - -static INLINE res_T -str_print_description - (struct str* str, - const unsigned rank, - const struct description* desc) -{ - res_T res = RES_OK; - ASSERT(str && desc); - str_clear(str); - ERR(str_printf(str, "Description %u: ", rank)); - switch (desc->type) { - case DESC_MAT_SOLID: - ERR(str_print_solid(str, desc->d.solid)); - break; - case DESC_MAT_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)); - 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)); - break; - case DESC_BOUND_F_FOR_SOLID: - 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)); - break; - case DESC_SOLID_SOLID_CONNECT: - ERR(str_print_ss_connect(str, desc->d.ss_connect)); - break; - default: - FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); - } -end: - return res; -error: - goto end; -} - -static INLINE const struct str* -get_description_name - (const struct description* desc) -{ - ASSERT(desc); - switch (desc->type) { - case DESC_MAT_SOLID: - return &desc->d.solid->name; - case DESC_MAT_FLUID: - return &desc->d.fluid->name; - case DESC_BOUND_T_FOR_SOLID: - return &desc->d.t_boundary->name; - case DESC_BOUND_H_FOR_SOLID: - case DESC_BOUND_H_FOR_FLUID: - return &desc->d.h_boundary->name; - case DESC_BOUND_F_FOR_SOLID: - return &desc->d.f_boundary->name; - case DESC_SOLID_FLUID_CONNECT: - return &desc->d.sf_connect->name; - case DESC_SOLID_SOLID_CONNECT: - return &desc->d.ss_connect->name; - default: - FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); - } -} - -static FINLINE void -description_get_medium_id - (const struct description* desc, - unsigned* id) -{ - ASSERT(desc && id); - switch (desc->type) { - case DESC_MAT_SOLID: - *id = desc->d.solid->solid_id; - return; - case DESC_MAT_FLUID: - *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; - return; - case DESC_BOUND_T_FOR_SOLID: - *id = desc->d.t_boundary->mat_id; - return; - case DESC_BOUND_F_FOR_SOLID: - *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 */ - default: - FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); - } -} - enum stardis_output_fmt { STARDIS_RENDERING_OUTPUT_FILE_FMT_VTK, STARDIS_RENDERING_OUTPUT_FILE_FMT_HT @@ -690,99 +153,22 @@ struct camera { struct str file_name; }; -static INLINE void -init_camera(struct mem_allocator* alloc, struct camera* cam) { - ASSERT(alloc && cam); - d3(cam->pos, STARDIS_DEFAULT_RENDERING_POS); - d3(cam->tgt, STARDIS_DEFAULT_RENDERING_TGT); - d3(cam->up, STARDIS_DEFAULT_RENDERING_UP); - cam->fmt = STARDIS_DEFAULT_RENDERING_OUTPUT_FILE_FMT; - cam->fov = STARDIS_DEFAULT_RENDERING_FOV; - cam->spp = STARDIS_DEFAULT_RENDERING_SPP; - cam->img_width = STARDIS_DEFAULT_RENDERING_IMG_WIDTH; - cam->img_height = STARDIS_DEFAULT_RENDERING_IMG_HEIGHT; - d2(cam->time_range, STARDIS_DEFAULT_RENDERING_TIME); - cam->auto_look_at = 1; - str_init(alloc, &cam->file_name); -} - -static INLINE void -release_camera(struct camera* cam) { - ASSERT(cam); - str_release(&cam->file_name); -} - -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 - fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg); -#endif -} - -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 - fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg); -#endif -} +void +init_camera + (struct mem_allocator* alloc, struct camera* cam); -static INLINE void -log_prt_fn(const char* msg, void* ctx) -{ -#ifdef STARDIS_ENABLE_MPI - int initialized, rank = 0; -#endif +/******************************************************************************/ +void +release_camera(struct camera* cam); - ASSERT(msg); - (void)ctx; +void +log_err_fn(const char* 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 +void +log_warn_fn(const char* msg, void* ctx); -#ifdef OS_WINDOWS - fprintf(stderr, "message: %s", msg); -#else - fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg); -#endif -} +void +log_prt_fn(const char* msg, void* ctx); struct counts { unsigned smed_count, fmed_count, tbound_count, hbound_count, @@ -853,12 +239,9 @@ struct stardis { int mpi_rank; }; -static INLINE unsigned -allocate_stardis_medium_id(struct stardis* stardis) -{ - ASSERT(stardis); - return stardis->next_medium_id++; -} +unsigned +allocate_stardis_medium_id + (struct stardis* stardis); #ifdef STARDIS_ENABLE_MPI extern LOCAL_SYM res_T @@ -872,22 +255,22 @@ extern LOCAL_SYM void finalize_mpi(void); #endif -extern LOCAL_SYM res_T +res_T stardis_init (const struct args* args, struct logger* logger, struct mem_allocator* allocator, struct stardis* stardis); -extern LOCAL_SYM void +void stardis_release (struct stardis* stardis); -extern LOCAL_SYM res_T +res_T init_enclosures (struct stardis* stardis); -extern LOCAL_SYM res_T +res_T validate_properties (const unsigned itri, const unsigned properties[SG3D_PROP_TYPES_COUNT__], diff --git a/src/stardis-args.c b/src/stardis-args.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -14,6 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #define _POSIX_C_SOURCE 200809L /* strdup */ +#include "stardis-args.h" #include "stardis-parsing.h" #include "stardis-app.h" #include "stardis-default.h" @@ -323,7 +324,7 @@ short_help 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" +"\nCopyright (C) 2018-2023 |Méso|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"); diff --git a/src/stardis-args.h b/src/stardis-args.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -25,7 +25,6 @@ struct camera; struct logger; struct mem_allocator; struct stardis; -struct dummies; enum stardis_mode { /* Ordered so that print_multiple_modes() prints in alphabetical order */ @@ -106,33 +105,33 @@ struct args { int verbose; }; -extern LOCAL_SYM res_T +res_T init_args (struct logger* logger, struct mem_allocator* mem, struct args** args); -extern LOCAL_SYM void +void release_args (struct args* args); -extern void +void print_version (FILE* stream); -extern void +void short_help (FILE* stream, const char* prog); -extern res_T +res_T parse_args (const int argc, char** argv, struct args* args, struct mem_allocator* allocator); -extern res_T +res_T parse_camera (struct logger* logger, char* cam_param, diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -14,10 +14,18 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "stardis-app.h" +#include "stardis-args.h" +#include "stardis-description.h" #include "stardis-output.h" #include "stardis-compute.h" +#include "stardis-parsing.h" +#include "stardis-default.h" #include "stardis-fluid.h" +#include "stardis-fluid-prog.h" #include "stardis-solid.h" +#include "stardis-solid-prog.h" +#include "stardis-sfconnect.h" +#include "stardis-ssconnect.h" #include <sdis.h> #include <sdis_version.h> @@ -40,7 +48,7 @@ #endif /******************************************************************************* - * Local Functions + * Local type; custom data for raytracing callbacks ******************************************************************************/ struct filter_ctx { const struct stardis* stardis; @@ -55,6 +63,10 @@ struct filter_ctx { #define FILTER_CTX_DEFAULT__ \ { NULL, S3D_INVALID_ID, NULL, { 0, 0, 0 }, FLT_MAX, 0, 0 } +/******************************************************************************* + * Local Functions + ******************************************************************************/ + /* Filter used from a point query to determine not only one of the closest * point, but the better one if there are more than one. In some circumstances * it is not possible to determine the medium we are in using a given hit, but @@ -182,6 +194,7 @@ check_probe_conform_to_type (const struct stardis* stardis, const int move2boundary, double pos[3], + double time, unsigned* iprim, double uv[2]) { @@ -245,36 +258,60 @@ check_probe_conform_to_type logger_print(stardis->logger, LOG_WARNING, "Could not determine the medium probe is in.\n"); } else { - if(filter_ctx.desc->type == DESC_MAT_SOLID) { - struct solid* solid = filter_ctx.desc->d.solid; - ASSERT(solid->delta < INF); + if(DESC_IS_SOLID(filter_ctx.desc)) { + double delta; + const char* pppp; + if(filter_ctx.desc->type == DESC_MAT_SOLID) { + struct solid* solid = filter_ctx.desc->d.solid; + delta = solid->delta; + pppp = ""; + } else { + struct solid_prog* solid_prog = filter_ctx.desc->d.solid_prog; + struct stardis_vertex vtx; + ASSERT(filter_ctx.desc->type == DESC_MAT_SOLID_PROG); + d3_set(vtx.P, pos); + vtx.time = time; + delta = solid_prog->delta(&vtx, solid_prog->prog_data); + pppp = "programmed "; + } + ASSERT(delta < INF); logger_print(stardis->logger, LOG_OUTPUT, - "Probe was in solid '%s'.\n", str_cget(&solid->name)); - if(filter_ctx.dist > 2 * solid->delta) { + "Probe was in %ssolid '%s'.\n", + pppp, str_cget(get_description_name(filter_ctx.desc))); + if(filter_ctx.dist > 2 * 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 / solid->delta); + filter_ctx.dist / delta); res = RES_BAD_ARG; goto error; } - if(filter_ctx.dist > 0.5 * solid->delta) { + if(filter_ctx.dist > 0.5 * delta) { logger_print(stardis->logger, LOG_WARNING, "Probe was %g delta from closest boundary. " "Consider using -p instead of -P.\n", - filter_ctx.dist / solid->delta); + filter_ctx.dist / delta); } else { if(filter_ctx.dist != 0) logger_print(stardis->logger, LOG_OUTPUT, "Probe was %g delta from closest boundary.\n", - filter_ctx.dist / solid->delta); + filter_ctx.dist / delta); } } else { + const char* pppp; + ASSERT(DESC_IS_FLUID(filter_ctx.desc)); /* TODO: check move length wrt local geometry? */ + if(filter_ctx.desc->type == DESC_MAT_FLUID) { + pppp = ""; + } else { + ASSERT(filter_ctx.desc->type == DESC_MAT_FLUID_PROG); + pppp = "programmed "; + } logger_print(stardis->logger, LOG_OUTPUT, - "Probe was in fluid '%s'.\n", str_cget(&filter_ctx.desc->d.fluid->name)); + "Probe was in %sfluid '%s'.\n", + pppp, str_cget(get_description_name(filter_ctx.desc))); logger_print(stardis->logger, LOG_OUTPUT, "Probe distance from closest boundary was %g.\n", filter_ctx.dist); } @@ -328,36 +365,54 @@ check_probe_conform_to_type res = RES_BAD_ARG; goto error; } - logger_print(stardis->logger, LOG_OUTPUT, - "Probe is in solid '%s'.\n", str_cget(&filter_ctx.desc->d.solid->name)); - if(filter_ctx.desc->type == DESC_MAT_SOLID) { - struct solid* solid = filter_ctx.desc->d.solid; - if(filter_ctx.dist < 0.25 * solid->delta) { + if(DESC_IS_SOLID(filter_ctx.desc)) { + double delta; + if(filter_ctx.desc->type == DESC_MAT_SOLID) { + struct solid* solid = filter_ctx.desc->d.solid; + delta = solid->delta; + } else { + struct solid_prog* solid_prog = filter_ctx.desc->d.solid_prog; + struct stardis_vertex vtx; + ASSERT(filter_ctx.desc->type == DESC_MAT_SOLID_PROG); + d3_set(vtx.P, pos); + vtx.time = time; + delta = solid_prog->delta(&vtx, solid_prog->prog_data); + } + if(filter_ctx.dist < 0.25 * delta) { logger_print(stardis->logger, LOG_ERROR, "Probe is %g delta from closest boundary. Use -P instead of -p.\n", - filter_ctx.dist / solid->delta); + filter_ctx.dist / 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 * solid->delta) { + if(filter_ctx.dist < 0.5 * delta) { logger_print(stardis->logger, LOG_WARNING, "Probe is %g delta from closest boundary. " "Consider using -P instead of -p.\n", - filter_ctx.dist / solid->delta); + filter_ctx.dist / delta); } else { logger_print(stardis->logger, LOG_OUTPUT, "Probe is %g delta from closest boundary.\n", - filter_ctx.dist / solid->delta); + filter_ctx.dist / 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)); + ASSERT(DESC_IS_FLUID(filter_ctx.desc)); /* In fluid; TODO: check distance wrt local geometry (use 4V/S?) */ + if(filter_ctx.desc->type == DESC_MAT_FLUID) { + 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)); + } else { + ASSERT(filter_ctx.desc->type == DESC_MAT_FLUID_PROG); + logger_print(stardis->logger, LOG_WARNING, + "Probe is in fluid_prog '%s': computing fluid temperature, " + "not using a specific position.\n", + str_cget(&filter_ctx.desc->d.fluid_prog->name)); + } } } @@ -381,23 +436,23 @@ error: args.rng_type = SSP_RNG_THREEFRY; \ } else { \ const char* name = str_cget(Name); \ - stream = fopen(name, "r"); \ - if(!stream) { \ + stream_r = fopen(name, "r"); \ + if(!stream_r) { \ res = RES_IO_ERR; \ logger_print(stardis->logger, LOG_ERROR, \ - "Could not open generator's state file ('%s').\n", \ + "Cannot 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); \ + res = read_random_generator_state(args.rng_state, stream_r); \ if(res != RES_OK) { \ logger_print(stardis->logger, LOG_ERROR, \ - "Could not read random generator's state ('%s').\n", \ + "Cannot read random generator's state ('%s').\n", \ name); \ goto error; \ } \ - fclose(stream); stream = NULL; \ + fclose(stream_r); stream_r = NULL; \ } \ } @@ -405,16 +460,16 @@ 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) { \ + stream_r = fopen(name, "wb"); \ + if(!stream_r) { \ res = RES_IO_ERR; \ logger_print(stardis->logger, LOG_ERROR, \ - "Could not write random generator's state ('%s').\n", \ + "Cannot 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_r)); \ + fclose(stream_r); stream_r = NULL; \ } \ } @@ -428,12 +483,15 @@ compute_probe(struct stardis* stardis, struct time* start) struct sdis_estimator* estimator = NULL; struct dump_path_context dump_ctx; struct sdis_solve_probe_args args = SDIS_SOLVE_PROBE_ARGS_DEFAULT; - FILE* stream = NULL; + FILE* stream_r = NULL; + FILE* stream_g = NULL; + FILE* stream_p = NULL; struct time compute_start, compute_end; ASSERT(stardis && start && (stardis->mode & MODE_PROBE_COMPUTE)); - ERR(check_probe_conform_to_type(stardis, 0, stardis->probe, &iprim, uv)); + ERR(check_probe_conform_to_type(stardis, 0, stardis->probe, + stardis->time_range[0], &iprim, uv)); args.nrealisations = stardis->samples; d3_set(args.position, stardis->probe); @@ -446,29 +504,37 @@ compute_probe(struct stardis* stardis, struct time* start) 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); + /* Try to open output files to detect errors early */ 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) { + stream_g = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream_g) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->bin_green_filename)); 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(!stream) { + stream_p = fopen(str_cget(&stardis->end_paths_filename), "w"); + if(!stream_p) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->end_paths_filename)); res = RES_IO_ERR; goto error; } - ERR(dump_paths_end(green, stardis, stream)); - fclose(stream); stream = NULL; + } + } + /* Call solve() */ + 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; + ERR(dump_green_bin(green, stardis, stream_g)); + if(stream_p) { + ERR(dump_paths_end(green, stardis, stream_p)); } time_current(&output_end); ERR(print_computation_time(NULL, stardis, @@ -484,17 +550,20 @@ compute_probe(struct stardis* stardis, struct time* start) if(stardis->mpi_initialized && stardis->mpi_rank != 0) { ERR(sdis_solve_probe(stardis->sdis_scn, &args, &estimator)); } else { + res_T tmp_res1, tmp_res2; 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)); + tmp_res1 = 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)); + tmp_res2 = sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx); + if(tmp_res1 != RES_OK) res = tmp_res1; + else if(tmp_res2 != RES_OK) res = tmp_res2; } } @@ -502,7 +571,9 @@ compute_probe(struct stardis* stardis, struct time* start) WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); end: - if(stream) fclose(stream); + if(stream_r) fclose(stream_r); + if(stream_g) fclose(stream_g); + if(stream_p) fclose(stream_p); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); if(args.rng_state) SSP(rng_ref_put(args.rng_state)); @@ -522,7 +593,9 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) struct dump_path_context dump_ctx; struct sdis_solve_probe_boundary_args args = SDIS_SOLVE_PROBE_BOUNDARY_ARGS_DEFAULT; - FILE* stream = NULL; + FILE* stream_r = NULL; + FILE* stream_g = NULL; + FILE* stream_p = NULL; struct time compute_start, compute_end; enum sdis_side compute_side; unsigned prop[3]; @@ -538,7 +611,8 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) #endif ASSERT(stardis && start && (stardis->mode & MODE_PROBE_COMPUTE_ON_INTERFACE)); - ERR(check_probe_conform_to_type(stardis, 1, stardis->probe, &iprim, uv)); + ERR(check_probe_conform_to_type(stardis, 1, stardis->probe, + stardis->time_range[0], &iprim, uv)); ASSERT(iprim != UINT_MAX); ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, @@ -560,7 +634,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(DESC_IS_MEDIUM(d->type)); + ASSERT(DESC_IS_MEDIUM(d)); medium_name = str_cget(get_description_name(d)); compute_side = SDIS_FRONT; compute_side_name = "FRONT"; @@ -569,7 +643,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(DESC_IS_MEDIUM(d->type)); + ASSERT(DESC_IS_MEDIUM(d)); medium_name = str_cget(get_description_name(d)); compute_side = SDIS_BACK; compute_side_name = "BACK"; @@ -589,8 +663,8 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) fd = descriptions + prop[SG3D_FRONT]; bd = descriptions + prop[SG3D_BACK]; - ASSERT(DESC_IS_MEDIUM(fd->type)); - ASSERT(DESC_IS_MEDIUM(bd->type)); + ASSERT(DESC_IS_MEDIUM(fd)); + ASSERT(DESC_IS_MEDIUM(bd)); description_get_medium_id(fd, &fmat_id); description_get_medium_id(bd, &bmat_id); @@ -677,7 +751,7 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) args.nrealisations = stardis->samples; args.iprim = iprim; - d3_set(args.uv, uv); + d2_set(args.uv, uv); args.side = compute_side; d2_set(args.time_range, stardis->time_range); @@ -689,30 +763,38 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) 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); + /* Try to open output files to detect errors early */ 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) { + stream_g = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream_g) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->bin_green_filename)); 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(!stream) { + stream_p = fopen(str_cget(&stardis->end_paths_filename), "w"); + if(!stream_p) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->end_paths_filename)); res = RES_IO_ERR; goto error; } - ERR(dump_paths_end(green, stardis, stream)); - fclose(stream); stream = NULL; + } + } + /* Call solve() */ + 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; + ERR(dump_green_bin(green, stardis, stream_g)); + if(stream_p) { + ERR(dump_paths_end(green, stardis, stream_p)); } time_current(&output_end); ERR(print_computation_time(NULL, stardis, @@ -728,17 +810,20 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) if(stardis->mpi_initialized && stardis->mpi_rank != 0) { ERR(sdis_solve_probe_boundary(stardis->sdis_scn, &args, &estimator)); } else { + res_T tmp_res1, tmp_res2; 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)); + tmp_res1 = 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)); + tmp_res2 = sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx); + if(tmp_res1 != RES_OK) res = tmp_res1; + else if(tmp_res2 != RES_OK) res = tmp_res2; } } @@ -746,7 +831,9 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); end: - if(stream) fclose(stream); + if(stream_r) fclose(stream_r); + if(stream_g) fclose(stream_g); + if(stream_p) fclose(stream_p); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); if(args.rng_state) SSP(rng_ref_put(args.rng_state)); @@ -773,7 +860,7 @@ auto_look_at double radius; double depth; res_T res; - ASSERT(scn && fov_x && proj_ratio && up); + ASSERT(scn && fov_x!=0 && proj_ratio!=0 && up); ERR(sdis_scene_get_aabb(scn, lower, upper)); @@ -845,7 +932,7 @@ compute_camera(struct stardis* stardis, struct time* start) struct dump_path_context dump_ctx; size_t definition[2]; size_t ix, iy; - FILE* stream; + FILE* stream = NULL; struct time compute_start, compute_end, output_end; ASSERT(stardis && start @@ -938,7 +1025,9 @@ compute_medium(struct stardis* stardis, struct time* start) struct sdis_green_function* green = NULL; struct sdis_solve_medium_args args = SDIS_SOLVE_MEDIUM_ARGS_DEFAULT; struct dump_path_context dump_ctx; - FILE* stream = NULL; + FILE* stream_r = NULL; + FILE* stream_g = NULL; + FILE* stream_p = NULL; struct time compute_start, compute_end; ASSERT(stardis && start && (stardis->mode & MODE_MEDIUM_COMPUTE)); @@ -964,29 +1053,38 @@ compute_medium(struct stardis* stardis, struct time* start) 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); + /* Try to open output files to detect errors early */ 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) { + stream_g = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream_g) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->bin_green_filename)); 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(!stream) { + stream_p = fopen(str_cget(&stardis->end_paths_filename), "w"); + if(!stream_p) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->end_paths_filename)); res = RES_IO_ERR; goto error; } - ERR(dump_paths_end(green, stardis, stream)); - fclose(stream); stream = NULL; + } + } + /* Call solve() */ + 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)); + ERR(dump_green_bin(green, stardis, stream_g)); + if(stream_p) { + ERR(dump_paths_end(green, stardis, stream_p)); } time_current(&output_end); ERR(print_computation_time(NULL, stardis, @@ -1002,16 +1100,19 @@ compute_medium(struct stardis* stardis, struct time* start) if(stardis->mpi_initialized && stardis->mpi_rank != 0) { ERR(sdis_solve_medium(stardis->sdis_scn, &args, &estimator)); } else { + res_T tmp_res1, tmp_res2; 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)); + tmp_res1 = 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)); + tmp_res2 = sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx); + if(tmp_res1 != RES_OK) res = tmp_res1; + else if(tmp_res2 != RES_OK) res = tmp_res2; } } @@ -1019,7 +1120,9 @@ compute_medium(struct stardis* stardis, struct time* start) WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); end: - if(stream) fclose(stream); + if(stream_r) fclose(stream_r); + if(stream_g) fclose(stream_g); + if(stream_p) fclose(stream_p); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); if(args.rng_state) SSP(rng_ref_put(args.rng_state)); @@ -1084,7 +1187,9 @@ compute_boundary(struct stardis* stardis, struct time* start) struct sdis_estimator* estimator = NULL; struct dump_path_context dump_ctx; struct sdis_solve_boundary_args args = SDIS_SOLVE_BOUNDARY_ARGS_DEFAULT; - FILE* stream = NULL; + FILE* stream_r = NULL; + FILE* stream_g = NULL; + FILE* stream_p = NULL; struct time compute_start, compute_end; ASSERT(stardis && start && (stardis->mode & MODE_BOUNDARY_COMPUTE)); @@ -1104,29 +1209,37 @@ compute_boundary(struct stardis* stardis, struct time* start) 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); + /* Try to open output files to detect errors early */ 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) { + stream_g = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream_g) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->bin_green_filename)); 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(!stream) { + stream_p = fopen(str_cget(&stardis->end_paths_filename), "w"); + if(!stream_p) { + logger_print(stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", str_cget(&stardis->end_paths_filename)); res = RES_IO_ERR; goto error; } - ERR(dump_paths_end(green, stardis, stream)); - fclose(stream); stream = NULL; + } + } + /* Call solve() */ + 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; + ERR(dump_green_bin(green, stardis, stream_g)); + if(stream_p) { + ERR(dump_paths_end(green, stardis, stream_p)); } time_current(&output_end); ERR(print_computation_time(NULL, stardis, @@ -1142,16 +1255,19 @@ compute_boundary(struct stardis* stardis, struct time* start) if(stardis->mpi_initialized && stardis->mpi_rank != 0) { ERR(sdis_solve_boundary(stardis->sdis_scn, &args, &estimator)); } else { + res_T tmp_res1, tmp_res2; 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)); + tmp_res1 = 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)); + tmp_res2 = sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx); + if(tmp_res1 != RES_OK) res = tmp_res1; + else if(tmp_res2 != RES_OK) res = tmp_res2; } } @@ -1159,7 +1275,9 @@ compute_boundary(struct stardis* stardis, struct time* start) WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); end: - if(stream) fclose(stream); + if(stream_r) fclose(stream_r); + if(stream_g) fclose(stream_g); + if(stream_p) fclose(stream_p); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); if(args.rng_state) SSP(rng_ref_put(args.rng_state)); @@ -1177,7 +1295,7 @@ compute_flux_boundary(struct stardis* stardis, struct time* start) struct sdis_solve_boundary_flux_args args = SDIS_SOLVE_BOUNDARY_FLUX_ARGS_DEFAULT; struct dump_path_context dump_ctx; - FILE* stream = NULL; + FILE* stream_r = NULL; struct time compute_start, compute_end; ASSERT(stardis && start && (stardis->mode & MODE_FLUX_BOUNDARY_COMPUTE)); @@ -1196,17 +1314,20 @@ compute_flux_boundary(struct stardis* stardis, struct time* start) if(stardis->mpi_initialized && stardis->mpi_rank != 0) { ERR(sdis_solve_boundary_flux(stardis->sdis_scn, &args, &estimator)); } else { + res_T tmp_res1, tmp_res2; 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)); + tmp_res1 = 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)); + tmp_res2 = sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx); + if(tmp_res1 != RES_OK) res = tmp_res1; + else if(tmp_res2 != RES_OK) res = tmp_res2; } /* Output random state? */ diff --git a/src/stardis-compute.h b/src/stardis-compute.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -33,13 +33,13 @@ find_medium_by_name const struct str* name, unsigned* id); /* Can be NULL */ -extern LOCAL_SYM res_T +res_T stardis_compute (struct stardis* stardis, struct time* start); -extern LOCAL_SYM res_T +res_T read_compute_surface (struct stardis* stardis); -#endif -\ No newline at end of file +#endif diff --git a/src/stardis-default.h.in b/src/stardis-default.h.in @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2020 |Meso|Star> +/* Copyright (C) 2018-2022 |Meso|Star> * * 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-description.c b/src/stardis-description.c @@ -0,0 +1,294 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-description.h" +#include "stardis-solid.h" +#include "stardis-solid-prog.h" +#include "stardis-fluid.h" +#include "stardis-fluid-prog.h" +#include "stardis-hbound.h" +#include "stardis-hbound-prog.h" +#include "stardis-hfbound.h" +#include "stardis-hfbound-prog.h" +#include "stardis-tbound.h" +#include "stardis-tbound-prog.h" +#include "stardis-fbound.h" +#include "stardis-fbound-prog.h" +#include "stardis-sfconnect.h" +#include "stardis-sfconnect-prog.h" +#include "stardis-ssconnect.h" +#include "stardis-ssconnect-prog.h" +#include "stardis-program.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +res_T +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; +} + +void +release_description + (struct description* desc, + struct mem_allocator* allocator) +{ + ASSERT(desc && allocator); + switch (desc->type) { + case DESC_MAT_SOLID: + release_solid(desc->d.solid, allocator); + break; + case DESC_MAT_SOLID_PROG: + release_solid_prog(desc->d.solid_prog, allocator); + break; + case DESC_MAT_FLUID: + release_fluid(desc->d.fluid, allocator); + break; + case DESC_MAT_FLUID_PROG: + release_fluid_prog(desc->d.fluid_prog, allocator); + break; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + release_h_boundary(desc->d.h_boundary, allocator); + break; + case DESC_BOUND_H_FOR_SOLID_PROG: + case DESC_BOUND_H_FOR_FLUID_PROG: + release_h_boundary_prog(desc->d.h_boundary_prog, allocator); + break; + case DESC_BOUND_HF_FOR_SOLID: + release_hf_boundary(desc->d.hf_boundary, allocator); + break; + case DESC_BOUND_HF_FOR_SOLID_PROG: + release_hf_boundary_prog(desc->d.hf_boundary_prog, allocator); + break; + case DESC_BOUND_T_FOR_SOLID: + release_t_boundary(desc->d.t_boundary, allocator); + break; + case DESC_BOUND_T_FOR_SOLID_PROG: + release_t_boundary_prog(desc->d.t_boundary_prog, allocator); + break; + case DESC_BOUND_F_FOR_SOLID: + release_f_boundary(desc->d.f_boundary, allocator); + break; + case DESC_BOUND_F_FOR_SOLID_PROG: + release_f_boundary_prog(desc->d.f_boundary_prog, allocator); + break; + case DESC_SOLID_FLUID_CONNECT: + release_sf_connect(desc->d.sf_connect, allocator); + break; + case DESC_SOLID_FLUID_CONNECT_PROG: + release_sf_connect_prog(desc->d.sf_connect_prog, allocator); + break; + case DESC_SOLID_SOLID_CONNECT: + release_ss_connect(desc->d.ss_connect, allocator); + break; + case DESC_SOLID_SOLID_CONNECT_PROG: + release_ss_connect_prog(desc->d.ss_connect_prog, allocator); + break; + case DESC_PROGRAM: + release_program(desc->d.program, allocator); + break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } +} + +res_T +str_print_description + (struct str* str, + const unsigned rank, + const struct description* desc) +{ + res_T res = RES_OK; + ASSERT(str && desc); + str_clear(str); + ERR(str_printf(str, "Description %u: ", rank)); + switch (desc->type) { + case DESC_MAT_SOLID: + ERR(str_print_solid(str, desc->d.solid)); + break; + case DESC_MAT_SOLID_PROG: + ERR(str_print_solid_prog(str, desc->d.solid_prog)); + break; + case DESC_MAT_FLUID: + ERR(str_print_fluid(str, desc->d.fluid)); + break; + case DESC_MAT_FLUID_PROG: + ERR(str_print_fluid_prog(str, desc->d.fluid_prog)); + break; + case DESC_BOUND_T_FOR_SOLID: + ERR(str_print_t_boundary(str, desc->d.t_boundary)); + break; + case DESC_BOUND_T_FOR_SOLID_PROG: + ERR(str_print_t_boundary_prog(str, desc->d.t_boundary_prog)); + break; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + ERR(str_print_h_boundary(str, desc)); + break; + case DESC_BOUND_H_FOR_SOLID_PROG: + case DESC_BOUND_H_FOR_FLUID_PROG: + ERR(str_print_h_boundary_prog(str, desc)); + break; + case DESC_BOUND_HF_FOR_SOLID: + ERR(str_print_hf_boundary(str, desc)); + break; + case DESC_BOUND_HF_FOR_SOLID_PROG: + ERR(str_print_hf_boundary_prog(str, desc)); + break; + case DESC_BOUND_F_FOR_SOLID: + ERR(str_print_f_boundary(str, desc->d.f_boundary)); + break; + case DESC_BOUND_F_FOR_SOLID_PROG: + ERR(str_print_f_boundary_prog(str, desc->d.f_boundary_prog)); + break; + case DESC_SOLID_FLUID_CONNECT: + ERR(str_print_sf_connect(str, desc->d.sf_connect)); + break; + case DESC_SOLID_FLUID_CONNECT_PROG: + ERR(str_print_sf_connect_prog(str, desc->d.sf_connect_prog)); + break; + case DESC_SOLID_SOLID_CONNECT: + ERR(str_print_ss_connect(str, desc->d.ss_connect)); + break; + case DESC_SOLID_SOLID_CONNECT_PROG: + ERR(str_print_ss_connect_prog(str, desc->d.ss_connect_prog)); + break; + case DESC_PROGRAM: + ERR(str_print_program(str, desc->d.program)); + break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } +end: + return res; +error: + goto end; +} + +const struct str* +get_description_name + (const struct description* desc) +{ + ASSERT(desc); + switch (desc->type) { + case DESC_MAT_SOLID: + return &desc->d.solid->name; + case DESC_MAT_SOLID_PROG: + return &desc->d.solid_prog->name; + case DESC_MAT_FLUID: + return &desc->d.fluid->name; + case DESC_MAT_FLUID_PROG: + return &desc->d.fluid_prog->name; + case DESC_BOUND_T_FOR_SOLID: + return &desc->d.t_boundary->name; + case DESC_BOUND_T_FOR_SOLID_PROG: + return &desc->d.t_boundary_prog->name; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + return &desc->d.h_boundary->name; + case DESC_BOUND_H_FOR_SOLID_PROG: + case DESC_BOUND_H_FOR_FLUID_PROG: + return &desc->d.h_boundary_prog->name; + case DESC_BOUND_HF_FOR_SOLID: + return &desc->d.hf_boundary->name; + case DESC_BOUND_HF_FOR_SOLID_PROG: + return &desc->d.hf_boundary_prog->name; + case DESC_BOUND_F_FOR_SOLID: + return &desc->d.f_boundary->name; + case DESC_BOUND_F_FOR_SOLID_PROG: + return &desc->d.f_boundary_prog->name; + case DESC_SOLID_FLUID_CONNECT: + return &desc->d.sf_connect->name; + case DESC_SOLID_FLUID_CONNECT_PROG: + return &desc->d.sf_connect_prog->name; + case DESC_SOLID_SOLID_CONNECT: + return &desc->d.ss_connect->name; + case DESC_SOLID_SOLID_CONNECT_PROG: + return &desc->d.ss_connect_prog->name; + case DESC_PROGRAM: + return &desc->d.program->name; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } +} + +void +description_get_medium_id + (const struct description* desc, + unsigned* id) +{ + ASSERT(desc && id); + switch (desc->type) { + case DESC_MAT_SOLID: + *id = desc->d.solid->solid_id; + return; + case DESC_MAT_SOLID_PROG: + *id = desc->d.solid_prog->solid_id; + return; + case DESC_MAT_FLUID: + *id = desc->d.fluid->fluid_id; + return; + case DESC_MAT_FLUID_PROG: + *id = desc->d.fluid_prog->fluid_id; + return; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + *id = desc->d.h_boundary->mat_id; + return; + case DESC_BOUND_H_FOR_SOLID_PROG: + case DESC_BOUND_H_FOR_FLUID_PROG: + *id = desc->d.h_boundary_prog->mat_id; + return; + case DESC_BOUND_HF_FOR_SOLID: + *id = desc->d.hf_boundary->mat_id; + return; + case DESC_BOUND_HF_FOR_SOLID_PROG: + *id = desc->d.hf_boundary_prog->mat_id; + return; + case DESC_BOUND_T_FOR_SOLID: + *id = desc->d.t_boundary->mat_id; + return; + case DESC_BOUND_T_FOR_SOLID_PROG: + *id = desc->d.t_boundary_prog->mat_id; + return; + case DESC_BOUND_F_FOR_SOLID: + *id = desc->d.f_boundary->mat_id; + return; + case DESC_BOUND_F_FOR_SOLID_PROG: + *id = desc->d.f_boundary_prog->mat_id; + return; + case DESC_SOLID_FLUID_CONNECT: /* No medium linked to SF */ + case DESC_SOLID_SOLID_CONNECT: /* No medium linked to SS */ + case DESC_SOLID_FLUID_CONNECT_PROG: /* No medium linked to SF */ + case DESC_SOLID_SOLID_CONNECT_PROG: /* No medium linked to SS */ + case DESC_PROGRAM: /* No medium linked to PRORGRAM */ + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } +} diff --git a/src/stardis-description.h b/src/stardis-description.h @@ -0,0 +1,162 @@ +/* Copyright (C) 2018-2023 |Méso|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_DESCRIPTION_H +#define STARDIS_DESCRIPTION_H + +#include <rsys/rsys.h> +#include <rsys/dynamic_array.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/* Forward declarations */ +struct mem_allocator; + +/* Different types of descriptions */ +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, + DESC_SOLID_SOLID_CONNECT, + DESC_MAT_SOLID_PROG, + DESC_MAT_FLUID_PROG, + DESC_BOUND_H_FOR_FLUID_PROG, + DESC_BOUND_H_FOR_SOLID_PROG, + DESC_BOUND_HF_FOR_SOLID, + DESC_BOUND_HF_FOR_SOLID_PROG, + DESC_BOUND_T_FOR_SOLID_PROG, + DESC_BOUND_F_FOR_SOLID_PROG, + DESC_SOLID_FLUID_CONNECT_PROG, + DESC_SOLID_SOLID_CONNECT_PROG, + DESC_PROGRAM, + DESCRIPTION_TYPE_COUNT__ +}; + +#define DESC_IS_H(D) \ + ((D)->type == DESC_BOUND_H_FOR_SOLID || (D)->type == DESC_BOUND_H_FOR_FLUID \ + || (D)->type == DESC_BOUND_H_FOR_SOLID_PROG \ + || (D)->type == DESC_BOUND_H_FOR_FLUID_PROG) +#define DESC_IS_HF(D) \ + ((D)->type == DESC_BOUND_HF_FOR_SOLID\ + || (D)->type == DESC_BOUND_HF_FOR_SOLID_PROG) +#define DESC_IS_T(D) \ + ((D)->type == DESC_BOUND_T_FOR_SOLID \ + || (D)->type == DESC_BOUND_T_FOR_SOLID_PROG) +#define DESC_IS_F(D) \ + ((D)->type == DESC_BOUND_F_FOR_SOLID \ + || (D)->type == DESC_BOUND_F_FOR_SOLID_PROG) +#define DESC_IS_SOLID(D) \ + ((D)->type == DESC_MAT_SOLID || (D)->type == DESC_MAT_SOLID_PROG) +#define DESC_IS_FLUID(D) \ + ((D)->type == DESC_MAT_FLUID || (D)->type == DESC_MAT_FLUID_PROG) +#define DESC_IS_MEDIUM(D) \ + (DESC_IS_SOLID(D) || DESC_IS_FLUID(D)) +#define DESC_IS_BOUNDARY(D) \ + (DESC_IS_H(D) || DESC_IS_T(D) || DESC_IS_F(D)) +#define DESC_IS_SOLID_FLUID(D) \ + ((D)->type == DESC_SOLID_FLUID_CONNECT \ + || (D)->type == DESC_SOLID_FLUID_CONNECT_PROG) +#define DESC_IS_SOLID_SOLID(D) \ + ((D)->type == DESC_SOLID_SOLID_CONNECT \ + || (D)->type == DESC_SOLID_SOLID_CONNECT_PROG) +#define DESC_IS_CONNECTION(D) \ + (DESC_IS_SOLID_FLUID(D) || DESC_IS_SOLID_SOLID(D)) +#define DESC_IS_PROG(D) \ + ((D)->type == DESC_MAT_SOLID_PROG || (D)->type == DESC_MAT_FLUID_PROG \ + || (D)->type == DESC_BOUND_H_FOR_FLUID_PROG \ + || (D)->type == DESC_BOUND_H_FOR_SOLID_PROG \ + || (D)->type == DESC_BOUND_HF_FOR_SOLID_PROG \ + || (D)->type == DESC_BOUND_T_FOR_SOLID_PROG \ + || (D)->type == DESC_BOUND_F_FOR_SOLID_PROG \ + || (D)->type == DESC_SOLID_FLUID_CONNECT_PROG \ + || (D)->type == DESC_SOLID_SOLID_CONNECT_PROG) + +/******************************************************************************/ + +struct fluid; +struct fluid_prog; +struct solid; +struct solid_prog; +struct t_boundary; +struct t_boundary_prog; +struct f_boundary; +struct f_boundary_prog; +struct h_boundary; +struct h_boundary_prog; +struct hf_boundary; +struct hf_boundary_prog; +struct solid_fluid_connect; +struct solid_fluid_connect_prog; +struct solid_solid_connect; +struct solid_solid_connect_prog; +struct program; + +struct description { + enum description_type type; + union { + struct fluid* fluid; + struct fluid_prog* fluid_prog; + struct solid* solid; + struct solid_prog* solid_prog; + struct t_boundary* t_boundary; + struct t_boundary_prog* t_boundary_prog; + struct f_boundary* f_boundary; + struct f_boundary_prog* f_boundary_prog; + struct h_boundary* h_boundary; + struct h_boundary_prog* h_boundary_prog; + struct hf_boundary* hf_boundary; + struct hf_boundary_prog* hf_boundary_prog; + struct solid_fluid_connect* sf_connect; + struct solid_fluid_connect_prog* sf_connect_prog; + struct solid_solid_connect* ss_connect; + struct solid_solid_connect_prog* ss_connect_prog; + struct program* program; + } d; +}; + +/******************************************************************************/ +res_T +init_description + (struct mem_allocator* alloc, + struct description* desc); + +void +release_description + (struct description* desc, + struct mem_allocator* allocator); + +res_T +str_print_description + (struct str* str, + const unsigned rank, + const struct description* desc); + +const struct str* +get_description_name + (const struct description* desc); + +void +description_get_medium_id + (const struct description* desc, + unsigned* id); + +#endif diff --git a/src/stardis-fbound-prog.c b/src/stardis-fbound-prog.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-fbound-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ + +res_T +init_f_boundary_prog + (struct mem_allocator* allocator, + struct f_boundary_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->mat_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_f_boundary_prog + (struct f_boundary_prog* bound, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(bound && allocator); + str_release(&bound->name); + str_release(&bound->prog_name); + if(bound->prog_data) + bound->release(bound->prog_data); + for(i = 0; i < bound->argc; i++) MEM_RM(allocator, bound->argv[i]); + MEM_RM(allocator, bound->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, bound); +} + +res_T +str_print_f_boundary_prog + (struct str* str, + const struct f_boundary_prog* b) +{ + res_T res = RES_OK; + ASSERT(str && b); + ERR(str_append_printf(str, + "programmed F boundary for SOLID '%s': lib='%s', " + "(using medium %u as external medium)", + str_cget(&b->name), str_cget(&b->prog_name), b->mat_id)); + if(b->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < b->argc; i++) { + ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); + } + } +end: + return res; +error: + goto end; +} + diff --git a/src/stardis-fbound-prog.h b/src/stardis-fbound-prog.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2018-2023 |Méso|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_FBOUND_PROG_H +#define SDIS_FBOUND_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct stardis; +struct mem_allocator; +struct fluid_prog; +struct description; +struct program; + +/******************************************************************************* + * F boundary prog data + ******************************************************************************/ +struct f_boundary_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*flux)(const struct stardis_interface_fragment*, void*); + unsigned mat_id; +}; + +res_T +init_f_boundary_prog + (struct mem_allocator* allocator, + struct f_boundary_prog** dst); + +void +release_f_boundary_prog + (struct f_boundary_prog* bound, + struct mem_allocator* allocator); + +res_T +str_print_f_boundary_prog + (struct str* str, + const struct f_boundary_prog* b); + +#endif diff --git a/src/stardis-fbound.c b/src/stardis-fbound.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-fbound.h" +#include "stardis-fluid.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_f_boundary + (struct mem_allocator* allocator, + struct f_boundary** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_initialized = 1; + (*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; +} + +void +release_f_boundary + (struct f_boundary* bound, + struct mem_allocator* allocator) +{ + ASSERT(bound && allocator); + str_release(&bound->name); + MEM_RM(allocator, bound); +} + +res_T +str_print_f_boundary + (struct str* str, + const struct f_boundary* bound) +{ + res_T res = RES_OK; + ASSERT(str && bound); + ERR(str_append_printf(str, + "F boundary for SOLID '%s': flux=%g (using medium %u as external medium)", + str_cget(&bound->name), bound->imposed_flux, bound->mat_id)); +end: + return res; +error: + goto end; +} + diff --git a/src/stardis-fbound.h b/src/stardis-fbound.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2018-2023 |Méso|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_FBOUND_H +#define SDIS_FBOUND_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct mem_allocator; + +/******************************************************************************* + * F boundary type + ******************************************************************************/ +struct f_boundary { + struct str name; + double imposed_flux; + unsigned mat_id; +}; + +res_T +init_f_boundary + (struct mem_allocator* allocator, + struct f_boundary** dst); + +void +release_f_boundary + (struct f_boundary* bound, + struct mem_allocator* allocator); + +res_T +str_print_f_boundary + (struct str* str, + const struct f_boundary* bound); + +#endif diff --git a/src/stardis-fluid-prog.c b/src/stardis-fluid-prog.c @@ -0,0 +1,203 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-fluid-prog.h" +#include "stardis-app.h" +#include "stardis-prog-properties.h" +#include "stardis-app.h" + +#include <rsys/mem_allocator.h> + +#include <sdis.h> + +#include <limits.h> + + +/******************************************************************************* + * Local Functions + ******************************************************************************/ +static double +fluid_prog_get_calorific_capacity + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct fluid_prog* const* fluid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*fluid_props)->cp(&v, (*fluid_props)->prog_data); +} + +static double +fluid_prog_get_volumic_mass + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct fluid_prog* const* fluid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*fluid_props)->rho(&v, (*fluid_props)->prog_data); +} + +static double +fluid_prog_get_temperature + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct fluid_prog* const* fluid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*fluid_props)->temp(&v, (*fluid_props)->prog_data); +} + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +create_solver_fluid_prog + (struct stardis* stardis, + const struct fluid_prog* fluid_props) +{ + res_T res = RES_OK; + struct sdis_fluid_shader fluid_shader = SDIS_FLUID_SHADER_NULL; + struct sdis_data* data = NULL; + const struct fluid_prog** props; + + ASSERT(stardis && fluid_props); + fluid_shader.calorific_capacity = fluid_prog_get_calorific_capacity; + fluid_shader.volumic_mass = fluid_prog_get_volumic_mass; + fluid_shader.temperature = fluid_prog_get_temperature; + ERR(sdis_data_create(stardis->dev, sizeof(struct fluid_prog*), + ALIGNOF(struct fluid_prog*), NULL, &data)); + + props = sdis_data_get(data); /* Fetch the allocated memory space */ + *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]); + ERR(sdis_fluid_create(stardis->dev, &fluid_shader, data, + darray_media_ptr_data_get(&stardis->media) + fluid_props->fluid_id)); + +end: + if(data) SDIS(data_ref_put(data)); + return res; +error: + goto end; +} + +res_T +create_solver_external_fluid_prog + (struct stardis* stardis, + const struct fluid_prog* fluid_props) +{ + res_T res = RES_OK; + struct sdis_fluid_shader fluid_shader = SDIS_FLUID_SHADER_NULL; + struct sdis_data* data = NULL; + const struct fluid_prog** props; + + ASSERT(stardis && fluid_props); + fluid_shader.calorific_capacity = fluid_prog_get_calorific_capacity; + fluid_shader.volumic_mass = fluid_prog_get_volumic_mass; + fluid_shader.temperature = fluid_prog_get_temperature; + /* temperature has to be provided by h_boundary_prog */ + ERR(sdis_data_create(stardis->dev, sizeof(struct fluid_prog*), + ALIGNOF(struct fluid_prog*), NULL, &data)); + + props = sdis_data_get(data); /* Fetch the allocated memory space */ + *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]); + ERR(sdis_fluid_create(stardis->dev, &fluid_shader, data, + darray_media_ptr_data_get(&stardis->media) + fluid_props->fluid_id)); + +end: + if(data) SDIS(data_ref_put(data)); + return res; +error: + goto end; +} + +res_T +init_fluid_prog(struct mem_allocator* allocator, struct fluid_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->desc_id = UINT_MAX; + (*dst)->fluid_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_fluid_prog + (struct fluid_prog* fluid, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(fluid && allocator); + str_release(&fluid->name); + str_release(&fluid->prog_name); + if(fluid->prog_data + && fluid->release) /* can be NULL if external fluid */ + { + fluid->release(fluid->prog_data); + } + for(i = 0; i < fluid->argc; i++) MEM_RM(allocator, fluid->argv[i]); + MEM_RM(allocator, fluid->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, fluid); +} + +res_T +str_print_fluid_prog(struct str* str, const struct fluid_prog* f) +{ + res_T res = RES_OK; + ASSERT(str && f); + ERR(str_append_printf(str, + "programmed fluid '%s': lib='%s', it is medium %u)", + str_cget(&f->name), str_cget(&f->prog_name), f->fluid_id)); + if(f->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < f->argc; i++) { + ERR(str_append_printf(str, (i+1 == f->argc ? "\t%s" : "\t%s\n"), f->argv[i])); + } + } +end: + return res; +error: + goto end; +} diff --git a/src/stardis-fluid-prog.h b/src/stardis-fluid-prog.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2018-2023 |Méso|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_FLUID_PROG_H +#define SDIS_FLUID_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct stardis; +struct mem_allocator; +struct program; + +/******************************************************************************* + * Fluid prog data + ******************************************************************************/ +struct fluid_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + int is_outside; /* the fluid is used for a boundary */ + unsigned desc_id; /* id of the boundary; meaningful if is_outside */ + unsigned fluid_id; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*rho)(const struct stardis_vertex*, void*); + double (*cp)(const struct stardis_vertex*, void*); + double (*temp)(const struct stardis_vertex*, void*); + double* (*t_range)(void*, double trange[2]); +}; + +res_T +create_solver_fluid_prog + (struct stardis* stardis, + const struct fluid_prog* fluid_props); + +res_T +create_solver_external_fluid_prog + (struct stardis* stardis, + const struct fluid_prog* fluid_props); + +res_T +init_fluid_prog + (struct mem_allocator* allocator, + struct fluid_prog** dst); + +void +release_fluid_prog + (struct fluid_prog* fluid, + struct mem_allocator* allocator); + +res_T +str_print_fluid_prog + (struct str* str, + const struct fluid_prog* fluid); + +#endif diff --git a/src/stardis-fluid.c b/src/stardis-fluid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -14,7 +14,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "stardis-fluid.h" -#include "stardis-compute.h" #include "stardis-app.h" #include <sdis.h> @@ -153,15 +152,15 @@ str_print_fluid(struct str* str, const struct fluid* f) { res_T res = RES_OK; ASSERT(str && f); - STR_APPEND_PRINTF(str, "Fluid '%s': rho=%g cp=%g", - ARG3( str_cget(&f->name), f->rho, f->cp ) ); + ERR(str_append_printf(str, "Fluid '%s': rho=%g cp=%g", + str_cget(&f->name), f->rho, f->cp)); if(f->tinit >= 0) { - STR_APPEND_PRINTF(str, " Tinit=%g", ARG1( f->tinit ) ); + ERR(str_append_printf(str, " Tinit=%g", f->tinit)); } if(f->imposed_temperature >= 0) { - STR_APPEND_PRINTF(str, " Temp=%g", ARG1( f->imposed_temperature ) ); + ERR(str_append_printf(str, " Temp=%g", f->imposed_temperature)); } - STR_APPEND_PRINTF(str, " (it is medium %u)", ARG1( f->fluid_id ) ); + ERR(str_append_printf(str, " (it is medium %u)", f->fluid_id)); end: return res; error: diff --git a/src/stardis-fluid.h b/src/stardis-fluid.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -36,7 +36,7 @@ struct fluid { double t0; /* End time of tinit */ int is_outside; /* the fluid is used for a boundary */ int is_green; /* green computation (nothing to do with fluid itself) */ - unsigned desc_id; /* id of the boundary; meaningful if is_outside */ + unsigned desc_id; unsigned fluid_id; }; @@ -45,15 +45,15 @@ create_solver_fluid (struct stardis* stardis, const struct fluid* fluid_props); -LOCAL_SYM res_T +res_T init_fluid(struct mem_allocator* allocator, struct fluid** dst); -LOCAL_SYM void +void release_fluid (struct fluid* desc, struct mem_allocator* allocator); -LOCAL_SYM res_T +res_T str_print_fluid(struct str* str, const struct fluid* s); #endif diff --git a/src/stardis-green-types.h.in b/src/stardis-green-types.h.in @@ -16,6 +16,8 @@ #ifndef SDIS_GREEN_H #define SDIS_GREEN_H +#include <stddef.h> + /* The number of the file format as presented thereafter */ #define GREEN_FILE_FORMAT_VERSION @STARDIS_GREEN_TYPES_VERSION@ diff --git a/src/stardis-hbound-prog.c b/src/stardis-hbound-prog.c @@ -0,0 +1,113 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-hbound-prog.h" +#include "stardis-fluid-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_h_boundary_prog + (struct mem_allocator* allocator, + struct h_boundary_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->mat_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_h_boundary_prog + (struct h_boundary_prog* bound, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(bound && allocator); + str_release(&bound->name); + str_release(&bound->prog_name); + if(bound->prog_data) + bound->release(bound->prog_data); + if(bound->possible_external_fluid) + release_fluid_prog(bound->possible_external_fluid, allocator); + for(i = 0; i < bound->argc; i++) MEM_RM(allocator, bound->argv[i]); + MEM_RM(allocator, bound->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, bound); +} + +res_T +str_print_h_boundary_prog + (struct str* str, + const struct description* desc) +{ + res_T res = RES_OK; + const struct h_boundary_prog* b; + ASSERT(str && desc && DESC_IS_H(desc)); + b = desc->d.h_boundary_prog; + ERR(str_append_printf(str, + "programmed H boundary for %s '%s': lib='%s', " + "(using medium %u as external medium)", + (desc->type == DESC_BOUND_H_FOR_SOLID_PROG ? "solid" : "fluid"), + str_cget(&b->name), str_cget(&b->prog_name), + b->mat_id)); + if(b->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < b->argc; i++) { + ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); + } + } +end: + return res; +error: + goto end; +} + +double +h_bound_prog_get_hmax + (struct h_boundary_prog* h_boundary_props) +{ + return h_boundary_props->hmax(h_boundary_props->prog_data); +} diff --git a/src/stardis-hbound-prog.h b/src/stardis-hbound-prog.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2018-2023 |Méso|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_HBOUND_PROG_H +#define SDIS_HBOUND_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct mem_allocator; +struct fluid_prog; +struct description; +struct program; + +/******************************************************************************* + * H boundary prog data + ******************************************************************************/ +struct h_boundary_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*ref_temp)(const struct stardis_interface_fragment*, void*); + double (*emissivity)(const struct stardis_interface_fragment*, void*); + double (*alpha)(const struct stardis_interface_fragment*, void*); + double (*hc)(const struct stardis_interface_fragment*, void*); + double (*hmax)(void*); + double* (*t_range)(void*, double trange[2]); + /* for h for solid */ + double (*boundary_temp)(const struct stardis_interface_fragment*, void*); + /* for h for fluid */ + double (*fluid_temp)(const struct stardis_vertex*, void*); + unsigned mat_id; + struct fluid_prog* possible_external_fluid; /* if H for solid */ +}; + +res_T +init_h_boundary_prog + (struct mem_allocator* allocator, + struct h_boundary_prog** dst); + +void +release_h_boundary_prog + (struct h_boundary_prog* bound, + struct mem_allocator* allocator); + +res_T +str_print_h_boundary_prog + (struct str* str, + const struct description* bound); + +double +h_bound_prog_get_hmax + (struct h_boundary_prog* h_boundary_props); + +#endif diff --git a/src/stardis-hbound.c b/src/stardis-hbound.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-hbound.h" +#include "stardis-fluid.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_h_boundary + (struct mem_allocator* allocator, + struct h_boundary** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_initialized = 1; + (*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; +} + +void +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); +} + +res_T +str_print_h_boundary + (struct str* str, + const struct description* desc) +{ + res_T res = RES_OK; + const struct h_boundary* b; + ASSERT(str && desc && DESC_IS_H(desc)); + b = desc->d.h_boundary; + ERR(str_append_printf(str, + "H boundary for %s '%s': ref_temperature=%g emissivity=%g specular_fraction=%g " + "hc=%g T=%g (using medium %u as external medium)", + (desc->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; +} diff --git a/src/stardis-hbound.h b/src/stardis-hbound.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2018-2023 |Méso|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_HBOUND_H +#define SDIS_HBOUND_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct mem_allocator; +struct fluid; +struct description; + +/******************************************************************************* + * H boundary type + ******************************************************************************/ +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 */ +}; + +res_T +init_h_boundary + (struct mem_allocator* allocator, + struct h_boundary** dst); + +void +release_h_boundary + (struct h_boundary* bound, + struct mem_allocator* allocator); + +res_T +str_print_h_boundary + (struct str* str, + const struct description* desc); + +#endif diff --git a/src/stardis-hfbound-prog.c b/src/stardis-hfbound-prog.c @@ -0,0 +1,113 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-hfbound-prog.h" +#include "stardis-fluid-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_hf_boundary_prog + (struct mem_allocator* allocator, + struct hf_boundary_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->mat_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_hf_boundary_prog + (struct hf_boundary_prog* bound, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(bound && allocator); + str_release(&bound->name); + str_release(&bound->prog_name); + if(bound->prog_data) + bound->release(bound->prog_data); + if(bound->possible_external_fluid) + release_fluid_prog(bound->possible_external_fluid, allocator); + for(i = 0; i < bound->argc; i++) MEM_RM(allocator, bound->argv[i]); + MEM_RM(allocator, bound->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, bound); +} + +res_T +str_print_hf_boundary_prog + (struct str* str, + const struct description* desc) +{ + res_T res = RES_OK; + const struct hf_boundary_prog* b; + ASSERT(str && desc && DESC_IS_HF(desc)); + b = desc->d.hf_boundary_prog; + ERR(str_append_printf(str, + "programmed HF boundary for %s '%s': lib='%s', " + "(using medium %u as external medium)", + (desc->type == DESC_BOUND_HF_FOR_SOLID_PROG ? "solid" : "fluid"), + str_cget(&b->name), str_cget(&b->prog_name), + b->mat_id)); + if(b->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < b->argc; i++) { + ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); + } + } +end: + return res; +error: + goto end; +} + +double +hf_bound_prog_get_hmax + (struct hf_boundary_prog* hf_boundary_props) +{ + return hf_boundary_props->hmax(hf_boundary_props->prog_data); +} diff --git a/src/stardis-hfbound-prog.h b/src/stardis-hfbound-prog.h @@ -0,0 +1,77 @@ +/* Copyright (C) 2018-2023 |Méso|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_HFBOUND_PROG_H +#define SDIS_HFBOUND_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct mem_allocator; +struct fluid_prog; +struct description; +struct program; + +/******************************************************************************* + * HF boundary prog data + ******************************************************************************/ +struct hf_boundary_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*ref_temp)(const struct stardis_interface_fragment*, void*); + double (*emissivity)(const struct stardis_interface_fragment*, void*); + double (*alpha)(const struct stardis_interface_fragment*, void*); + double (*hc)(const struct stardis_interface_fragment*, void*); + double (*hmax)(void*); + double* (*t_range)(void*, double trange[2]); + /* for h for solid */ + double (*boundary_temp)(const struct stardis_interface_fragment*, void*); + double (*flux)(const struct stardis_interface_fragment*, void*); + /* for h for fluid */ + double (*fluid_temp)(const struct stardis_vertex*, void*); + unsigned mat_id; + struct fluid_prog* possible_external_fluid; /* if H for solid */ +}; + +res_T +init_hf_boundary_prog + (struct mem_allocator* allocator, + struct hf_boundary_prog** dst); + +void +release_hf_boundary_prog + (struct hf_boundary_prog* bound, + struct mem_allocator* allocator); + +res_T +str_print_hf_boundary_prog + (struct str* str, + const struct description* bound); + +double +hf_bound_prog_get_hmax + (struct hf_boundary_prog* hf_boundary_props); + +#endif diff --git a/src/stardis-hfbound.c b/src/stardis-hfbound.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-hfbound.h" +#include "stardis-fluid.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_hf_boundary + (struct mem_allocator* allocator, + struct hf_boundary** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_initialized = 1; + (*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; +} + +void +release_hf_boundary + (struct hf_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); +} + +res_T +str_print_hf_boundary + (struct str* str, + const struct description* desc) +{ + res_T res = RES_OK; + const struct hf_boundary* b; + ASSERT(str && desc && DESC_IS_HF(desc)); + b = desc->d.hf_boundary; + ERR(str_append_printf(str, + "HF boundary for %s '%s': ref_temperature=%g emissivity=%g specular_fraction=%g " + "hc=%g T=%g flux=%g (using medium %u as external medium)", + (desc->type == DESC_BOUND_HF_FOR_SOLID ? "solid" : "fluid"), + str_cget(&b->name), b->ref_temperature, b->emissivity, + b->specular_fraction, b->hc, b->imposed_temperature, b->imposed_flux, + b->mat_id)); +end: + return res; +error: + goto end; +} diff --git a/src/stardis-hfbound.h b/src/stardis-hfbound.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2018-2023 |Méso|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_HFBOUND_H +#define SDIS_HFBOUND_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct mem_allocator; +struct fluid; +struct description; + +/******************************************************************************* + * HF boundary type + ******************************************************************************/ +struct hf_boundary { + struct str name; + double ref_temperature; + double emissivity; + double specular_fraction; + double hc; + double imposed_flux; + double imposed_temperature; + unsigned mat_id; + struct fluid* possible_external_fluid; /* if HF for solid */ +}; + +res_T +init_hf_boundary + (struct mem_allocator* allocator, + struct hf_boundary** dst); + +void +release_hf_boundary + (struct hf_boundary* bound, + struct mem_allocator* allocator); + +res_T +str_print_hf_boundary + (struct str* str, + const struct description* desc); + +#endif diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -18,6 +18,18 @@ #include "stardis-compute.h" #include "stardis-output.h" #include "stardis-solid.h" +#include "stardis-hbound.h" +#include "stardis-hbound-prog.h" +#include "stardis-hfbound.h" +#include "stardis-hfbound-prog.h" +#include "stardis-tbound.h" +#include "stardis-tbound-prog.h" +#include "stardis-fbound.h" +#include "stardis-fbound-prog.h" +#include "stardis-ssconnect.h" +#include "stardis-ssconnect-prog.h" +#include "stardis-sfconnect.h" +#include "stardis-sfconnect-prog.h" #include <sdis.h> @@ -95,6 +107,126 @@ interface_get_tcr return interface_props->tcr; } +static double +emissivity_1 + (const struct stardis_interface_fragment* frag, + void* data) +{ + (void)frag, (void)data; + return 1; +} + +static double +intface_prog_get_temp + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_temp(&f, interface_props->prog_data); +} + +static double +intface_prog_get_flux + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_flux(&f, interface_props->prog_data); +} + +static double +intface_prog_get_hc + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_hc(&f, interface_props->prog_data); +} + +static double +intface_prog_get_emissivity + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_emissivity(&f, interface_props->prog_data); +} + +static double +intface_prog_get_alpha + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_alpha(&f, interface_props->prog_data); +} + +static double +intface_prog_get_ref_temp + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_ref_temp(&f, interface_props->prog_data); +} + +static double +intface_prog_get_tcr + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + struct stardis_interface_fragment f; + d3_set(f.P, frag->P); + d3_set(f.Ng, frag->Ng); + d3_set(f.uv, frag->uv); + f.time = frag->time; + ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); + f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; + return interface_props->get_tcr(&f, interface_props->prog_data); +} /******************************************************************************* * Public Functions @@ -107,16 +239,16 @@ create_intface struct htable_intface* htable_interfaces) { struct int_descs int_descs = INT_DESCS_NULL; - struct sdis_interface** p_intface; - struct sdis_interface* intface; + struct sdis_interface** pp_intface; + struct sdis_interface* p_intface; struct sdis_medium* front_med = NULL; struct sdis_medium* back_med = NULL; struct sdis_interface_side_shader* fluid_side_shader = NULL; struct sdis_data* data = NULL; - unsigned fd, bd, cd, descr[SG3D_PROP_TYPES_COUNT__]; + unsigned fd, bd, id, descr[SG3D_PROP_TYPES_COUNT__]; int fluid_count = 0, solid_count = 0; int solid_fluid_connection_count = 0, solid_solid_connection_count = 0; - int connection_count = 0, boundary_count = 0; + int intface_count = 0, boundary_count = 0, prog_count = 0; const struct description* descriptions; struct sdis_medium** media; res_T res = RES_OK; @@ -133,20 +265,20 @@ create_intface /* Create key */ int_descs.front = fd = descr[SG3D_FRONT]; int_descs.back = bd = descr[SG3D_BACK]; - int_descs.connect = cd = descr[SG3D_INTFACE]; + int_descs.intface = id = descr[SG3D_INTFACE]; /* Search if interface already exists, or create it */ - p_intface = htable_intface_find(htable_interfaces, &int_descs); - if(p_intface) { - intface = *p_intface; + pp_intface = htable_intface_find(htable_interfaces, &int_descs); + if(pp_intface) { + p_intface = *pp_intface; } else { /* create new interface and register */ struct sdis_interface_shader interface_shader = SDIS_INTERFACE_SHADER_NULL; struct intface* interface_props = NULL; - unsigned id; + unsigned mid; int front_defined = (fd != SG3D_UNSPECIFIED_PROPERTY); int back_defined = (bd != SG3D_UNSPECIFIED_PROPERTY); - int connect_defined = (cd != SG3D_UNSPECIFIED_PROPERTY); + int intface_defined = (id != SG3D_UNSPECIFIED_PROPERTY); ERR(sdis_data_create(stardis->dev, sizeof(struct intface), ALIGNOF(struct intface), NULL, &data)); @@ -156,20 +288,35 @@ create_intface interface_props->front_medium_id = UINT_MAX; interface_props->back_medium_id = UINT_MAX; interface_props->desc_id = UINT_MAX; + interface_props->get_temp = NULL; + interface_props->get_flux = NULL; + interface_props->get_hc = NULL; + interface_props->get_emissivity = NULL; + interface_props->get_alpha = NULL; + interface_props->get_ref_temp = NULL; + interface_props->get_tcr = NULL; + interface_props->prog_data = NULL; + if(fluid_count == 2) { + res = RES_BAD_ARG; + goto error; + } if(front_defined) { + description_get_medium_id(&descriptions[fd], &mid); + interface_props->front_medium_id = mid; + front_med = media[mid]; switch (descriptions[fd].type) { + case DESC_MAT_SOLID_PROG: + prog_count++; + /* fall through */ case DESC_MAT_SOLID: - id = descriptions[fd].d.solid->solid_id; solid_count++; - interface_props->front_medium_id = id; - front_med = media[id]; break; + case DESC_MAT_FLUID_PROG: + prog_count++; + /* fall through */ case DESC_MAT_FLUID: fluid_count++; - id = descriptions[fd].d.fluid->fluid_id; - interface_props->front_medium_id = id; - front_med = media[id]; fluid_side_shader = &interface_shader.front; break; default: @@ -177,105 +324,211 @@ create_intface } } if(back_defined) { + description_get_medium_id(&descriptions[bd], &mid); + interface_props->back_medium_id = mid; + back_med = media[mid]; switch (descriptions[bd].type) { + case DESC_MAT_SOLID_PROG: + prog_count++; + /* fall through */ case DESC_MAT_SOLID: - id = descriptions[bd].d.solid->solid_id; solid_count++; - interface_props->back_medium_id = id; - back_med = media[id]; break; + case DESC_MAT_FLUID_PROG: + prog_count++; + /* fall through */ case DESC_MAT_FLUID: fluid_count++; - 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 - * fluids and this case lead to an error */ + /* cannot overwrite as the 2-fluid case is an error */ fluid_side_shader = &interface_shader.back; break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } } - if(fluid_count == 2) { - res = RES_BAD_ARG; - goto error; - } - if(connect_defined) { - const struct description* connect = descriptions + cd; - int type_checked = 0; + if(intface_defined) { + const struct description* intface = descriptions + id; + int for_fluid = 0; struct sdis_medium* def_medium = NULL; unsigned ext_id; - if(connect->type != DESC_SOLID_FLUID_CONNECT - && connect->type != DESC_SOLID_SOLID_CONNECT - && front_defined == back_defined) - { - /* 1 and only 1 defined */ + if(!DESC_IS_CONNECTION(intface) && front_defined == back_defined) { + /* not connection implies 1 and only 1 side defined */ res = RES_BAD_ARG; goto error; } - if(front_defined) { - def_medium = front_med; - fluid_side_shader = (descriptions[fd].type == DESC_MAT_FLUID) - ? &interface_shader.front : &interface_shader.back; - } else { - ASSERT(back_defined); - def_medium = back_med; - fluid_side_shader = (descriptions[bd].type == DESC_MAT_FLUID) - ? &interface_shader.back : &interface_shader.front; - } - interface_props->desc_id = cd; - switch(connect->type) { + /* meaningless if connection (but unused in this case) */ + def_medium = front_defined ? front_med : back_med; + interface_props->desc_id = id; + switch(intface->type) { case DESC_BOUND_H_FOR_FLUID: if(sdis_medium_get_type(def_medium) != SDIS_FLUID) { res = RES_BAD_ARG; goto error; } - type_checked = 1; - ASSERT(connect->d.h_boundary->imposed_temperature >= 0); + for_fluid = 1; + ASSERT(intface->d.h_boundary->imposed_temperature >= 0); interface_props->imposed_temperature - = connect->d.h_boundary->imposed_temperature; + = intface->d.h_boundary->imposed_temperature; ASSERT(fluid_side_shader); fluid_side_shader->temperature = interface_get_temperature; /* fall through */ case DESC_BOUND_H_FOR_SOLID: - if(!type_checked - && sdis_medium_get_type(def_medium) != SDIS_SOLID) - { - res = RES_BAD_ARG; goto error; + if(!for_fluid) { + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(!fluid_side_shader); + fluid_side_shader = + front_defined ? &interface_shader.back : &interface_shader.front; } - ext_id = connect->d.h_boundary->mat_id; /* External material id */ + ext_id = intface->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)); - connection_count++; + (for_fluid ? SDIS_SOLID : SDIS_FLUID)); + intface_count++; 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->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_upper_bound = intface->d.h_boundary->hc; + interface_props->hc = intface->d.h_boundary->hc; + interface_props->ref_temperature = intface->d.h_boundary->ref_temperature; + interface_props->emissivity = intface->d.h_boundary->emissivity; + interface_props->alpha = intface->d.h_boundary->specular_fraction; + if(intface->d.h_boundary->hc > 0) { + interface_shader.convection_coef = interface_get_convection_coef; + } + fluid_side_shader->reference_temperature = interface_get_ref_temperature; + if(intface->d.h_boundary->emissivity > 0) { + fluid_side_shader->emissivity = interface_get_emissivity; + fluid_side_shader->specular_fraction = interface_get_alpha; + } + break; + case DESC_BOUND_HF_FOR_SOLID: + if(!for_fluid) { + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(!fluid_side_shader); + fluid_side_shader = + front_defined ? &interface_shader.back : &interface_shader.front; + } + ext_id = intface->d.hf_boundary->mat_id; /* External material id */ + ASSERT(ext_id < darray_media_ptr_size_get(&stardis->media)); + ASSERT(sdis_medium_get_type(media[ext_id]) == + (for_fluid ? SDIS_SOLID : SDIS_FLUID)); + intface_count++; + boundary_count++; + if(front_defined) back_med = media[ext_id]; + else front_med = media[ext_id]; + interface_shader.convection_coef_upper_bound = intface->d.hf_boundary->hc; + interface_props->hc = intface->d.hf_boundary->hc; + interface_props->ref_temperature = intface->d.hf_boundary->ref_temperature; + interface_props->emissivity = intface->d.hf_boundary->emissivity; + interface_props->alpha = intface->d.hf_boundary->specular_fraction; + if(intface->d.hf_boundary->hc > 0) { interface_shader.convection_coef = interface_get_convection_coef; } - ASSERT(fluid_side_shader); fluid_side_shader->reference_temperature = interface_get_ref_temperature; - if(connect->d.h_boundary->emissivity > 0) { + ASSERT(intface->d.hf_boundary->imposed_flux != SDIS_FLUX_NONE); + if(intface->d.hf_boundary->imposed_flux) { + interface_props->imposed_flux = intface->d.hf_boundary->imposed_flux; + interface_shader.front.flux = interface_get_flux; + interface_shader.back.flux = interface_get_flux; + } + if(intface->d.hf_boundary->emissivity > 0) { fluid_side_shader->emissivity = interface_get_emissivity; fluid_side_shader->specular_fraction = interface_get_alpha; } break; + case DESC_BOUND_H_FOR_FLUID_PROG: + if(sdis_medium_get_type(def_medium) != SDIS_FLUID) { + res = RES_BAD_ARG; + goto error; + } + for_fluid = 1; + interface_props->get_temp = intface->d.h_boundary_prog->boundary_temp; + ASSERT(fluid_side_shader); + fluid_side_shader->temperature = intface_prog_get_temp; + /* fall through */ + case DESC_BOUND_H_FOR_SOLID_PROG: + if(!for_fluid) { + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(!fluid_side_shader); + fluid_side_shader = + front_defined ? &interface_shader.back : &interface_shader.front; + } + ext_id = intface->d.h_boundary_prog->mat_id; /* External material id */ + ASSERT(ext_id < darray_media_ptr_size_get(&stardis->media)); + ASSERT(sdis_medium_get_type(media[ext_id]) == + (for_fluid ? SDIS_SOLID : SDIS_FLUID)); + prog_count++; + intface_count++; + boundary_count++; + if(front_defined) back_med = media[ext_id]; + else front_med = media[ext_id]; + interface_shader.convection_coef_upper_bound + = h_bound_prog_get_hmax(intface->d.h_boundary_prog); + ASSERT(interface_shader.convection_coef_upper_bound >= 0); + interface_shader.convection_coef + = intface_prog_get_hc; + fluid_side_shader->reference_temperature + = intface_prog_get_ref_temp; + fluid_side_shader->emissivity = intface_prog_get_emissivity; + fluid_side_shader->specular_fraction = intface_prog_get_alpha; + interface_props->get_hc = intface->d.h_boundary_prog->hc; + interface_props->get_emissivity = intface->d.h_boundary_prog->emissivity; + interface_props->get_alpha = intface->d.h_boundary_prog->alpha; + interface_props->get_ref_temp = intface->d.h_boundary_prog->ref_temp; + interface_props->prog_data = intface->d.h_boundary_prog->prog_data; + break; + case DESC_BOUND_HF_FOR_SOLID_PROG: + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(!fluid_side_shader); + fluid_side_shader = + front_defined ? &interface_shader.back : &interface_shader.front; + ext_id = intface->d.hf_boundary_prog->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); + prog_count++; + intface_count++; + boundary_count++; + if(front_defined) back_med = media[ext_id]; + else front_med = media[ext_id]; + interface_shader.convection_coef_upper_bound + = hf_bound_prog_get_hmax(intface->d.hf_boundary_prog); + ASSERT(interface_shader.convection_coef_upper_bound >= 0); + interface_shader.convection_coef = intface_prog_get_hc; + fluid_side_shader->reference_temperature = intface_prog_get_ref_temp; + fluid_side_shader->emissivity = intface_prog_get_emissivity; + fluid_side_shader->specular_fraction = intface_prog_get_alpha; + interface_shader.front.flux = intface_prog_get_flux; + interface_shader.back.flux = intface_prog_get_flux; + interface_props->get_hc = intface->d.hf_boundary_prog->hc; + interface_props->get_emissivity = intface->d.hf_boundary_prog->emissivity; + interface_props->get_alpha = intface->d.hf_boundary_prog->alpha; + interface_props->get_flux = intface->d.hf_boundary_prog->flux; + interface_props->get_ref_temp = intface->d.hf_boundary_prog->ref_temp; + interface_props->prog_data = intface->d.hf_boundary_prog->prog_data; + break; case DESC_BOUND_T_FOR_SOLID: if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { res = RES_BAD_ARG; goto error; } - ext_id = connect->d.t_boundary->mat_id; /* External material id */ + fluid_side_shader = + front_defined ? &interface_shader.back : &interface_shader.front; + ext_id = intface->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++; + intface_count++; boundary_count++; if(front_defined) { ASSERT(!back_med); @@ -284,35 +537,81 @@ create_intface ASSERT(!front_med); front_med = media[ext_id]; } - /* The imposed T is for the 2 sides (until there is contact resistances) */ + /* The imposed T is for the 2 sides (there is no contact resistance) */ interface_shader.front.temperature = interface_get_temperature; interface_shader.back.temperature = interface_get_temperature; /* 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(intface->d.t_boundary->imposed_temperature >= 0); interface_props->imposed_temperature - = connect->d.t_boundary->imposed_temperature; + = intface->d.t_boundary->imposed_temperature; + break; + case DESC_BOUND_T_FOR_SOLID_PROG: + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { + res = RES_BAD_ARG; + goto error; + } + fluid_side_shader = + front_defined ? &interface_shader.back : &interface_shader.front; + ext_id = intface->d.t_boundary_prog->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); + prog_count++; + intface_count++; + boundary_count++; + if(front_defined) { + ASSERT(!back_med); + back_med = media[ext_id]; + } else { + ASSERT(!front_med); + front_med = media[ext_id]; + } + /* The imposed T is for the 2 sides (there is no contact resistance) */ + interface_shader.front.temperature = intface_prog_get_temp; + interface_shader.back.temperature = intface_prog_get_temp; + /* Set emissivity to 1 to allow radiative paths comming from + * a possible external fluid to 'see' the imposed T */ + fluid_side_shader->emissivity = interface_get_emissivity; + interface_props->get_emissivity = emissivity_1; + interface_props->get_temp = intface->d.t_boundary_prog->temperature; + interface_props->prog_data = intface->d.t_boundary_prog->prog_data; break; case DESC_BOUND_F_FOR_SOLID: if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { res = RES_BAD_ARG; goto error; } - connection_count++; + intface_count++; boundary_count++; if(front_defined) { - back_med = media[connect->d.f_boundary->mat_id]; - interface_shader.front.flux = interface_get_flux; + back_med = media[intface->d.f_boundary->mat_id]; } else { - front_med = media[connect->d.f_boundary->mat_id]; - interface_shader.back.flux = interface_get_flux; + front_med = media[intface->d.f_boundary->mat_id]; } - ASSERT(connect->d.f_boundary->imposed_flux != SDIS_FLUX_NONE); - interface_props->imposed_flux = connect->d.f_boundary->imposed_flux; + interface_shader.front.flux = interface_get_flux; + interface_shader.back.flux = interface_get_flux; + ASSERT(intface->d.f_boundary->imposed_flux != SDIS_FLUX_NONE); + interface_props->imposed_flux = intface->d.f_boundary->imposed_flux; + break; + case DESC_BOUND_F_FOR_SOLID_PROG: + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { + res = RES_BAD_ARG; + goto error; + } + prog_count++; + intface_count++; + boundary_count++; + if(front_defined) { + back_med = media[intface->d.f_boundary_prog->mat_id]; + } else { + front_med = media[intface->d.f_boundary_prog->mat_id]; + } + interface_shader.front.flux = intface_prog_get_flux; + interface_shader.back.flux = intface_prog_get_flux; + interface_props->get_flux = intface->d.f_boundary_prog->flux; + interface_props->prog_data = intface->d.f_boundary_prog->prog_data; break; case DESC_SOLID_FLUID_CONNECT: /* Both front and back should be defined */ @@ -321,23 +620,48 @@ create_intface goto error; } ASSERT(front_defined && back_defined); - connection_count++; + intface_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->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_upper_bound = intface->d.sf_connect->hc; + interface_props->hc = intface->d.sf_connect->hc; + interface_props->ref_temperature = intface->d.sf_connect->ref_temperature; + interface_props->emissivity = intface->d.sf_connect->emissivity; + interface_props->alpha = intface->d.sf_connect->specular_fraction; + if(intface->d.sf_connect->hc > 0) { interface_shader.convection_coef = interface_get_convection_coef; } ASSERT(fluid_side_shader); fluid_side_shader->reference_temperature = interface_get_ref_temperature; - if(connect->d.sf_connect->emissivity > 0) { + if(intface->d.sf_connect->emissivity > 0) { fluid_side_shader->emissivity = interface_get_emissivity; fluid_side_shader->specular_fraction = interface_get_alpha; } break; + case DESC_SOLID_FLUID_CONNECT_PROG: + /* Both front and back should be defined */ + if(solid_count != 1 || fluid_count != 1) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(front_defined && back_defined); + prog_count++; + intface_count++; + solid_fluid_connection_count++; + interface_shader.convection_coef_upper_bound + = sf_connect_prog_get_hmax(intface->d.sf_connect_prog); + ASSERT(interface_shader.convection_coef_upper_bound >= 0); + interface_props->get_ref_temp = intface->d.sf_connect_prog->ref_temp; + interface_props->get_hc = intface->d.sf_connect_prog->hc; + interface_props->get_emissivity + = intface->d.sf_connect_prog->emissivity; + interface_props->get_alpha = intface->d.sf_connect_prog->alpha; + interface_shader.convection_coef = intface_prog_get_hc; + ASSERT(fluid_side_shader); + fluid_side_shader->emissivity = intface_prog_get_emissivity; + fluid_side_shader->specular_fraction = intface_prog_get_alpha; + fluid_side_shader->reference_temperature = intface_prog_get_ref_temp; + interface_props->prog_data = intface->d.sf_connect_prog->prog_data; + break; case DESC_SOLID_SOLID_CONNECT: /* Both front and back should be defined */ if(solid_count != 2 || fluid_count != 0) { @@ -345,19 +669,33 @@ create_intface goto error; } ASSERT(front_defined && back_defined); - connection_count++; + intface_count++; solid_solid_connection_count++; - interface_props->tcr = connect->d.ss_connect->tcr; - if(connect->d.ss_connect->tcr > 0) { + interface_props->tcr = intface->d.ss_connect->tcr; + if(intface->d.ss_connect->tcr > 0) { interface_shader.thermal_contact_resistance = interface_get_tcr; } break; + case DESC_SOLID_SOLID_CONNECT_PROG: + /* Both front and back should be defined */ + if(solid_count != 2 || fluid_count != 0) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(front_defined && back_defined); + prog_count++; + intface_count++; + solid_solid_connection_count++; + interface_props->get_tcr = intface->d.ss_connect_prog->tcr; + interface_shader.thermal_contact_resistance = intface_prog_get_tcr; + interface_props->prog_data = intface->d.ss_connect_prog->prog_data; + break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } } - if((fluid_count + solid_count + connection_count < 2) + if((fluid_count + solid_count + intface_count < 2) || (boundary_count && (fluid_count + solid_count != 1))) { res = RES_BAD_ARG; @@ -365,12 +703,12 @@ create_intface } ERR(sdis_interface_create(stardis->dev, front_med, back_med, - &interface_shader, data, &intface)); + &interface_shader, data, &p_intface)); SDIS(data_ref_put(data)); data = NULL; - ERR(darray_interface_ptrs_push_back(&stardis->geometry.interfaces, &intface)); - ERR(htable_intface_set(htable_interfaces, &int_descs, &intface)); + ERR(darray_interface_ptrs_push_back(&stardis->geometry.interfaces, &p_intface)); + ERR(htable_intface_set(htable_interfaces, &int_descs, &p_intface)); } - ERR(darray_interface_ptrs_push_back(&stardis->geometry.interf_bytrg, &intface)); + ERR(darray_interface_ptrs_push_back(&stardis->geometry.interf_bytrg, &p_intface)); end: if(data) SDIS(data_ref_put(data)); diff --git a/src/stardis-intface.h b/src/stardis-intface.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -21,12 +21,21 @@ #include <limits.h> struct stardis; -struct dummies; +struct stardis_interface_fragment; /******************************************************************************* * Interface data ******************************************************************************/ struct intface { + /* programmed interfaces */ + double (*get_temp)(const struct stardis_interface_fragment*, void*); + double (*get_flux)(const struct stardis_interface_fragment*, void*); + double (*get_hc)(const struct stardis_interface_fragment*, void*); + double (*get_emissivity)(const struct stardis_interface_fragment*, void*); + double (*get_alpha)(const struct stardis_interface_fragment*, void*); + double (*get_ref_temp)(const struct stardis_interface_fragment*, void*); + double (*get_tcr)(const struct stardis_interface_fragment*, void*); + void* prog_data; /* fluid - solid */ double hc; double ref_temperature; @@ -44,7 +53,7 @@ struct intface { /* Declare the hash table that map an interface to its descriptor */ struct int_descs { - unsigned front, back, connect; + unsigned front, back, intface; }; #define INT_DESCS_NULL__ { UINT_MAX, UINT_MAX, UINT_MAX } static const struct int_descs INT_DESCS_NULL = INT_DESCS_NULL__; @@ -53,7 +62,7 @@ static INLINE char eq_desc(const struct int_descs* a, const struct int_descs* b) { return (char)(a->front == b->front && a->back == b->back - && a->connect == b->connect); + && a->intface == b->intface); } #define HTABLE_NAME intface @@ -62,7 +71,7 @@ eq_desc(const struct int_descs* a, const struct int_descs* b) #define HTABLE_KEY_FUNCTOR_EQ eq_desc #include <rsys/hash_table.h> -extern res_T +res_T create_intface (struct stardis* stardis, unsigned tr_idx, diff --git a/src/stardis-main.c b/src/stardis-main.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -14,6 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "stardis-app.h" +#include "stardis-args.h" #include "stardis-parsing.h" #include "stardis-output.h" #include "stardis-compute.h" @@ -65,7 +66,7 @@ main ERR(init_args(&logger, &allocator, &args)); args_initialized = 1; ERR(parse_args(argc, argv, args, &allocator)); - mode = args->mode; + mode = (int)args->mode; if(mode & MODE_DUMP_HELP) { short_help(stdout, argv[0]); diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -15,18 +15,24 @@ #define _POSIX_C_SOURCE 200112L /* snprintf */ #include "stardis-output.h" +#include "stardis-args.h" #include "stardis-compute.h" #include "stardis-fluid.h" #include "stardis-solid.h" +#include "stardis-hbound.h" +#include "stardis-tbound.h" +#include "stardis-fbound.h" +#include "stardis-ssconnect.h" +#include "stardis-sfconnect.h" #include "stardis-intface.h" #include "stardis-app.h" #include "stardis-green-types.h" #include <sdis.h> +#include<star/ssp.h> #include<star/senc3d.h> #include<star/sg3d.h> -#include<star/ssp.h> #include <rsys/math.h> #include <rsys/mem_allocator.h> @@ -68,7 +74,6 @@ enum enclosure_errors_t { ENCLOSURE_WITH_UNDEF_MEDIUM = BIT(2) }; - static res_T copy_desc_to_green_desc (struct green_description* gdesc, @@ -248,7 +253,7 @@ dump_path char* name = NULL; enum sdis_heat_path_flag status = SDIS_HEAT_PATH_NONE; size_t vcount_, scount_, offset, name_sz, istrip; - unsigned long scount, vcount; + unsigned long scount, vcount, strip_1, type_changes, *strip_type_changes = NULL; ASSERT(path && dump_ctx && dump_ctx->stardis @@ -268,21 +273,49 @@ dump_path stream = fopen(name, "w"); if(!stream) { + logger_print(dump_ctx->stardis->logger, LOG_ERROR, + "cannot open file '%s'\n", name); res = RES_IO_ERR; goto error; } /* Get counts */ ERR(sdis_heat_path_get_line_strips_count(path, &scount_)); - if(scount > ULONG_MAX) goto abort; + if(scount_ > ULONG_MAX) goto abort; scount = (unsigned long)scount_; vcount_ = 0; + strip_1 = 0; + type_changes = 0; + strip_type_changes = MEM_CALLOC(dump_ctx->stardis->allocator, scount, + sizeof(*strip_type_changes)); + if(!strip_type_changes) { + res = RES_MEM_ERR; + goto error; + } + FOR_EACH(istrip, 0, scount_) { - size_t n; - ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &n)); - vcount_+= n; + size_t ivert, nverts; + enum sdis_heat_vertex_type prev_type = SDIS_HEAT_VERTEX_CONDUCTION; + ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); + if(nverts == 0 || nverts > ULONG_MAX) goto abort; + if(nverts == 1) strip_1++; + FOR_EACH(ivert, 0, nverts) { + struct sdis_heat_vertex vtx; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert, &vtx)); + /* Count changes in vertex type along strips + * As we use vertex type instead of segment type, the vertices where type + * change are duplicated (with the only difference of their types) so that + * segments where type change are zero-length. + * This way Paraview displays segments with no misleading color gradient */ + if(ivert != 0 && vtx.type != prev_type) { + type_changes++; + strip_type_changes[istrip]++; + } + prev_type = vtx.type; + } + vcount_+= nverts; } - if(vcount > ULONG_MAX) goto abort; + if(vcount_ > ULONG_MAX) goto abort; vcount = (unsigned long)vcount_; /* Header */ fprintf(stream, "# vtk DataFile Version 2.0\n"); @@ -290,60 +323,84 @@ dump_path fprintf(stream, "ASCII\n"); fprintf(stream, "DATASET POLYDATA\n"); /* Write path positions */ - fprintf(stream, "POINTS %lu double\n", vcount); + fprintf(stream, "POINTS %lu double\n", vcount + type_changes); FOR_EACH(istrip, 0, scount_) { size_t ivert, nverts; + enum sdis_heat_vertex_type prev_type = SDIS_HEAT_VERTEX_CONDUCTION; 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(ivert != 0 && vtx.type != prev_type) { + /* duplicate the previous vertex */ + struct sdis_heat_vertex v; + ERR(sdis_heat_path_line_strip_get_vertex(path, istrip, ivert-1, &v)); + fprintf(stream, "%g %g %g\n", SPLIT3(v.P)); + } fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P)); + prev_type = vtx.type; } } - /* Write the strips of the path */ - fprintf(stream, "LINES %lu %lu\n", scount, scount + vcount); + /* Write the strips of the path + * Workaround a Paraview crash by creating 2-vertices-long paths from + * single-vertex paths */ + fprintf(stream, "LINES %lu %lu\n", + scount, scount + vcount + strip_1 + type_changes); offset = 0; - FOR_EACH(istrip, 0, scount) { - size_t ivert, nverts; + FOR_EACH(istrip, 0, scount_) { + size_t 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)); + if(nverts == 1) { + fprintf(stream, "2 %lu %lu\n", (unsigned long)offset, (unsigned long)offset); + } else { + size_t ivert; + fprintf(stream, "%lu", (unsigned long)nverts + strip_type_changes[istrip]); + FOR_EACH(ivert, 0, nverts + strip_type_changes[istrip]) { + if(ivert + offset > ULONG_MAX) goto abort; + fprintf(stream, " %lu", (unsigned long)(ivert + offset)); + } + fprintf(stream, "\n"); } - fprintf(stream, "\n"); - offset += nverts; + offset += nverts + strip_type_changes[istrip]; } /* 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) { + 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); + fprintf(stream, "POINT_DATA %lu\n", vcount + type_changes); /* Write the type of the random walk vertices */ - fprintf(stream, "SCALARS Vertex_Type unsigned_char 1\n"); + fprintf(stream, "SCALARS Segment_Type unsigned_char 1\n"); fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(istrip, 0, scount_) { size_t ivert, nverts; + enum sdis_heat_vertex_type prev_type = SDIS_HEAT_VERTEX_CONDUCTION; ERR(sdis_heat_path_line_strip_get_vertices_count(path, istrip, &nverts)); FOR_EACH(ivert, 0, nverts) { struct sdis_heat_vertex vtx; + int t; 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; + case SDIS_HEAT_VERTEX_CONDUCTION: t = 0; break; + case SDIS_HEAT_VERTEX_CONVECTION: t = 1; break; + case SDIS_HEAT_VERTEX_RADIATIVE: t = 2; break; default: FATAL("Unreachable code.\n"); break; } + fprintf(stream, "%d\n", t); + if(ivert != 0 && vtx.type != prev_type) { + /* duplicate the previous vertex, except its type which is defined as + * the type of the current vertex */ + fprintf(stream, "%d\n", t); + } + prev_type = vtx.type; } } /* Write the weights of the random walk vertices */ @@ -351,11 +408,19 @@ dump_path fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(istrip, 0, scount_) { size_t ivert, nverts; + enum sdis_heat_vertex_type prev_type = SDIS_HEAT_VERTEX_CONDUCTION; + double prev_w = 0; 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); + if(ivert != 0 && vtx.type != prev_type) { + /* duplicate the previous vertex */ + fprintf(stream, "%g\n", prev_w); + } + prev_type = vtx.type; + prev_w = vtx.weight; } } /* Write the branch_id of the random walk vertices */ @@ -363,33 +428,53 @@ dump_path fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(istrip, 0, scount_) { size_t ivert, nverts; + enum sdis_heat_vertex_type prev_type = SDIS_HEAT_VERTEX_CONDUCTION; + int prev_id = 0; 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(ivert != 0 && vtx.type != prev_type) { + /* duplicate the previous vertex */ + fprintf(stream, "%d\n", prev_id); + } + prev_type = vtx.type; + prev_id = vtx.branch_id; } } /* If computation time is not INF, * write the time of the random walk vertices */ FOR_EACH(istrip, 0, scount_) { size_t ivert, nverts; + enum sdis_heat_vertex_type prev_type = SDIS_HEAT_VERTEX_CONDUCTION; + double prev_time = 0; 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(IS_INF(vtx.time)) { + if(istrip || ivert) goto abort; + goto end_prt_time; + } 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); + if(ivert != 0 && vtx.type != prev_type) { + /* duplicate the previous vertex */ + fprintf(stream, "%g\n", prev_time); + } + prev_type = vtx.type; + prev_time = vtx.time; } } +end_prt_time: end: MEM_RM(dump_ctx->stardis->allocator, name); + MEM_RM(dump_ctx->stardis->allocator, strip_type_changes); if(stream) fclose(stream); return res; error: @@ -604,7 +689,7 @@ dump_sample_end pos = pt.data.itfrag.fragment.P; d__ = sdis_data_get(data); id = d__->desc_id; - CHK(DESC_IS_T(descs[id].type) || DESC_IS_H(descs[id].type)); + CHK(DESC_IS_T(descs+id) || DESC_IS_H(descs+id)); break; } case SDIS_VERTEX: @@ -689,7 +774,7 @@ dump_sample data = sdis_interface_get_data(pt.data.itfrag.intface); 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)); + CHK(DESC_IS_T(descs+desc_id) || DESC_IS_H(descs+desc_id)); header.sample_end_description_id = desc_id; header.at_initial = 0; break; @@ -1177,7 +1262,7 @@ dump_boundaries_at_the_end_of_vtk ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, t, descr)); if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY - && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + && DESC_IS_BOUNDARY(descriptions+descr[SG3D_INTFACE])) /* Descriptions are numbered from 1 in the log (so the 1+ below) */ fprintf(stream, "%u\n", 1 + descr[SG3D_INTFACE]); else fprintf(stream, "%u\n", SG3D_UNSPECIFIED_PROPERTY); @@ -1382,7 +1467,7 @@ dump_enclosure_related_stuff_at_the_end_of_vtk if(descr[SG3D_FRONT] != SG3D_UNSPECIFIED_PROPERTY) description_get_medium_id(descriptions + descr[SG3D_FRONT], &fmid); else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY - && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + && DESC_IS_BOUNDARY(descriptions+descr[SG3D_INTFACE])) { description_get_medium_id(descriptions + descr[SG3D_INTFACE], &fmid); } @@ -1390,7 +1475,7 @@ dump_enclosure_related_stuff_at_the_end_of_vtk if(descr[SENC3D_BACK] != SG3D_UNSPECIFIED_PROPERTY) description_get_medium_id(descriptions + descr[SENC3D_BACK], &bmid); else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY - && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + && DESC_IS_BOUNDARY(descriptions+descr[SG3D_INTFACE])) { description_get_medium_id(descriptions + descr[SG3D_INTFACE], &bmid); } @@ -1402,7 +1487,7 @@ dump_enclosure_related_stuff_at_the_end_of_vtk if(descr[SG3D_FRONT] != SG3D_UNSPECIFIED_PROPERTY) description_get_medium_id(descriptions + descr[SG3D_FRONT], &mid); else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY - && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + && DESC_IS_BOUNDARY(descriptions+descr[SG3D_INTFACE])) { description_get_medium_id(descriptions + descr[SG3D_INTFACE], &mid); } @@ -1413,7 +1498,7 @@ dump_enclosure_related_stuff_at_the_end_of_vtk if(descr[SENC3D_BACK] != SG3D_UNSPECIFIED_PROPERTY) description_get_medium_id(descriptions + descr[SENC3D_BACK], &mid); else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY - && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + && DESC_IS_BOUNDARY(descriptions+descr[SG3D_INTFACE])) { description_get_medium_id(descriptions + descr[SG3D_INTFACE], &mid); } diff --git a/src/stardis-output.h b/src/stardis-output.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -39,50 +39,50 @@ struct dump_path_context { struct stardis* stardis; }; -extern res_T +res_T dump_path (const struct sdis_heat_path* path, void* context); -extern res_T +res_T print_sample (struct sdis_green_path* path, void* ctx); -extern res_T +res_T dump_vtk_image (const struct sdis_estimator_buffer* buf, FILE* stream); -extern res_T +res_T dump_ht_image (const struct sdis_estimator_buffer* buf, FILE* stream); -extern res_T +res_T dump_green_ascii (struct sdis_green_function* green, const struct stardis* stardis, FILE* stream); -extern res_T +res_T dump_green_bin (struct sdis_green_function* green, const struct stardis* stardis, FILE* stream); -extern res_T +res_T dump_paths_end (struct sdis_green_function* green, const struct stardis* stardis, FILE* stream); -extern res_T +res_T dump_enclosure_related_stuff_at_the_end_of_vtk (struct stardis* stardis, FILE* stream); -extern res_T +res_T print_computation_time (struct sdis_estimator* estimator, /* Can be NULL */ struct stardis* stardis, @@ -91,39 +91,39 @@ print_computation_time struct time* computation_end, struct time* output_end); /* Can be NULL */ -extern res_T +res_T print_single_MC_result (struct sdis_estimator* estimator, struct stardis* stardis, FILE* stream); -extern res_T +res_T dump_map (const struct stardis* stardis, const struct darray_estimators* estimators, FILE* stream); -extern res_T +res_T dump_boundaries_at_the_end_of_vtk (const struct stardis* stardis, FILE* stream); -extern res_T +res_T dump_compute_region_at_the_end_of_vtk (struct stardis* stardis, FILE* stream); -extern res_T +res_T dump_model_as_c_chunks (struct stardis* stardis, FILE* stream); -extern res_T +res_T write_random_generator_state (struct sdis_estimator* estimator, FILE* stream); -extern res_T +res_T read_random_generator_state (struct ssp_rng* state, FILE* stream); diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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,18 +13,39 @@ * 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-args.h" +#include "stardis-description.h" +#include "stardis-hbound.h" +#include "stardis-hbound-prog.h" +#include "stardis-hfbound.h" +#include "stardis-hfbound-prog.h" +#include "stardis-tbound.h" +#include "stardis-tbound-prog.h" +#include "stardis-fbound.h" +#include "stardis-fbound-prog.h" +#include "stardis-sfconnect.h" +#include "stardis-sfconnect-prog.h" +#include "stardis-ssconnect.h" +#include "stardis-ssconnect-prog.h" +#include "stardis-fluid-prog.h" +#include "stardis-fluid.h" +#include "stardis-solid-prog.h" +#include "stardis-solid.h" +#include "stardis-program.h" #include "stardis-default.h" #include "stardis-green-types.h" +#include <rsys/rsys.h> #include <rsys/cstr.h> #include <rsys/double2.h> #include <rsys/double3.h> #include <rsys/logger.h> +#include <rsys/text_reader.h> +#include <rsys/library.h> -#include <getopt.h> +#include <wordexp.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> @@ -33,30 +54,12 @@ #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 ******************************************************************************/ - -void -add_geom_ctx_indices - (const unsigned itri, - unsigned ids[3], - void* context) -{ - const struct add_geom_ctx* ctx = context; - const unsigned* trg; - int i; - ASSERT(ids && ctx); - ASSERT(itri < ctx->stl_desc.triangles_count); - trg = ctx->stl_desc.indices + 3 * itri; - for(i = 0; i < 3; i++) ids[i] = trg[i]; -} - -void +static void add_geom_ctx_properties (const unsigned itri, unsigned prop[3], @@ -70,20 +73,6 @@ add_geom_ctx_properties for(i = 0; i < SG3D_PROP_TYPES_COUNT__; i++) prop[i] = ctx->properties[i]; } -void -add_geom_ctx_position - (const unsigned ivert, - double pos[3], - void* context) -{ - const struct add_geom_ctx* ctx = context; - const float* v; - ASSERT(pos && ctx); - ASSERT(ivert < ctx->stl_desc.vertices_count); - v = ctx->stl_desc.vertices + 3 * ivert; - d3_set_f3(pos, v); -} - static res_T add_geom_keep_degenerated (const unsigned itri, @@ -92,7 +81,6 @@ add_geom_keep_degenerated { const struct add_geom_ctx* ctx = context; struct darray_uint* degenerated; - ASSERT(abort && ctx && ctx->custom); (void)abort; ASSERT(itri < ctx->stl_desc.triangles_count); degenerated = ctx->custom; @@ -104,9 +92,10 @@ read_sides_and_files (struct stardis* stardis, const int descr_is_intface, /* if 1, don't read side */ const unsigned description_id, - char** tok_ctx) + wordexp_t* pwordexp, + size_t* idx) { - char* tk = NULL; + char* arg = NULL; int file_count = 0; struct sstl* sstl = NULL; struct add_geom_ctx add_geom_ctx; @@ -116,7 +105,7 @@ read_sides_and_files struct str str; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp && idx); darray_uint_init(stardis->allocator, &degenerated); str_init(stardis->allocator, &str); @@ -138,8 +127,9 @@ read_sides_and_files add_geom_ctx.properties[SG3D_BACK] = SG3D_UNSPECIFIED_PROPERTY; add_geom_ctx.properties[SG3D_INTFACE] = description_id; } else { - tk = strtok_r(NULL, " \t", tok_ctx); - if(!tk) { + if(pwordexp->we_wordc <= *idx + || 0 == strcasecmp((arg = pwordexp->we_wordv[(*idx)++]), "PROG_PARAMS")) + { if(file_count == 0) { /* At least 1 side */ logger_print(stardis->logger, LOG_ERROR, @@ -150,29 +140,30 @@ read_sides_and_files else break; } add_geom_ctx.properties[SG3D_INTFACE] = SG3D_UNSPECIFIED_PROPERTY; - if(0 == strcasecmp(tk, "FRONT")) { + if(0 == strcasecmp(arg, "FRONT")) { add_geom_ctx.properties[SG3D_FRONT] = description_id; add_geom_ctx.properties[SG3D_BACK] = SG3D_UNSPECIFIED_PROPERTY; } - else if(0 == strcasecmp(tk, "BACK")) { + else if(0 == strcasecmp(arg, "BACK")) { add_geom_ctx.properties[SG3D_FRONT] = SG3D_UNSPECIFIED_PROPERTY; add_geom_ctx.properties[SG3D_BACK] = description_id; } - else if(0 == strcasecmp(tk, "BOTH")) { + else if(0 == strcasecmp(arg, "BOTH")) { add_geom_ctx.properties[SG3D_FRONT] = description_id; add_geom_ctx.properties[SG3D_BACK] = description_id; } else { logger_print(stardis->logger, LOG_ERROR, - "Invalid side specifier: %s\n", tk); + "Invalid side specifier: %s\n", arg); res = RES_BAD_ARG; goto error; } } - tk = strtok_r(NULL, " \t", tok_ctx); - if(!tk) { - if(!descr_is_intface /* Has read a side */ - || !file_count) /* Need at least 1 file */ + if(pwordexp->we_wordc <= *idx + || 0 == strcasecmp((arg = pwordexp->we_wordv[(*idx)++]), "PROG_PARAMS")) + { + if(!descr_is_intface /* Has read a side specifier */ + || !file_count) /* Need at least 1 file name */ { logger_print(stardis->logger, LOG_ERROR, "Invalid data (missing token 'file name')\n"); @@ -182,15 +173,19 @@ read_sides_and_files else break; } file_count++; - res = sstl_load(sstl, tk); - if(res != RES_OK) { + res = sstl_load(sstl, arg); + if(res == RES_OK) { + ERR(sstl_get_desc(sstl, &add_geom_ctx.stl_desc)); + ASSERT(add_geom_ctx.stl_desc.vertices_count <= UINT_MAX + && add_geom_ctx.stl_desc.triangles_count <= UINT_MAX); + logger_print(stardis->logger, LOG_OUTPUT, + "Read file '%s': %u triangles found.\n", + arg, (unsigned)add_geom_ctx.stl_desc.triangles_count); + } else { logger_print(stardis->logger, LOG_ERROR, - "Cannot read STL file: '%s'\n", tk); + "Cannot read STL file: '%s'\n", arg); goto error; } - ERR(sstl_get_desc(sstl, &add_geom_ctx.stl_desc)); - ASSERT(add_geom_ctx.stl_desc.vertices_count <= UINT_MAX - && add_geom_ctx.stl_desc.triangles_count <= UINT_MAX); res = sg3d_geometry_add( stardis->geometry.sg3d, @@ -205,16 +200,16 @@ read_sides_and_files ASSERT(c <= ULONG_MAX); logger_print(stardis->logger, LOG_WARNING, "File '%s' included %lu degenerated triangles (removed)\n", - tk, (unsigned long)c); + arg, (unsigned long)c); ERR(str_printf(&str, "Degenerated triangles IDs: %u", ids[0])); - FOR_EACH(n, 1, c) { STR_APPEND_PRINTF(&str, ", %u", ARG1( ids[n] ) ); } + FOR_EACH(n, 1, c) { ERR(str_append_printf(&str, ", %u", ids[n])); } logger_print(stardis->logger, LOG_OUTPUT, "%s\n", str_cget(&str)); darray_uint_clear(&degenerated); } if(res != RES_OK) { logger_print(stardis->logger, LOG_ERROR, - "Cannot add file content: '%s'\n", tk); + "Cannot add file content: '%s'\n", arg); goto error; } /* Check conflicts */ @@ -225,7 +220,7 @@ read_sides_and_files (stardis->mode & COMPUTE_MODES) && !(stardis->mode & MODE_DUMP_VTK); logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), "Merge conflicts found reading file '%s' (%u triangles).\n", - tk, merge_errors - current_merge_errors); + arg, merge_errors - current_merge_errors); if(is_for_compute) { res = RES_BAD_ARG; goto error; @@ -246,35 +241,67 @@ error: /******************************************************************************* * Public Functions ******************************************************************************/ +void +add_geom_ctx_position + (const unsigned ivert, + double pos[3], + void* context) +{ + const struct add_geom_ctx* ctx = context; + const float* v; + ASSERT(pos && ctx); + ASSERT(ivert < ctx->stl_desc.vertices_count); + v = ctx->stl_desc.vertices + 3 * ivert; + d3_set_f3(pos, v); +} + +void +add_geom_ctx_indices + (const unsigned itri, + unsigned ids[3], + void* context) +{ + const struct add_geom_ctx* ctx = context; + const unsigned* trg; + int i; + ASSERT(ids && ctx); + ASSERT(itri < ctx->stl_desc.triangles_count); + trg = ctx->stl_desc.indices + 3 * itri; + for(i = 0; i < 3; i++) ids[i] = trg[i]; +} static res_T description_set_name (struct stardis* stardis, struct str* name, - const char* tk) + const char* arg) { res_T res = RES_OK; double foo; 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", "SOLID_SOLID_CONNECTION", "TRAD", - "T_BOUNDARY_FOR_SOLID", "UNKNOWN" }; + "AUTO", "BACK", "BOTH", "FLUID", "FLUID_PROG", "FRONT", "F_BOUNDARY_FOR_SOLID", + "F_BOUNDARY_FOR_SOLID_PROG", "H_BOUNDARY_FOR_FLUID", "H_BOUNDARY_FOR_FLUID_PROG", + "HF_BOUNDARY_FOR_SOLID", "HF_BOUNDARY_FOR_SOLID_PROG", + "H_BOUNDARY_FOR_SOLID", "H_BOUNDARY_FOR_SOLID_PROG", "PROGRAM", "PROG_PARAMS", + "SCALE", "SOLID", "SOLID_PROG", "SOLID_FLUID_CONNECTION", + "SOLID_FLUID_CONNECTION_PROG", "SOLID_SOLID_CONNECTION", + "SOLID_SOLID_CONNECTION_PROG", "TRAD", "T_BOUNDARY_FOR_SOLID", + "T_BOUNDARY_FOR_SOLID_PROG", "UNKNOWN" }; const char* reason = NULL; - int i; - ASSERT(name && tk); + size_t i; + ASSERT(name && arg); /* Use name before uppercasing it */ - ERR(str_set(name, tk)); + ERR(str_set(name, arg)); - if(RES_OK == cstr_to_double(tk, &foo)) { + if(RES_OK == cstr_to_double(arg, &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])) { + if(0 == strcasecmp(arg, keywords[i])) { /* A keyword is not a sensible choice for a name! */ res = RES_BAD_ARG; reason = "reserved keyword"; @@ -294,7 +321,7 @@ end: error: ASSERT(reason != NULL); logger_print(stardis->logger, LOG_ERROR, "Invalid name (%s): %s\n", - reason, tk); + reason, arg); goto end; } @@ -305,7 +332,7 @@ find_description_by_name const struct description* self) { size_t i; - ASSERT(stardis && name && self); + ASSERT(stardis && name); FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) { struct description* desc @@ -324,110 +351,658 @@ static res_T process_h (struct stardis* stardis, const enum description_type type, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct h_boundary* h_boundary; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.hbound_count++; sz = darray_descriptions_size_get(&stardis->descriptions); ERR(darray_descriptions_resize(&stardis->descriptions, sz+1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; - ERR(init_h(stardis->allocator, &desc->d.h_boundary)); + ERR(init_h_boundary(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, &h_boundary->name, tk)); + CHK_ARG(idx, "h boundary name"); + ERR(description_set_name(stardis, &h_boundary->name, arg)); if(find_description_by_name(stardis, &h_boundary->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); 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); + CHK_ARG(idx, "ref_temperature"); + res = cstr_to_double(arg, &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); + logger_print(stardis->logger, LOG_ERROR, + "Invalid reference temperature: %s\n", arg); 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, &h_boundary->emissivity); + CHK_ARG(idx, "emissivity"); + res = cstr_to_double(arg, &h_boundary->emissivity); if(res != RES_OK || h_boundary->emissivity < 0 || h_boundary->emissivity > 1) { - logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", arg); 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, &h_boundary->specular_fraction); + CHK_ARG(idx, "specular fraction"); + res = cstr_to_double(arg, &h_boundary->specular_fraction); if(res != RES_OK || h_boundary->specular_fraction < 0 || h_boundary->specular_fraction > 1) { logger_print(stardis->logger, LOG_ERROR, - "Invalid specular fraction: %s\n", tk); - if(res == RES_OK) res = RES_BAD_ARG; - goto end; - } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc"); - res = cstr_to_double(tk, &h_boundary->hc); - if(res != RES_OK - || h_boundary->hc < 0) - { - logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk); + "Invalid specular fraction: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_ARG(idx, "Convection coefficient"); + res = cstr_to_double(arg, &h_boundary->hc); + if(res != RES_OK + || h_boundary->hc < 0) + { + logger_print(stardis->logger, LOG_ERROR, + "Invalid Convection coefficient: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_ARG(idx, "temperature"); + res = cstr_to_double(arg, &h_boundary->imposed_temperature); + if(res != RES_OK + || h_boundary->imposed_temperature < 0) + { + logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", arg); + 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) + ERR(get_dummy_solid_id(stardis, &h_boundary->mat_id)); + else { + struct fluid* fluid = NULL; + ASSERT(type == DESC_BOUND_H_FOR_SOLID); + 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->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->imposed_temperature, + fluid->fluid_id); + } + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* HF_BOUNDARY_FOR_SOLID Name ref_temperature emissivity specular_fraction hc + * T_env flux STL_filenames */ +static res_T +process_hf + (struct stardis* stardis, + const enum description_type type, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + size_t sz; + struct hf_boundary* hf_boundary; + size_t idx = 1; + struct fluid* fluid = NULL; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.hbound_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz+1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_hf_boundary(stardis->allocator, &desc->d.hf_boundary)); + hf_boundary = desc->d.hf_boundary; + desc->type = type; + + CHK_ARG(idx, "hf boundary name"); + ERR(description_set_name(stardis, &hf_boundary->name, arg)); + if(find_description_by_name(stardis, &hf_boundary->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + + CHK_ARG(idx, "ref_temperature"); + res = cstr_to_double(arg, &hf_boundary->ref_temperature); + if(res != RES_OK + || hf_boundary->ref_temperature < 0) + { + logger_print(stardis->logger, LOG_ERROR, + "Invalid reference temperature: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + stardis->t_range[0] = MMIN(stardis->t_range[0], hf_boundary->ref_temperature); + stardis->t_range[1] = MMAX(stardis->t_range[1], hf_boundary->ref_temperature); + CHK_ARG(idx, "emissivity"); + res = cstr_to_double(arg, &hf_boundary->emissivity); + if(res != RES_OK + || hf_boundary->emissivity < 0 + || hf_boundary->emissivity > 1) + { + logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_ARG(idx, "specular fraction"); + res = cstr_to_double(arg, &hf_boundary->specular_fraction); + if(res != RES_OK + || hf_boundary->specular_fraction < 0 + || hf_boundary->specular_fraction > 1) + { + logger_print(stardis->logger, LOG_ERROR, + "Invalid specular fraction: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_ARG(idx, "convection coefficient"); + res = cstr_to_double(arg, &hf_boundary->hc); + if(res != RES_OK + || hf_boundary->hc < 0) + { + logger_print(stardis->logger, LOG_ERROR, + "Invalid convection coefficient: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_ARG(idx, "temperature"); + res = cstr_to_double(arg, &hf_boundary->imposed_temperature); + if(res != RES_OK + || hf_boundary->imposed_temperature < 0) + { + logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_ARG(idx, "flux"); + res = cstr_to_double(arg, &hf_boundary->imposed_flux); + if(res != RES_OK + || hf_boundary->imposed_flux == SDIS_FLUX_NONE) { + /* Flux can be < 0 but not undefined */ + logger_print(stardis->logger, LOG_ERROR, + "Invalid flux: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + stardis->t_range[0] = MMIN(stardis->t_range[0], hf_boundary->imposed_temperature); + stardis->t_range[1] = MMAX(stardis->t_range[1], hf_boundary->imposed_temperature); + + ASSERT(type == DESC_BOUND_HF_FOR_SOLID); + ERR(init_fluid(stardis->allocator, &fluid)); + fluid->fluid_id = allocate_stardis_medium_id(stardis); + hf_boundary->mat_id = fluid->fluid_id; + hf_boundary->possible_external_fluid = fluid; + ASSERT(sz <= UINT_MAX); + fluid->desc_id = (unsigned)sz; + fluid->imposed_temperature = hf_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->imposed_temperature, + fluid->fluid_id); + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +static res_T +set_argc_argv + (struct mem_allocator* allocator, + size_t* argc, + char** argv[], + const wordexp_t* pwordexp, + size_t idx) +{ + size_t i, n; + res_T res = RES_OK; + + ASSERT(argc && argv && pwordexp); + *argv = NULL; + + if(pwordexp->we_wordc < idx) { + res = RES_BAD_ARG; + goto error; + } + *argc = pwordexp->we_wordc - idx; + *argv = MEM_CALLOC(allocator, 1 + *argc, sizeof(char *)); + if(*argv == NULL) { + res = RES_MEM_ERR; + goto error; + } + for(i = idx, n = 0; i < pwordexp->we_wordc; i++, n++) { + (*argv)[n] = MEM_CALLOC(allocator, 1, 1 + strlen(pwordexp->we_wordv[i])); + if((*argv)[n] == NULL) { + res = RES_MEM_ERR; + goto error; + } + strcpy((*argv)[n], pwordexp->we_wordv[i]); /* size is adequate */ + } +end: + return res; +error: + if(*argv) { + for(i = 0; i < *argc; i++) + if((*argv)[i]) MEM_RM(allocator, (*argv)[i]); + MEM_RM(allocator, *argv); + } + goto end; +} + +/* utility macros */ +#define GET_LIB_SYMBOL_BASE(DestField, LibHandle, FunName, Optional) \ + *(void**)DestField = library_get_symbol((LibHandle), #FunName ); \ + if(!*DestField && !(Optional)) { \ + logger_print(stardis->logger, LOG_ERROR, \ + "Cannot find function '" #FunName "()' in lib %s\n", lib_name); \ + res = RES_BAD_ARG; \ + goto error; \ + } + +#define GET_LIB_SYMBOL(Dest, Field, FunName) \ + GET_LIB_SYMBOL_BASE(&((Dest)->Field), (Dest)->program->lib_handle, FunName, 0) + +#define CREATE_DESC_DATA_BASE(Desc, CreateArgs) \ + (Desc)->prog_data = (Desc)->create(&ctx, CreateArgs); \ + if(!(Desc)->prog_data) { \ + logger_print(stardis->logger, LOG_ERROR, \ + "Cannot create data for description %s\n", str_cget(&(Desc)->name)); \ + res = RES_BAD_ARG; \ + goto error; \ + } + +#define CREATE_DESC_DATA(Desc) \ + CREATE_DESC_DATA_BASE(Desc, \ + LIST_ARG3((Desc)->program->prog_data, (Desc)->argc, (Desc)->argv)) + +/* The returned program is NULL if no stardis_create_program function is + * defined in the library. */ +static res_T +get_prog_common + (const char* lib_name, + struct stardis* stardis, + struct program** program, + void* (**create) + (const struct stardis_description_create_context*, void*, size_t, char**), + void (**release)(void*)) +{ + res_T res = RES_OK; + struct description* desc; + struct str tmp; + + ASSERT(lib_name && program && create && release && stardis); + + /* get the library handler */ + str_init(stardis->allocator, &tmp); + ERR(str_set(&tmp, lib_name)); + desc = find_description_by_name(stardis, &tmp, NULL); + if(!desc) { + logger_print(stardis->logger, LOG_ERROR, + "Undefined PROGRAM: %s\n", lib_name); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + else if(desc->type != DESC_PROGRAM) { + logger_print(stardis->logger, LOG_ERROR, + "Is not a PROGRAM: %s\n", lib_name); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + *program = desc->d.program; + /* get the mandatory user-defined functions from the library */ + GET_LIB_SYMBOL_BASE(create, (*program)->lib_handle, stardis_create_data, 0); + GET_LIB_SYMBOL_BASE(release, (*program)->lib_handle, stardis_release_data, 0); + +end: + str_release(&tmp); + return res; +error: + goto end; +} + +/* PROGRAM Name library_path [...] */ +static res_T +process_program + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + size_t sz; + struct program* program; + const char* lib_name; + const char* lic; + const char* _c_; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_program(stardis->allocator, &desc->d.program)); + program = desc->d.program; + desc->type = DESC_PROGRAM; + + CHK_ARG(idx, "program name"); + ERR(description_set_name(stardis, &program->name, arg)); + if(find_description_by_name(stardis, &program->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + lib_name = arg; + + CHK_ARG(idx, "library path"); + ERR(str_set(&program->lib_path, arg)); + + /* get the library handler */ + program->lib_handle = library_open(arg); + if(!program->lib_handle) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot open library: %s (%s)\n", lib_name, arg); + res = RES_BAD_ARG; + goto error; + } + + /* get the mandatory user-defined functions from the library */ + GET_LIB_SYMBOL_BASE(&program->get_copyright_notice, program->lib_handle, + get_copyright_notice, 0); + GET_LIB_SYMBOL_BASE(&program->get_license_short, program->lib_handle, + get_license_short, 0); + GET_LIB_SYMBOL_BASE(&program->get_license_text, program->lib_handle, + get_license_text, 0); + /* get the optional user-defined functions from the library */ + GET_LIB_SYMBOL_BASE(&program->create, + program->lib_handle, stardis_create_library_data, 1); + GET_LIB_SYMBOL_BASE(&program->release, + program->lib_handle, stardis_release_library_data, 1); + GET_LIB_SYMBOL_BASE(&program->finalize, + program->lib_handle, stardis_finalize_library_data, 1); + if(!(program->create && program->release && program->finalize) + && !(!program->create && !program->release && !program->finalize)) + { + logger_print(stardis->logger, LOG_ERROR, + "Inconsistent library data management for library '%s'.\n", + lib_name); + logger_print(stardis->logger, LOG_ERROR, + "Please define all or none of stardis_create_library_data, " + "stardis_finalize_library_data and stardis_release_library_data funcions.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &program->argc, &program->argv, + pwordexp, idx)); + if(program->create) { + /* create and init custom data */ + struct stardis_program_context ctx; + ctx.name = lib_name; + switch(stardis->verbose) { + case 0: ctx.verbosity_level = STARDIS_VERBOSE_NONE; break; + case 1: ctx.verbosity_level = STARDIS_VERBOSE_ERROR; break; + case 2: ctx.verbosity_level = STARDIS_VERBOSE_WARNING; break; + case 3: ctx.verbosity_level = STARDIS_VERBOSE_INFO; break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } + CREATE_DESC_DATA_BASE(program, LIST_ARG2(program->argc, program->argv)); + } else if(program->argc != 0) { + logger_print(stardis->logger, LOG_ERROR, + "Library '%s' has no custom data management functions but has arguments:\n", + lib_name); + for( ; idx < pwordexp->we_wordc; idx++) { + logger_print(stardis->logger, LOG_ERROR, "%s\n", pwordexp->we_wordv[idx]); + } + res = RES_BAD_ARG; + goto error; + } + + lic = program->get_license_short(program->prog_data); + _c_ = program->get_copyright_notice(program->prog_data); + if(!lic) { + res = RES_BAD_ARG; + goto error; + } + if(!_c_) { + res = RES_BAD_ARG; + goto error; + } + logger_print(stardis->logger, LOG_OUTPUT, + "Loading external library '%s': \"%s\"\n", + str_cget(&program->name), str_cget(&program->lib_path)); + logger_print(stardis->logger, LOG_OUTPUT, " %s\n", _c_); + logger_print(stardis->logger, LOG_OUTPUT, " %s\n", lic); + +end: + return res; +error: + goto end; +} + +/* H_BOUNDARY_FOR_SOLID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] + * H_BOUNDARY_FOR_FLUID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_h_prog + (struct stardis* stardis, + const enum description_type type, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct h_boundary_prog* h_boundary_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.fmed_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_h_boundary_prog(stardis->allocator, &desc->d.h_boundary_prog)); + h_boundary_prog = desc->d.h_boundary_prog; + desc->type = type; + + CHK_ARG(idx, "programmed h boundary name"); + ERR(description_set_name(stardis, &h_boundary_prog->name, arg)); + if(find_description_by_name(stardis, &h_boundary_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + desc_name = arg; + + CHK_ARG(idx, "program name"); + ERR(str_set(&h_boundary_prog->prog_name, arg)); + lib_name = arg; + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &h_boundary_prog->argc, + &h_boundary_prog->argv, pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &h_boundary_prog->program, + &h_boundary_prog->create, &h_boundary_prog->release)); + GET_LIB_SYMBOL(h_boundary_prog, ref_temp, stardis_reference_temperature); + GET_LIB_SYMBOL(h_boundary_prog, emissivity, stardis_emissivity); + GET_LIB_SYMBOL(h_boundary_prog, alpha, stardis_specular_fraction); + GET_LIB_SYMBOL(h_boundary_prog, hc, stardis_convection_coefficient); + GET_LIB_SYMBOL(h_boundary_prog, hmax, stardis_max_convection_coefficient); + GET_LIB_SYMBOL(h_boundary_prog, t_range, stardis_t_range); + if(type == DESC_BOUND_H_FOR_FLUID_PROG) { + GET_LIB_SYMBOL(h_boundary_prog, boundary_temp, stardis_boundary_temperature); + } else { + GET_LIB_SYMBOL(h_boundary_prog, fluid_temp, stardis_medium_temperature); + } + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(h_boundary_prog); + + h_boundary_prog->t_range(h_boundary_prog->prog_data, stardis->t_range); + + /* create the media behind the interface */ + if(type == DESC_BOUND_H_FOR_FLUID_PROG) { + ERR(get_dummy_solid_id(stardis, &h_boundary_prog->mat_id)); + } else { + struct fluid_prog* fluid_prog = NULL; + ASSERT(type == DESC_BOUND_H_FOR_SOLID_PROG); + ERR(init_fluid_prog(stardis->allocator, &fluid_prog)); + fluid_prog->fluid_id = allocate_stardis_medium_id(stardis); + h_boundary_prog->mat_id = fluid_prog->fluid_id; + h_boundary_prog->possible_external_fluid = fluid_prog; + fluid_prog->desc_id = (unsigned)sz; + fluid_prog->temp = h_boundary_prog->fluid_temp; + fluid_prog->is_outside = 1; + fluid_prog->prog_data = h_boundary_prog->prog_data; + /* fluid_prog->release is NULL to avoid deleting shared prog_data */ + ERR(create_solver_external_fluid_prog(stardis, fluid_prog)); + logger_print(stardis->logger, LOG_OUTPUT, + "External programmed fluid created (it is medium %u)\n", + fluid_prog->fluid_id); + } + +end: + return res; +error: + goto end; +} + +/* HF_BOUNDARY_FOR_SOLID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_hf_prog + (struct stardis* stardis, + const enum description_type type, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct hf_boundary_prog* hf_boundary_prog; + struct stardis_description_create_context ctx; + struct fluid_prog* fluid_prog = NULL; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + ASSERT(type == DESC_BOUND_HF_FOR_SOLID_PROG); /* No HF prog for fluids */ + + stardis->counts.fmed_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_hf_boundary_prog(stardis->allocator, &desc->d.hf_boundary_prog)); + hf_boundary_prog = desc->d.hf_boundary_prog; + desc->type = type; + + CHK_ARG(idx, "programmed hf boundary name"); + ERR(description_set_name(stardis, &hf_boundary_prog->name, arg)); + if(find_description_by_name(stardis, &hf_boundary_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature"); - res = cstr_to_double(tk, &h_boundary->imposed_temperature); - if(res != RES_OK - || 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); + desc_name = arg; - if(type == DESC_BOUND_H_FOR_FLUID) - ERR(get_dummy_solid_id(stardis, &h_boundary->mat_id)); - else { - 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->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->imposed_temperature, - fluid->fluid_id); - } + CHK_ARG(idx, "program name"); + ERR(str_set(&hf_boundary_prog->prog_name, arg)); + lib_name = arg; ASSERT(sz <= UINT_MAX); - ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &hf_boundary_prog->argc, + &hf_boundary_prog->argv, pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &hf_boundary_prog->program, + &hf_boundary_prog->create, &hf_boundary_prog->release)); + GET_LIB_SYMBOL(hf_boundary_prog, ref_temp, stardis_reference_temperature); + GET_LIB_SYMBOL(hf_boundary_prog, emissivity, stardis_emissivity); + GET_LIB_SYMBOL(hf_boundary_prog, alpha, stardis_specular_fraction); + GET_LIB_SYMBOL(hf_boundary_prog, hc, stardis_convection_coefficient); + GET_LIB_SYMBOL(hf_boundary_prog, hmax, stardis_max_convection_coefficient); + GET_LIB_SYMBOL(hf_boundary_prog, flux, stardis_boundary_flux); + GET_LIB_SYMBOL(hf_boundary_prog, t_range, stardis_t_range); + GET_LIB_SYMBOL(hf_boundary_prog, fluid_temp, stardis_medium_temperature); + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(hf_boundary_prog); + + hf_boundary_prog->t_range(hf_boundary_prog->prog_data, stardis->t_range); + + /* create the media behind the interface */ + ERR(init_fluid_prog(stardis->allocator, &fluid_prog)); + fluid_prog->fluid_id = allocate_stardis_medium_id(stardis); + hf_boundary_prog->mat_id = fluid_prog->fluid_id; + hf_boundary_prog->possible_external_fluid = fluid_prog; + fluid_prog->desc_id = (unsigned)sz; + fluid_prog->temp = hf_boundary_prog->fluid_temp; + fluid_prog->is_outside = 1; + fluid_prog->prog_data = hf_boundary_prog->prog_data; + /* fluid_prog->release is NULL to avoid deleting shared prog_data */ + ERR(create_solver_external_fluid_prog(stardis, fluid_prog)); + logger_print(stardis->logger, LOG_OUTPUT, + "External programmed fluid created (it is medium %u)\n", + fluid_prog->fluid_id); end: return res; @@ -439,42 +1014,44 @@ error: static res_T process_t (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct t_boundary* t_boundary; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.tbound_count++; sz = darray_descriptions_size_get(&stardis->descriptions); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; - ERR(init_t(stardis->allocator, &desc->d.t_boundary)); + ERR(init_t_boundary(stardis->allocator, &desc->d.t_boundary)); t_boundary = desc->d.t_boundary; desc->type = DESC_BOUND_T_FOR_SOLID; 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, &t_boundary->name, tk)); + + CHK_ARG(idx, "temperature boundary name"); + ERR(description_set_name(stardis, &t_boundary->name, arg)); if(find_description_by_name(stardis, &t_boundary->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature"); - res = cstr_to_double(tk, &t_boundary->imposed_temperature); + CHK_ARG(idx, "temperature"); + res = cstr_to_double(arg, &t_boundary->imposed_temperature); if(res != RES_OK || t_boundary->imposed_temperature < 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -482,7 +1059,72 @@ process_t 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)); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* T_BOUNDARY_FOR_SOLID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_t_prog + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct t_boundary_prog* t_boundary_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.fmed_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_t_boundary_prog(stardis->allocator, &desc->d.t_boundary_prog)); + t_boundary_prog = desc->d.t_boundary_prog; + desc->type = DESC_BOUND_T_FOR_SOLID_PROG; + + ERR(get_dummy_fluid_id(stardis, &t_boundary_prog->mat_id)); + + CHK_ARG(idx, "programmed t boundary name"); + ERR(description_set_name(stardis, &t_boundary_prog->name, arg)); + if(find_description_by_name(stardis, &t_boundary_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + desc_name = arg; + + CHK_ARG(idx, "program name"); + ERR(str_set(&t_boundary_prog->prog_name, arg)); + lib_name = arg; + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &t_boundary_prog->argc, + &t_boundary_prog->argv, pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &t_boundary_prog->program, + &t_boundary_prog->create, &t_boundary_prog->release)); + GET_LIB_SYMBOL(t_boundary_prog, temperature, stardis_boundary_temperature); + GET_LIB_SYMBOL(t_boundary_prog, t_range, stardis_t_range); + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(t_boundary_prog); + + t_boundary_prog->t_range(t_boundary_prog->prog_data, stardis->t_range); end: return res; @@ -494,43 +1136,44 @@ error: static res_T process_flx (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct f_boundary* f_boundary; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.fbound_count++; sz = darray_descriptions_size_get(&stardis->descriptions); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; - ERR(init_f(stardis->allocator, &desc->d.f_boundary)); + ERR(init_f_boundary(stardis->allocator, &desc->d.f_boundary)); f_boundary = desc->d.f_boundary; desc->type = DESC_BOUND_F_FOR_SOLID; 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, &f_boundary->name, tk)); + CHK_ARG(idx, "flux boundary name"); + ERR(description_set_name(stardis, &f_boundary->name, arg)); if(find_description_by_name(stardis, &f_boundary->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "flux"); - res = cstr_to_double(tk, &f_boundary->imposed_flux); + CHK_ARG(idx, "flux"); + res = cstr_to_double(arg, &f_boundary->imposed_flux); if(res != RES_OK || 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); + logger_print(stardis->logger, LOG_ERROR, "Invalid flux: %s\n", arg); goto end; } if(f_boundary->imposed_flux != 0 && stardis->picard_order > 1) { @@ -543,7 +1186,70 @@ process_flx } ASSERT(sz <= UINT_MAX); - ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* F_BOUNDARY_FOR_SOLID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_flx_prog + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct f_boundary_prog* f_boundary_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.fmed_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_f_boundary_prog(stardis->allocator, &desc->d.f_boundary_prog)); + f_boundary_prog = desc->d.f_boundary_prog; + desc->type = DESC_BOUND_F_FOR_SOLID_PROG; + + ERR(get_dummy_fluid_id(stardis, &f_boundary_prog->mat_id)); + + CHK_ARG(idx, "programmed t boundary name"); + ERR(description_set_name(stardis, &f_boundary_prog->name, arg)); + if(find_description_by_name(stardis, &f_boundary_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + + CHK_ARG(idx, "program name"); + ERR(str_set(&f_boundary_prog->prog_name, arg)); + desc_name = arg; + desc_name = arg; + lib_name = arg; + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &f_boundary_prog->argc, + &f_boundary_prog->argv, pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &f_boundary_prog->program, + &f_boundary_prog->create, &f_boundary_prog->release)); + GET_LIB_SYMBOL(f_boundary_prog, flux, stardis_boundary_flux); + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(f_boundary_prog); end: return res; @@ -555,22 +1261,23 @@ error: static res_T process_sfc (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct solid_fluid_connect* sf_connect; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.sfconnect_count++; sz = darray_descriptions_size_get(&stardis->descriptions); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; - ERR(init_sf(stardis->allocator, &desc->d.sf_connect)); + ERR(init_sf_connect(stardis->allocator, &desc->d.sf_connect)); sf_connect = desc->d.sf_connect; desc->type = DESC_SOLID_FLUID_CONNECT; @@ -579,59 +1286,128 @@ process_sfc * we continue the trend to ensure connection ID is OK */ 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, &sf_connect->name, tk)); + CHK_ARG(idx, "solid-fluid connection name"); + ERR(description_set_name(stardis, &sf_connect->name, arg)); if(find_description_by_name(stardis, &sf_connect->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); 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); + CHK_ARG(idx, "ref_temperature"); + res = cstr_to_double(arg, &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); + logger_print(stardis->logger, LOG_ERROR, + "Invalid reference temperature: %s\n", arg); 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, &sf_connect->emissivity); + CHK_ARG(idx, "emissivity"); + res = cstr_to_double(arg, &sf_connect->emissivity); if(res != RES_OK || sf_connect->emissivity < 0 || sf_connect->emissivity > 1) { - logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", arg); 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, &sf_connect->specular_fraction); + CHK_ARG(idx, "specular fraction"); + res = cstr_to_double(arg, &sf_connect->specular_fraction); if(res != RES_OK || sf_connect->specular_fraction < 0 || sf_connect->specular_fraction > 1) { logger_print(stardis->logger, LOG_ERROR, - "Invalid specular fraction: %s\n", tk); + "Invalid specular fraction: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc"); - res = cstr_to_double(tk, &sf_connect->hc); + CHK_ARG(idx, "convection coefficient"); + res = cstr_to_double(arg, &sf_connect->hc); if(res != RES_OK || sf_connect->hc < 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Invalid convection coefficient: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } ASSERT(sz <= UINT_MAX); - ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* SOLID_FLUID_CONNECTION_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_sfc_prog + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct solid_fluid_connect_prog* sf_connect_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.sfconnect_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_sf_connect_prog(stardis->allocator, &desc->d.sf_connect_prog)); + sf_connect_prog = desc->d.sf_connect_prog; + desc->type = DESC_SOLID_FLUID_CONNECT_PROG; + + CHK_ARG(idx, "programmed solid-fluid connection name"); + ERR(description_set_name(stardis, &sf_connect_prog->name, arg)); + if(find_description_by_name(stardis, &sf_connect_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + desc_name = arg; + + CHK_ARG(idx, "program name"); + ERR(str_set(&sf_connect_prog->prog_name, arg)); + lib_name = arg; + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &sf_connect_prog->argc, + &sf_connect_prog->argv, pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &sf_connect_prog->program, + &sf_connect_prog->create, &sf_connect_prog->release)); + GET_LIB_SYMBOL(sf_connect_prog, ref_temp, stardis_reference_temperature); + GET_LIB_SYMBOL(sf_connect_prog, emissivity, stardis_emissivity); + GET_LIB_SYMBOL(sf_connect_prog, alpha, stardis_specular_fraction); + GET_LIB_SYMBOL(sf_connect_prog, hc, stardis_convection_coefficient); + GET_LIB_SYMBOL(sf_connect_prog, hmax, stardis_max_convection_coefficient); + GET_LIB_SYMBOL(sf_connect_prog, t_range, stardis_t_range); + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(sf_connect_prog); + + sf_connect_prog->t_range(sf_connect_prog->prog_data, stardis->t_range); end: return res; @@ -643,22 +1419,23 @@ error: static res_T process_ssc (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct solid_solid_connect* ss_connect; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.ssconnect_count++; sz = darray_descriptions_size_get(&stardis->descriptions); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; - ERR(init_ss(stardis->allocator, &desc->d.ss_connect)); + ERR(init_ss_connect(stardis->allocator, &desc->d.ss_connect)); ss_connect = desc->d.ss_connect; desc->type = DESC_SOLID_SOLID_CONNECT; @@ -667,22 +1444,22 @@ process_ssc * we continue the trend to ensure connection ID is OK */ 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, &ss_connect->name, tk)); + CHK_ARG(idx, "solid-solid connection name"); + ERR(description_set_name(stardis, &ss_connect->name, arg)); if(find_description_by_name(stardis, &ss_connect->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "contact resistance"); - res = cstr_to_double(tk, &ss_connect->tcr); + CHK_ARG(idx, "contact resistance"); + res = cstr_to_double(arg, &ss_connect->tcr); if(res != RES_OK || ss_connect->tcr < 0) { logger_print(stardis->logger, LOG_ERROR, - "Invalid contact resistance: %s\n", tk); + "Invalid contact resistance: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -693,7 +1470,74 @@ process_ssc } ASSERT(sz <= UINT_MAX); - ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* SOLID_SOLID_CONNECTION_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_ssc_prog + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct solid_solid_connect_prog* ss_connect_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.sfconnect_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_ss_connect_prog(stardis->allocator, &desc->d.ss_connect_prog)); + ss_connect_prog = desc->d.ss_connect_prog; + desc->type = DESC_SOLID_SOLID_CONNECT_PROG; + + CHK_ARG(idx, "programmed solid-solid connection name"); + ERR(description_set_name(stardis, &ss_connect_prog->name, arg)); + if(find_description_by_name(stardis, &ss_connect_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + desc_name = arg; + + CHK_ARG(idx, "program name"); + ERR(str_set(&ss_connect_prog->prog_name, arg)); + lib_name = arg; + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &ss_connect_prog->argc, + &ss_connect_prog->argv, pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &ss_connect_prog->program, + &ss_connect_prog->create, &ss_connect_prog->release)); + GET_LIB_SYMBOL(ss_connect_prog, tcr, stardis_thermal_contact_resistance); + if(!ss_connect_prog->tcr) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot find function 'stardis_thermal_contact_resistance()' in lib %s\n", + lib_name); + res = RES_BAD_ARG; + goto error; + } + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(ss_connect_prog); end: return res; @@ -705,17 +1549,18 @@ static res_T read_imposed_temperature (struct stardis* stardis, double* imposed_temperature, - char** tok_ctx) + wordexp_t* pwordexp, + size_t* idx) { - char* tk = NULL; + char* arg = NULL; struct str keep; res_T res = RES_OK; - ASSERT(stardis && imposed_temperature && tok_ctx); + ASSERT(stardis && imposed_temperature && pwordexp); str_init(stardis->allocator, &keep); - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "imposed temperature"); - ERR(str_set(&keep, tk)); - if(RES_OK == cstr_to_double(tk, imposed_temperature)) { + CHK_ARG((*idx), "imposed temperature"); + ERR(str_set(&keep, arg)); + if(RES_OK == cstr_to_double(arg, imposed_temperature)) { /* Was a number */ if(*imposed_temperature < 0) { res = RES_BAD_ARG; @@ -723,7 +1568,7 @@ read_imposed_temperature } } else { /* Could be 'unknown' */ - if(0 == strcasecmp(tk, "UNKNOWN")) { + if(0 == strcasecmp(arg, "UNKNOWN")) { *imposed_temperature = UNKNOWN_MEDIUM_TEMPERATURE; } else { res = RES_BAD_ARG; @@ -743,17 +1588,15 @@ static res_T read_delta (struct stardis* stardis, double* delta, - char** tok_ctx) + wordexp_t* pwordexp, + size_t* idx) { - char* tk = NULL; - struct str keep; + char* arg = NULL; res_T res = RES_OK; - ASSERT(stardis && delta && tok_ctx); + ASSERT(stardis && delta && pwordexp && idx); - str_init(stardis->allocator, &keep); - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "delta"); - ERR(str_set(&keep, tk)); - if(RES_OK == cstr_to_double(tk, delta)) { + CHK_ARG((*idx), "delta"); + if(RES_OK == cstr_to_double(arg, delta)) { /* Was a number */ if(*delta <= 0) { res = RES_BAD_ARG; @@ -761,7 +1604,7 @@ read_delta } } else { /* Could be 'auto' */ - if(0 == strcasecmp(tk, "AUTO")) { + if(0 == strcasecmp(arg, "AUTO")) { /* Set to DELTA_AUTO until actual value is substituted */ *delta = DELTA_AUTO; } else { @@ -770,11 +1613,9 @@ read_delta } } end: - str_release(&keep); return res; error: - logger_print(stardis->logger, LOG_ERROR, "Invalid delta: %s\n", - str_cget(&keep)); + logger_print(stardis->logger, LOG_ERROR, "Invalid delta: %s\n", arg); goto end; } @@ -782,15 +1623,16 @@ error: static res_T process_solid (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct solid* solid; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.smed_count++; @@ -800,63 +1642,62 @@ process_solid ERR(init_solid(stardis->allocator, &desc->d.solid)); solid = desc->d.solid; desc->type = DESC_MAT_SOLID; - 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); solid->desc_id = (unsigned)sz; - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid name"); - ERR(description_set_name(stardis, &solid->name, tk)); + CHK_ARG(idx, "solid name"); + ERR(description_set_name(stardis, &solid->name, arg)); if(find_description_by_name(stardis, &solid->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "lambda"); - res = cstr_to_double(tk, &solid->lambda); + CHK_ARG(idx, "lambda"); + res = cstr_to_double(arg, &solid->lambda); if(res != RES_OK || solid->lambda <= 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid lambda: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid lambda: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "rho"); - res = cstr_to_double(tk, &solid->rho); + CHK_ARG(idx, "rho"); + res = cstr_to_double(arg, &solid->rho); if(res != RES_OK || solid->rho <= 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "cp"); - res = cstr_to_double(tk, &solid->cp); + CHK_ARG(idx, "cp"); + res = cstr_to_double(arg, &solid->cp); if(res != RES_OK || solid->cp <= 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - ERR(read_delta(stardis, &solid->delta, tok_ctx)); - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Tinit"); - res = cstr_to_double(tk, &solid->tinit); + ERR(read_delta(stardis, &solid->delta, pwordexp, &idx)); + CHK_ARG(idx, "Tinit"); + res = cstr_to_double(arg, &solid->tinit); if(res != RES_OK || solid->tinit < 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } 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)); + pwordexp, &idx)); if(solid->imposed_temperature >= 0 && solid->imposed_temperature != solid->tinit) { @@ -870,11 +1711,11 @@ process_solid 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, &solid->vpower); + CHK_ARG(idx, "volumic power"); + res = cstr_to_double(arg, &solid->vpower); if(res != RES_OK) { /* VPower can be < 0 */ - logger_print(stardis->logger, LOG_ERROR, "Invalid volumic power: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid volumic power: %s\n", arg); goto end; } if(solid->vpower != 0 && stardis->picard_order > 1) { @@ -889,8 +1730,79 @@ process_solid /* Actual solid creation is defered until geometry is read to allow * enclosure shape VS delta analysis (and auto delta computation) */ + ERR(read_sides_and_files(stardis, 0, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* SOLID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_solid_prog + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct solid_prog* solid_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.fmed_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_solid_prog(stardis->allocator, &desc->d.solid_prog)); + solid_prog = desc->d.solid_prog; + desc->type = DESC_MAT_SOLID_PROG; + solid_prog->solid_id = allocate_stardis_medium_id(stardis); ASSERT(sz <= UINT_MAX); - ERR(read_sides_and_files(stardis, 0, (unsigned)sz, tok_ctx)); + solid_prog->desc_id = (unsigned)sz; + + CHK_ARG(idx, "programmed solid name"); + ERR(description_set_name(stardis, &solid_prog->name, arg)); + if(find_description_by_name(stardis, &solid_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + desc_name = arg; + + CHK_ARG(idx, "program name"); + ERR(str_set(&solid_prog->prog_name, arg)); + lib_name = arg; + + ERR(read_sides_and_files(stardis, 0, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &solid_prog->argc, &solid_prog->argv, + pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &solid_prog->program, + &solid_prog->create, &solid_prog->release)); + GET_LIB_SYMBOL(solid_prog, lambda, stardis_conductivity); + GET_LIB_SYMBOL(solid_prog, rho, stardis_volumic_mass); + GET_LIB_SYMBOL(solid_prog, cp, stardis_calorific_capacity); + GET_LIB_SYMBOL(solid_prog, delta, stardis_delta_solid); + GET_LIB_SYMBOL(solid_prog, temp, stardis_medium_temperature); + GET_LIB_SYMBOL(solid_prog, vpower, stardis_volumic_power); + GET_LIB_SYMBOL(solid_prog, t_range, stardis_t_range); + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(solid_prog); + + solid_prog->t_range(solid_prog->prog_data, stardis->t_range); + + ERR(create_solver_solid_prog(stardis, solid_prog)); end: return res; @@ -902,15 +1814,16 @@ error: static res_T process_fluid (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; struct description* desc; size_t sz; struct fluid* fluid; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); stardis->counts.fmed_count++; @@ -920,53 +1833,51 @@ process_fluid ERR(init_fluid(stardis->allocator, &desc->d.fluid)); fluid = desc->d.fluid; desc->type = DESC_MAT_FLUID; - 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); fluid->desc_id = (unsigned)sz; - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "fluid name"); - ERR(description_set_name(stardis, &fluid->name, tk)); + CHK_ARG(idx, "fluid name"); + ERR(description_set_name(stardis, &fluid->name, arg)); if(find_description_by_name(stardis, &fluid->name, desc)) { logger_print(stardis->logger, LOG_ERROR, - "Name already used: %s\n", tk); + "Name already used: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "rho"); - res = cstr_to_double(tk, &fluid->rho); + CHK_ARG(idx, "rho"); + res = cstr_to_double(arg, &fluid->rho); if(res != RES_OK || fluid->rho <= 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "cp"); - res = cstr_to_double(tk, &fluid->cp); + CHK_ARG(idx, "cp"); + res = cstr_to_double(arg, &fluid->cp); if(res != RES_OK || fluid->cp <= 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Tinit"); - res = cstr_to_double(tk, &fluid->tinit); + CHK_ARG(idx, "Tinit"); + res = cstr_to_double(arg, &fluid->tinit); if(res != RES_OK || fluid->tinit < 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } 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)); + pwordexp, &idx)); if(fluid->imposed_temperature >= 0 && fluid->imposed_temperature != fluid->tinit) { @@ -983,8 +1894,76 @@ process_fluid ERR(create_solver_fluid(stardis, fluid)); + ERR(read_sides_and_files(stardis, 0, (unsigned)sz, pwordexp, &idx)); + +end: + return res; +error: + goto end; +} + +/* FLUID_PROG Name ProgName STL_filenames [PROG_PARAMS ...] */ +static res_T +process_fluid_prog + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + char* arg = NULL; + struct description* desc; + const char *lib_name, *desc_name; + size_t sz; + struct fluid_prog* fluid_prog; + struct stardis_description_create_context ctx; + size_t idx = 1; + res_T res = RES_OK; + + ASSERT(stardis && pwordexp); + + stardis->counts.fmed_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + ERR(init_fluid_prog(stardis->allocator, &desc->d.fluid_prog)); + fluid_prog = desc->d.fluid_prog; + desc->type = DESC_MAT_FLUID_PROG; + fluid_prog->fluid_id = allocate_stardis_medium_id(stardis); ASSERT(sz <= UINT_MAX); - ERR(read_sides_and_files(stardis, 0, (unsigned)sz, tok_ctx)); + fluid_prog->desc_id = (unsigned)sz; + + CHK_ARG(idx, "programmed fluid name"); + ERR(description_set_name(stardis, &fluid_prog->name, arg)); + if(find_description_by_name(stardis, &fluid_prog->name, desc)) { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", arg); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + desc_name = arg; + + CHK_ARG(idx, "program name"); + ERR(str_set(&fluid_prog->prog_name, arg)); + lib_name = arg; + + ERR(read_sides_and_files(stardis, 0, (unsigned)sz, pwordexp, &idx)); + + /* store the end of line as args for custom init */ + ERR(set_argc_argv(stardis->allocator, &fluid_prog->argc, &fluid_prog->argv, + pwordexp, idx)); + /* get the user-defined functions from the library */ + ERR(get_prog_common(lib_name, stardis, &fluid_prog->program, + &fluid_prog->create, &fluid_prog->release)); + GET_LIB_SYMBOL(fluid_prog, rho, stardis_volumic_mass); + GET_LIB_SYMBOL(fluid_prog, cp, stardis_calorific_capacity); + GET_LIB_SYMBOL(fluid_prog, temp, stardis_medium_temperature); + GET_LIB_SYMBOL(fluid_prog, t_range, stardis_t_range); + /* create and init custom data */ + ctx.name = desc_name; + CREATE_DESC_DATA(fluid_prog); + + fluid_prog->t_range(fluid_prog->prog_data, stardis->t_range); + + ERR(create_solver_fluid_prog(stardis, fluid_prog)); end: return res; @@ -996,12 +1975,13 @@ error: static res_T process_scale (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); if(stardis->scale_factor > 0) { logger_print(stardis->logger, LOG_ERROR, @@ -1009,13 +1989,13 @@ process_scale res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "scale factor"); - res = cstr_to_double(tk, &stardis->scale_factor); + CHK_ARG(idx, "scale factor"); + res = cstr_to_double(arg, &stardis->scale_factor); if(res != RES_OK || stardis->scale_factor <= 0) { logger_print(stardis->logger, LOG_ERROR, - "Invalid scale factor: %s\n", tk); + "Invalid scale factor: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1030,12 +2010,13 @@ error: static res_T process_radiative (struct stardis* stardis, - char** tok_ctx) + wordexp_t* pwordexp) { - char* tk = NULL; + char* arg = NULL; + size_t idx = 1; res_T res = RES_OK; - ASSERT(stardis && tok_ctx); + ASSERT(stardis && pwordexp); if(stardis->trad_def) { logger_print(stardis->logger, LOG_ERROR, @@ -1043,23 +2024,23 @@ process_radiative res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Trad"); - res = cstr_to_double(tk, &stardis->trad); + CHK_ARG(idx, "Trad"); + res = cstr_to_double(arg, &stardis->trad); if(res != RES_OK || stardis->trad < 0) { logger_print(stardis->logger, LOG_ERROR, - "Invalid Trad: %s\n", tk); + "Invalid Trad: %s\n", arg); 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); + CHK_ARG(idx, "Trad reference"); + res = cstr_to_double(arg, &stardis->trad_ref); if(res != RES_OK || stardis->trad_ref < 0) { logger_print(stardis->logger, LOG_ERROR, - "Invalid Trad reference: %s\n", tk); + "Invalid Trad reference: %s\n", arg); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1072,71 +2053,106 @@ error: } /* Read medium or boundary line; should be one of: - * SOLID Name lambda rho cp delta Tinit Timposed volumic_power STL_filenames + * SOLID Name lambda rho cp delta Tinit Timposed volumic_power STL_sides_filenames * FLUID Name rho cp Tinit Timposed STL_filenames - * H_BOUNDARY_FOR_SOLID Name ref_temperature emissivity specular_fraction hc T_env STL_filenames + * H_BOUNDARY_FOR_SOLID Name ref_temperature emissivity specular_fraction hc T_env STL_sides_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 ref_temperature emissivity specular_fraction hc STL_filenames + * + * SOLID_PROG Name Libray STL_sides_filenames [ PROG_PARAMS ... ] + * SOLID_PROG Name Libray STL_sides_filenames [ PROG_PARAMS ... ] + * H_BOUNDARY_FOR_SOLID_PROG Name Libray STL_filenames [ PROG_PARAMS ... ] + * H_BOUNDARY_FOR_FLUID_PROG Name Libray STL_filenames [ PROG_PARAMS ... ] + * T_BOUNDARY_FOR_SOLID_PROG Name Libray STL_filenames [ PROG_PARAMS ... ] + * F_BOUNDARY_FOR_SOLID_PROG Name Libray STL_filenames [ PROG_PARAMS ... ] + * SOLID_FLUID_CONNECTION_PROG Name Libray STL_filenames [ PROG_PARAMS ... ] + * SOLID_SOLID_CONNECTION_PROG Name Libray STL_filenames [ PROG_PARAMS ... ] + * * SCALE scale_factor * TRAD Trad Trad_ref * - * STL_filenames = { { FRONT | BACK | BOTH } STL_filename }+ + * STL_sides_filenames = { { FRONT | BACK | BOTH } STL_filename }+ + * STL_filenames = { STL_filename }+ */ -res_T +static res_T process_model_line (const char* file_name, - char* line, + const char* line, + wordexp_t *pwordexp, struct stardis* stardis) { res_T res = RES_OK; - struct str keep; - char* tk = NULL, * tok_ctx = NULL; + char* arg = NULL; + size_t idx = 0; - ASSERT(file_name && line && stardis); + ASSERT(file_name && line && pwordexp && stardis); - str_init(stardis->allocator, &keep); - ERR(str_set(&keep, line)); - CHK_TOK(strtok_r(line, " \t", &tok_ctx), "model line type"); + CHK_ARG(idx, "model line type"); - if(0 == strcasecmp(tk, "H_BOUNDARY_FOR_SOLID")) - ERR(process_h(stardis, DESC_BOUND_H_FOR_SOLID, &tok_ctx)); - else if(0 == strcasecmp(tk, "H_BOUNDARY_FOR_FLUID")) - ERR(process_h(stardis, DESC_BOUND_H_FOR_FLUID, &tok_ctx)); - else if(0 == strcasecmp(tk, "T_BOUNDARY_FOR_SOLID")) - ERR(process_t(stardis, &tok_ctx)); - else if(0 == strcasecmp(tk, "F_BOUNDARY_FOR_SOLID")) - 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")) - ERR(process_ssc(stardis, &tok_ctx)); - else if(0 == strcasecmp(tk, "SOLID")) - ERR(process_solid(stardis, &tok_ctx)); - else if(0 == strcasecmp(tk, "FLUID")) - 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)); + if(0 == strcasecmp(arg, "H_BOUNDARY_FOR_SOLID")) + ERR(process_h(stardis, DESC_BOUND_H_FOR_SOLID, pwordexp)); + else if(0 == strcasecmp(arg, "H_BOUNDARY_FOR_SOLID_PROG")) + ERR(process_h_prog(stardis, DESC_BOUND_H_FOR_SOLID_PROG, pwordexp)); + else if(0 == strcasecmp(arg, "HF_BOUNDARY_FOR_SOLID")) + ERR(process_hf(stardis, DESC_BOUND_HF_FOR_SOLID, pwordexp)); + else if(0 == strcasecmp(arg, "HF_BOUNDARY_FOR_SOLID_PROG")) + ERR(process_hf_prog(stardis, DESC_BOUND_HF_FOR_SOLID_PROG, pwordexp)); + else if(0 == strcasecmp(arg, "H_BOUNDARY_FOR_FLUID")) + ERR(process_h(stardis, DESC_BOUND_H_FOR_FLUID, pwordexp)); + else if(0 == strcasecmp(arg, "H_BOUNDARY_FOR_FLUID_PROG")) + ERR(process_h_prog(stardis, DESC_BOUND_H_FOR_FLUID_PROG, pwordexp)); + else if(0 == strcasecmp(arg, "T_BOUNDARY_FOR_SOLID")) + ERR(process_t(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "T_BOUNDARY_FOR_SOLID_PROG")) + ERR(process_t_prog(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "F_BOUNDARY_FOR_SOLID")) + ERR(process_flx(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "F_BOUNDARY_FOR_SOLID_PROG")) + ERR(process_flx_prog(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SOLID_FLUID_CONNECTION")) + ERR(process_sfc(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SOLID_FLUID_CONNECTION_PROG")) + ERR(process_sfc_prog(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SOLID_SOLID_CONNECTION")) + ERR(process_ssc(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SOLID_SOLID_CONNECTION_PROG")) + ERR(process_ssc_prog(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SOLID")) + ERR(process_solid(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SOLID_PROG")) + ERR(process_solid_prog(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "FLUID")) + ERR(process_fluid(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "FLUID_PROG")) + ERR(process_fluid_prog(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "PROGRAM")) + ERR(process_program(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SCALE")) + ERR(process_scale(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "TRAD")) + ERR(process_radiative(stardis, pwordexp)); else { logger_print(stardis->logger, LOG_ERROR, - "Unknown description type: %s\n", tk); + "Unknown description type: %s\n", arg); res = RES_BAD_ARG; goto error; } end: - str_release(&keep); return res; error: logger_print(stardis->logger, LOG_ERROR, "Invalid description line in model file '%s':\n", file_name); - logger_print(stardis->logger, LOG_ERROR, "%s\n", str_cget(&keep)); + logger_print(stardis->logger, LOG_ERROR, "%s\n", line); goto end; } +/******************************************************************************* + * Public Functions + ******************************************************************************/ + res_T get_dummy_solid_id (struct stardis* stardis, @@ -1202,3 +2218,100 @@ end: error: goto end; } + +res_T +read_model + (const struct darray_str* model_files, + struct stardis* stardis) +{ + res_T res = RES_OK; + const struct str* files = NULL; + size_t i; + FILE* f = NULL; + struct txtrdr* txtrdr = NULL; + wordexp_t pwordexp; + int word_initialized = 0; + + 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); + int fst = 1; + f = fopen(name, "r"); + if(!f) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot open model file '%s'\n", name); + res = RES_IO_ERR; + goto error; + } + txtrdr_stream(stardis->allocator, f, name, '#', &txtrdr); + for(;;) { + char* line; + int flags = WRDE_NOCMD | WRDE_UNDEF; + if(!fst) flags |= WRDE_REUSE; + ERR(txtrdr_read_line(txtrdr)); + line = txtrdr_get_line(txtrdr); + if(!line) break; + word_initialized = 1; + switch(wordexp(line, &pwordexp, flags)) { + case 0: /* No error */ + break; + case WRDE_NOSPACE: /* Ran out of memory. */ + res = RES_MEM_ERR; + goto error; + case WRDE_BADCHAR: /* A metachar appears in the wrong place. */ + logger_print(stardis->logger, LOG_ERROR, + "%s: word expansion error: invalid character:\n", name); + goto exp_error; + case WRDE_BADVAL: /* Undefined var reference with WRDE_UNDEF. */ + logger_print(stardis->logger, LOG_ERROR, + "%s: word expansion error: undefined environment variable:\n", name); + goto exp_error; + case WRDE_CMDSUB: /* Command substitution with WRDE_NOCMD. */ + logger_print(stardis->logger, LOG_ERROR, + "%s: word expansion error: command substitution is not enabled:\n", + name); + goto exp_error; + case WRDE_SYNTAX: /* Shell syntax error. */ + logger_print(stardis->logger, LOG_ERROR, + "%s: word expansion error: syntax error:\n", name); + goto exp_error; + default: + FATAL("Unexpected return code.\n"); + } + ERR(process_model_line(name, line, &pwordexp, stardis)); + fst = 0; + continue; +exp_error: + logger_print(stardis->logger, LOG_ERROR, "%s\n", line); + res = RES_BAD_ARG; + goto error; + } + txtrdr_ref_put(txtrdr); + txtrdr = NULL; + fclose(f); + f = NULL; + } + if(stardis->scale_factor <= 0) + 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: + if(word_initialized) wordfree(&pwordexp); + return res; +error: + if(f) fclose(f); + if(txtrdr) txtrdr_ref_put(txtrdr); + goto exit; +} + diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -23,19 +23,25 @@ #include <star/sstl.h> -struct camera; struct logger; -struct mem_allocator; struct stardis; -struct dummies; /* Utility macros */ -#define CHK_TOK(x, Name) if((tk = (x)) == NULL) {\ - logger_print(stardis->logger, LOG_ERROR,\ - "Invalid data (missing token '" Name "')\n");\ - res = RES_BAD_ARG;\ - goto error;\ - } (void)0 +#define CHK_ARG(Idx, Name) {\ + if(pwordexp->we_wordc <= (Idx)) {\ + logger_print(stardis->logger, LOG_ERROR,\ + "Invalid data (missing token '" Name "')\n");\ + arg = "(missing)";\ + res = RES_BAD_ARG;\ + goto error;\ + } else {\ + arg = pwordexp->we_wordv[(Idx)++];\ + if(!arg) {\ + arg = "(inconsistant wordexp)";\ + goto error; /* to silent a gcc-11 */\ + }\ + }\ +}(void)0 /* Same ctx used for both media and interface add (some unused parts) */ struct add_geom_ctx { @@ -46,38 +52,31 @@ struct add_geom_ctx { /* Possible callbacks for sg3d_geometry_add calls * when void* context is a struct add_geom_ctx */ -extern LOCAL_SYM void +void add_geom_ctx_indices (const unsigned itri, unsigned ids[3], void* context); -extern LOCAL_SYM void -add_geom_ctx_properties - (const unsigned itri, - unsigned prop[3], - void* context); - -extern LOCAL_SYM void +void add_geom_ctx_position (const unsigned ivert, double pos[3], void* context); -extern LOCAL_SYM res_T -process_model_line - (const char* file_name, - char* line, - struct stardis* stardis); - -extern LOCAL_SYM res_T +res_T get_dummy_solid_id (struct stardis* stardis, unsigned* id); -extern LOCAL_SYM res_T +res_T get_dummy_fluid_id (struct stardis* stardis, unsigned* id); +res_T +read_model + (const struct darray_str* model_files, + struct stardis* stardis); + #endif /*ARGS_H*/ diff --git a/src/stardis-prog-properties.h.in b/src/stardis-prog-properties.h.in @@ -0,0 +1,584 @@ +/* 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 Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef STARDIS_PROG_H__ +#define STARDIS_PROG_H__ + +/* This header file is intended for inclusion in shared libraries defining + * programmed descriptions used in stardis model files. + * Please refer to stardis(1) and stardis-input(5) man pages for additional + * information. */ + +/* The version of the API described thereafter */ +#define STARDIS_PROG_PROPERTIES_VERSION @STARDIS_PROG_PROPERTIES_VERSION@ + +#include <stddef.h> + +/*****************************************************************************/ +/* API types. */ +/* The various functions defining programmed descriptions receive arguments */ +/* of the following types when called from the stardis simulation. */ +/*****************************************************************************/ + +struct stardis_vertex { + double P[3]; /* World space position */ + double time; /* "Time" of the vertex */ +}; + +enum stardis_side { + FRONT, + BACK +}; + +struct stardis_interface_fragment { + double P[3]; /* World space position */ + double Ng[3]; /* Normalized world space geometry normal at the interface */ + double uv[2]; /* Parametric coordinates of the interface */ + double time; /* Current time */ + enum stardis_side side; +}; + +enum stardis_return_status { + STARDIS_SUCCESS, + STARDIS_FAILURE +}; + +enum stardis_verbosity_levels { + STARDIS_VERBOSE_NONE, + STARDIS_VERBOSE_ERROR, + STARDIS_VERBOSE_WARNING, + STARDIS_VERBOSE_INFO +}; + +struct stardis_program_context { + const char* name; /* Program name */ + enum stardis_verbosity_levels verbosity_level; +}; + +struct stardis_description_create_context { + const char* name; /* Description name */ +}; + +/******************************************************************************/ +/* Optional functions for any programmed library. */ +/* Either all 3 or none of the 3 following functions must be defined. */ +/* If a libray doesn't need its own data, just let these functions undefined. */ +/******************************************************************************/ + +/* Create the data attached to a given libray. + * A NULL result is interpreted as an error and ends the program. + * This function is called the first time a description using this library is + * processed. + * argc + argv describe the (possibly zero) arguments coming from the stardis + * input file in the main-like standard way. */ +extern void* +stardis_create_library_data + (const struct stardis_program_context* ctx, + size_t argc, + char* argv[]); + +/* Finalize the data created by the successive stardis_create_data calls for + * the descriptions created using this library. + * A STARDIS_FAILURE result ends the program. + * This function is called after descriptions creation, before simulation + * starts. + * lib_data is the pointer returned by stardis_create_library_data for this + * library. */ +enum stardis_return_status +stardis_finalize_library_data + (void* lib_data); + +/* Release the data created by stardis_create_library_data. + * This function is called after the simulation finished and after releasing + * descriptions data. + * lib_data is the pointer returned by stardis_create_library_data for this + * library. */ +extern void +stardis_release_library_data + (void* lib_data); + +/******************************************************************************/ +/* Mandatory functions for any programmed description regardless of its type. */ +/******************************************************************************/ + +/* Create the data attached to a given description. + * A NULL result is interpreted as an error and ends the program. + * This function is called every time a description using this library is + * processed. + * lib_data is the pointer returned by stardis_create_library_data for the + * library or NULL if stardis_create_library_data is not defined. + * argc + argv describe the (possibly zero) arguments coming from the stardis + * input file in the main-like standard way. */ +extern void* +stardis_create_data + (const struct stardis_description_create_context *ctx, + void* lib_data, + size_t argc, + char* argv[]); + +/* Release the data created by stardis_create_data. + * This function is called after the simulation finished. + * data is the pointer returned by stardis_create_data for the description. */ +extern void +stardis_release_data + (void* data); + +/* Get the copyright notice. + * A NULL result is interpreted as an error and ends the program. + * data is the pointer returned by stardis_create_data for the description. */ +const char* +get_copyright_notice + (void* data); + +/* Get single-line (name and link?) version of the license. + * A NULL result is interpreted as an error and ends the program. + * data is the pointer returned by stardis_create_data for the description. */ +const char* +get_license_short + (void* data); + +/* Get full license text. + * A NULL result is interpreted as an error and ends the program. + * data is the pointer returned by stardis_create_data for the description. */ +const char* +get_license_text + (void* data); + +/*****************************************************************************/ +/* Additional mandatory function declarations (sorted by description type). */ +/* Some functions appear multiple times as they are part of more than one */ +/* description requirement. */ +/*****************************************************************************/ + +/*********************************************************/ +/* Additional mandatory functions for a programmed solid */ +/*********************************************************/ + +/* Returns the calorific capacity at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this solid. + * data is the pointer returned by stardis_create_data for this solid. */ +extern double +stardis_calorific_capacity + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the volumic mass at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this solid. + * data is the pointer returned by stardis_create_data for this solid. */ +extern double +stardis_volumic_mass + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the conductivity at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this solid. + * data is the pointer returned by stardis_create_data for this solid. */ +extern double +stardis_conductivity + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the delta numerical parameter at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this solid. + * data is the pointer returned by stardis_create_data for this solid. */ +extern double +stardis_delta_solid + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the volumic power at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this solid. + * data is the pointer returned by stardis_create_data for this solid. */ +extern double +stardis_volumic_power + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the temperature at a given vertex. + * If the temperature is not known/imposed the expected return value is -1. + * This functions is called at every vertex of every path of the computation + * crossing this solid. + * data is the pointer returned by stardis_create_data for this solid. */ +extern double +stardis_medium_temperature + (const struct stardis_vertex* vtx, + void* data); + +/* Computes the expected temperature range for this solid. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this solid. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +/*********************************************************/ +/* Additional mandatory functions for a programmed fluid */ +/*********************************************************/ + +/* Returns the calorific capacity at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this fluid. + * data is the pointer returned by stardis_create_data for this fluid. */ +extern double +stardis_calorific_capacity + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the volumic mass at a given vertex. + * This functions is called at every vertex of every path of the computation + * crossing this fluid. + * data is the pointer returned by stardis_create_data for this fluid. */ +extern double +stardis_volumic_mass + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the temperature at a given vertex. + * If the temperature is not known/imposed the expected return value is -1. + * This functions is called at every vertex of every path of the computation + * crossing this fluid. + * data is the pointer returned by stardis_create_data for this fluid. */ +extern double +stardis_medium_temperature + (const struct stardis_vertex* vtx, + void* data); + +/* Computes the expected temperature range for this fluid. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this fluid. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +/**************************************************************************/ +/* Additional mandatory functions for a programmed H boundary for a fluid */ +/**************************************************************************/ + +/* Returns the boundary temperature at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_boundary_temperature + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the emissivity at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_emissivity + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the specular fraction at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_specular_fraction + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the convection coefficient at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_convection_coefficient + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the reference temperature at a given fragment. + * This temperature is used as a reference to linearize radiative transfer + * in Picard computations. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_reference_temperature + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the upper bound of the convection coefficient accross this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_max_convection_coefficient + (void* data); + +/* Computes the expected temperature range for this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +/**************************************************************************/ +/* Additional mandatory functions for a programmed H boundary for a solid */ +/**************************************************************************/ + +/* Returns the emissivity at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_emissivity + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the specular fraction at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_specular_fraction + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the convection coefficient at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_convection_coefficient + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the reference temperature at a given fragment. + * This temperature is used as a reference to linearize radiative transfer + * in Picard computations. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_reference_temperature + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the temperature at a given vertex. + * The intent is to return the temperature in an implicit fluid enclosing this + * solid. + * This functions is called at every vertex of every path of the computation + * crossing this fluid. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_medium_temperature + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the upper bound of the convection coefficient accross this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_max_convection_coefficient + (void* data); + +/* Computes the expected temperature range for this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +/**************************************************************/ +/* Additional mandatory functions for a programmed T boundary */ +/**************************************************************/ + +/* Returns the boundary temperature at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_boundary_temperature + (const struct stardis_interface_fragment* frag, + void* data); + +/* Computes the expected temperature range for this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +/****************************************************************/ +/* Additional mandatory functions for a programmed F+H boundary */ +/****************************************************************/ + +/* Returns the emissivity at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_emissivity + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the specular fraction at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_specular_fraction + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the convection coefficient at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_convection_coefficient + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the flux at the boundary at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_boundary_flux + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the reference temperature at a given fragment. + * This temperature is used as a reference to linearize radiative transfer + * in Picard computations. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_reference_temperature + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the temperature at a given vertex. + * The intent is to return the temperature in an implicit fluid enclosing this + * solid. + * This functions is called at every vertex of every path of the computation + * crossing this fluid. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_medium_temperature + (const struct stardis_vertex* vtx, + void* data); + +/* Returns the upper bound of the convection coefficient accross this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_max_convection_coefficient + (void* data); + +/* Computes the expected temperature range for this boundary. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this boundary. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +/**************************************************************/ +/* Additional mandatory functions for a programmed F boundary */ +/**************************************************************/ + +/* Returns the flux at the boundary at a given fragment. + * This functions is called every time a path of the computation reaches + * this boundary. + * data is the pointer returned by stardis_create_data for this boundary. */ +extern double +stardis_boundary_flux + (const struct stardis_interface_fragment* frag, + void* data); + +/**************************************************************************/ +/* Additional mandatory functions for a programmed Solid-Solid connection */ +/**************************************************************************/ + +/* Returns the thermal contact resistance at a given fragment. + * This functions is called every time a path of the computation reaches + * this connection. + * data is the pointer returned by stardis_create_data for this connection. */ +extern double +stardis_thermal_contact_resistance + (const struct stardis_interface_fragment* frag, + void* data); + +/**************************************************************************/ +/* Additional mandatory functions for a programmed Solid-Fluid connection */ +/**************************************************************************/ + +/* Returns the emissivity at a given fragment. + * This functions is called every time a path of the computation reaches + * this connection. + * data is the pointer returned by stardis_create_data for this connection. */ +extern double +stardis_emissivity + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the specular fraction at a given fragment. + * This functions is called every time a path of the computation reaches + * this connection. + * data is the pointer returned by stardis_create_data for this connection. */ +extern double +stardis_specular_fraction + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the convection coefficient at a given fragment. + * This functions is called every time a path of the computation reaches + * this connection. + * data is the pointer returned by stardis_create_data for this connection. */ +extern double +stardis_convection_coefficient + (const struct stardis_interface_fragment* frag, + void* data); + +/* Returns the upper bound of the convection coefficient accross this connection. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this connection. */ +extern double +stardis_max_convection_coefficient + (void* data); + +/* Computes the expected temperature range for this connection. + * This functions is called once when initializing the computation. + * data is the pointer returned by stardis_create_data for this connection. + * Returns its modified range argument. */ +extern double* +stardis_t_range + (void* data, + double range[2]); + +#endif + diff --git a/src/stardis-program.c b/src/stardis-program.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include <rsys/rsys.h> +#include <rsys/library.h> + +#include "stardis-program.h" + +res_T +init_program + (struct mem_allocator* allocator, + struct program** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->lib_path); + (*dst)->argc = 0; + (*dst)->argv = NULL; + str_initialized = 1; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->lib_path); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_program + (struct program* program, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(program && allocator); + str_release(&program->name); + str_release(&program->lib_path); + if(program->prog_data) { + ASSERT(program->release); + program->release(program->prog_data); + } + library_close(program->lib_handle); + for(i = 0; i < program->argc; i++) MEM_RM(allocator, program->argv[i]); + MEM_RM(allocator, program->argv); + MEM_RM(allocator, program); +} + +res_T +str_print_program + (struct str* str, + const struct program* p) +{ + res_T res = RES_OK; + ERR(str_append_printf(str, "Library %s", str_cget(&p->name))); + if(p->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < p->argc; i++) { + ERR(str_append_printf(str, (i+1 == p->argc ? "\t%s" : "\t%s\n"), p->argv[i])); + } + } +end: + return res; +error: + goto end; +} + diff --git a/src/stardis-program.h b/src/stardis-program.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2018-2023 |Méso|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_PROGRAM_H +#define STARDIS_PROGRAM_H + +#include "stardis-app.h" + +#include <stardis-prog-properties.h> + +#include <rsys/rsys.h> +#include <rsys/str.h> + +/* Forward declarations */ +struct mem_allocator; + +/* type to store data for libraries involved in programmed descriptions */ +struct program { + void* prog_data; /* result of the create() call */ + struct str name; + struct str lib_path; + size_t argc; + char** argv; + /* lib handle and function ptrs */ + void* lib_handle; + const char* (*get_copyright_notice)(void*); + const char* (*get_license_short)(void*); + const char* (*get_license_text)(void*); + void* (*create)(struct stardis_program_context*, size_t, char**); + enum stardis_return_status (*finalize)(void*); + void (*release)(void*); +}; + +res_T +init_program + (struct mem_allocator* allocator, + struct program** dst); + +void +release_program + (struct program* program, + struct mem_allocator* allocator); + +res_T +str_print_program + (struct str* str, + const struct program* program); + +#endif diff --git a/src/stardis-sfconnect-prog.c b/src/stardis-sfconnect-prog.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-sfconnect-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_sf_connect_prog + (struct mem_allocator* allocator, + struct solid_fluid_connect_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->connection_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_sf_connect_prog + (struct solid_fluid_connect_prog* connect, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(connect && allocator); + str_release(&connect->name); + str_release(&connect->prog_name); + if(connect->prog_data) + connect->release(connect->prog_data); + for(i = 0; i < connect->argc; i++) MEM_RM(allocator, connect->argv[i]); + MEM_RM(allocator, connect->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, connect); +} + +res_T +str_print_sf_connect_prog + (struct str* str, + const struct solid_fluid_connect_prog* c) +{ + res_T res = RES_OK; + ASSERT(str && c); + ERR(str_append_printf(str, + "programmed Solid-Fluid connection '%s': lib='%s'", + str_cget(&c->name), str_cget(&c->prog_name))); + if(c->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < c->argc; i++) { + ERR(str_append_printf(str, (i+1 == c->argc ? "\t%s" : "\t%s\n"), c->argv[i])); + } + } +end: + return res; +error: + goto end; +} + +double +sf_connect_prog_get_hmax + (const struct solid_fluid_connect_prog* connect) +{ + return connect->hmax(connect->prog_data); +} + diff --git a/src/stardis-sfconnect-prog.h b/src/stardis-sfconnect-prog.h @@ -0,0 +1,77 @@ +/* Copyright (C) 2018-2023 |Méso|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_SF_CONNECT_PROG_H +#define SDIS_SF_CONNECT_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct stardis; +struct mem_allocator; +struct program; + +/******************************************************************************* + * Solid-Fluid prog data + ******************************************************************************/ +struct solid_fluid_connect_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + int is_outside; /* the fluid is used for a boundary */ + unsigned desc_id; /* id of the boundary; meaningful if is_outside */ + unsigned connection_id; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*ref_temp)(const struct stardis_interface_fragment*, void*); + double (*emissivity)(const struct stardis_interface_fragment*, void*); + double (*alpha)(const struct stardis_interface_fragment*, void*); + double (*hc)(const struct stardis_interface_fragment*, void*); + double (*hmax)(void*); + double* (*t_range)(void*, double trange[2]); +}; + +res_T +create_solver_sf_connect_prog + (struct stardis* stardis, + const struct solid_fluid_connect_prog* connect); + +res_T +init_sf_connect_prog + (struct mem_allocator* allocator, + struct solid_fluid_connect_prog** dst); + +void +release_sf_connect_prog + (struct solid_fluid_connect_prog* connect, + struct mem_allocator* allocator); + +res_T +str_print_sf_connect_prog + (struct str* str, + const struct solid_fluid_connect_prog* connect); + +double +sf_connect_prog_get_hmax + (const struct solid_fluid_connect_prog* connect); + +#endif diff --git a/src/stardis-sfconnect.c b/src/stardis-sfconnect.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-sfconnect.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_sf_connect + (struct mem_allocator* allocator, + struct solid_fluid_connect** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_initialized = 1; + (*dst)->connection_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) str_release(&(*dst)->name); + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_sf_connect + (struct solid_fluid_connect* connect, + struct mem_allocator* allocator) +{ + ASSERT(connect && allocator); + str_release(&connect->name); + MEM_RM(allocator, connect); +} + +res_T +str_print_sf_connect + (struct str* str, + const struct solid_fluid_connect* connect) +{ + res_T res = RES_OK; + ASSERT(str && connect); + ERR(str_append_printf(str, + "Solid-Fluid connection '%s': " + "ref_temperature=%g emissivity=%g, specular_fraction=%g hc=%g", + str_cget(&connect->name), + connect->ref_temperature, connect->emissivity, connect->specular_fraction, + connect->hc)); +end: + return res; +error: + goto end; +} + diff --git a/src/stardis-sfconnect.h b/src/stardis-sfconnect.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2018-2023 |Méso|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_SF_CONNECT_H +#define SDIS_SF_CONNECT_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct mem_allocator; + +/******************************************************************************* + * Solid-Fluid connection type + ******************************************************************************/ + +struct solid_fluid_connect { + struct str name; + double ref_temperature; + double emissivity; + double specular_fraction; + double hc; + unsigned connection_id; +}; + +res_T +init_sf_connect + (struct mem_allocator* allocator, + struct solid_fluid_connect** dst); + +void +release_sf_connect + (struct solid_fluid_connect* connect, + struct mem_allocator* allocator); + +res_T +str_print_sf_connect + (struct str* str, + const struct solid_fluid_connect* connect); + +#endif diff --git a/src/stardis-solid-prog.c b/src/stardis-solid-prog.c @@ -0,0 +1,205 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-solid-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-app.h" + +#include <rsys/mem_allocator.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Local Functions + ******************************************************************************/ + +static double +solid_prog_get_thermal_conductivity + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*solid_props)->lambda(&v, (*solid_props)->prog_data); +} + +static double +solid_prog_get_volumic_mass + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*solid_props)->rho(&v, (*solid_props)->prog_data); +} + +static double +solid_prog_get_calorific_capacity + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*solid_props)->cp(&v, (*solid_props)->prog_data); +} + +static double +solid_prog_get_delta + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*solid_props)->delta(&v, (*solid_props)->prog_data); +} + +static double +solid_prog_get_volumic_power + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*solid_props)->vpower(&v, (*solid_props)->prog_data); +} + +static double +solid_prog_get_temperature + (const struct sdis_rwalk_vertex* vtx, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_vertex v; + d3_set(v.P, vtx->P); + v.time = vtx->time; + return (*solid_props)->temp(&v, (*solid_props)->prog_data); +} + +/******************************************************************************* + * Public Functions + ******************************************************************************/ + +res_T +create_solver_solid_prog + (struct stardis* stardis, + const struct solid_prog* solid_props) +{ + res_T res = RES_OK; + struct sdis_solid_shader solid_shader = SDIS_SOLID_SHADER_NULL; + struct sdis_data* data = NULL; + const struct solid_prog** props; + + ASSERT(stardis && solid_props); + solid_shader.calorific_capacity = solid_prog_get_calorific_capacity; + solid_shader.thermal_conductivity = solid_prog_get_thermal_conductivity; + solid_shader.volumic_mass = solid_prog_get_volumic_mass; + solid_shader.delta= solid_prog_get_delta; + solid_shader.volumic_power = solid_prog_get_volumic_power; + solid_shader.temperature = solid_prog_get_temperature; + ERR(sdis_data_create(stardis->dev, sizeof(struct solid_prog*), + ALIGNOF(struct solid_prog*), NULL, &data)); + + props = sdis_data_get(data); /* Fetch the allocated memory space */ + *props = solid_props; + 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]); + ERR(sdis_solid_create(stardis->dev, &solid_shader, data, + darray_media_ptr_data_get(&stardis->media) + solid_props->solid_id)); + +end: + if(data) SDIS(data_ref_put(data)); + return res; +error: + goto end; +} + +res_T +init_solid_prog(struct mem_allocator* allocator, struct solid_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->desc_id = UINT_MAX; + (*dst)->solid_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_solid_prog + (struct solid_prog* solid, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(solid && allocator); + str_release(&solid->name); + str_release(&solid->prog_name); + if(solid->prog_data) + solid->release(solid->prog_data); + for(i = 0; i < solid->argc; i++) MEM_RM(allocator, solid->argv[i]); + MEM_RM(allocator, solid->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, solid); +} + +res_T +str_print_solid_prog(struct str* str, const struct solid_prog* f) +{ + res_T res = RES_OK; + ASSERT(str && f); + ERR(str_append_printf(str, + "programmed solid '%s': lib='%s', it is medium %u)", + str_cget(&f->name), str_cget(&f->prog_name), f->solid_id)); + if(f->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < f->argc; i++) { + ERR(str_append_printf(str, (i+1 == f->argc ? "\t%s" : "\t%s\n"), f->argv[i])); + } + } +end: + return res; +error: + goto end; +} diff --git a/src/stardis-solid-prog.h b/src/stardis-solid-prog.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2018-2023 |Méso|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_SOLID_PROG_H +#define SDIS_SOLID_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct stardis; +struct mem_allocator; +struct program; + +/******************************************************************************* + * Solid prog data + ******************************************************************************/ +struct solid_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + int is_outside; /* the solid is used for a boundary */ + unsigned desc_id; /* id of the boundary; meaningful if is_outside */ + unsigned solid_id; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*lambda)(const struct stardis_vertex*, void*); + double (*rho)(const struct stardis_vertex*, void*); + double (*cp)(const struct stardis_vertex*, void*); + double (*delta)(const struct stardis_vertex*, void*); + double (*temp)(const struct stardis_vertex*, void*); + double (*vpower)(const struct stardis_vertex*, void*); + double* (*t_range)(void*, double trange[2]); +}; + +res_T +create_solver_solid_prog + (struct stardis* stardis, + const struct solid_prog* solid_props); + +res_T +init_solid_prog + (struct mem_allocator* allocator, + struct solid_prog** dst); + +void +release_solid_prog + (struct solid_prog* solid, + struct mem_allocator* allocator); + +res_T +str_print_solid_prog + (struct str* str, + const struct solid_prog* s); + +#endif diff --git a/src/stardis-solid.c b/src/stardis-solid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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 @@ -14,7 +14,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "stardis-solid.h" -#include "stardis-compute.h" #include "stardis-app.h" #include <sdis.h> @@ -174,7 +173,7 @@ init_solid(struct mem_allocator* allocator, struct solid** dst) (*dst)->delta = 1; (*dst)->tinit = -1; (*dst)->imposed_temperature = -1; - (*dst)->vpower = 0; + (*dst)->vpower = SDIS_VOLUMIC_POWER_NONE; (*dst)->t0 = 0; (*dst)->is_outside = 0; (*dst)->is_green = 0; @@ -203,18 +202,18 @@ str_print_solid(struct str* str, const struct solid* s) { res_T res = RES_OK; ASSERT(str && s); - STR_APPEND_PRINTF(str, "Solid '%s': lambda=%g rho=%g cp=%g delta=%g", - ARG5( str_cget(&s->name), s->lambda, s->rho, s->cp, s->delta ) ); + ERR(str_append_printf(str, "Solid '%s': lambda=%g rho=%g cp=%g delta=%g", + str_cget(&s->name), s->lambda, s->rho, s->cp, s->delta)); if(s->vpower != 0) { - STR_APPEND_PRINTF(str, " VPower=%g", ARG1( s->vpower ) ); + ERR(str_append_printf(str, " VPower=%g", s->vpower)); } if(s->tinit >= 0) { - STR_APPEND_PRINTF(str, " Tinit=%g", ARG1( s->tinit ) ); + ERR(str_append_printf(str, " Tinit=%g", s->tinit)); } if(s->imposed_temperature >= 0) { - STR_APPEND_PRINTF(str, " Temp=%g", ARG1( s->imposed_temperature ) ); + ERR(str_append_printf(str, " Temp=%g", s->imposed_temperature)); } - STR_APPEND_PRINTF(str, " (it is medium %u)", ARG1( s->solid_id ) ); + ERR(str_append_printf(str, " (it is medium %u)", s->solid_id)); end: return res; error: diff --git a/src/stardis-solid.h b/src/stardis-solid.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-2023 |Méso|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,22 +37,22 @@ struct solid { double t0; /* End time of tinit */ int is_outside; /* the solid is used for a boundary */ int is_green; /* green computation (nothing to do with solid itself) */ - unsigned desc_id; /* id of the boundary; meaningful if is_outside */ + unsigned desc_id; unsigned solid_id; }; -LOCAL_SYM res_T +res_T init_solid(struct mem_allocator* allocator, struct solid** dst); -LOCAL_SYM void +void release_solid (struct solid* desc, struct mem_allocator* allocator); -LOCAL_SYM res_T +res_T str_print_solid(struct str* str, const struct solid* solid); -LOCAL_SYM res_T +res_T create_solver_solid (struct stardis* stardis, const struct solid* solid_props); diff --git a/src/stardis-ssconnect-prog.c b/src/stardis-ssconnect-prog.c @@ -0,0 +1,99 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-ssconnect-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_ss_connect_prog + (struct mem_allocator* allocator, + struct solid_solid_connect_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->connection_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + (*dst)->connection_id = UINT_MAX; + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_ss_connect_prog + (struct solid_solid_connect_prog* connect, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(connect && allocator); + str_release(&connect->name); + str_release(&connect->prog_name); + if(connect->prog_data) + connect->release(connect->prog_data); + for(i = 0; i < connect->argc; i++) MEM_RM(allocator, connect->argv[i]); + MEM_RM(allocator, connect->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, connect); +} + +res_T +str_print_ss_connect_prog + (struct str* str, + const struct solid_solid_connect_prog* c) +{ + res_T res = RES_OK; + ASSERT(str && c); + ERR(str_append_printf(str, + "programmed Solid-Solid connection '%s': lib='%s'", + str_cget(&c->name), str_cget(&c->prog_name))); + if(c->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < c->argc; i++) { + ERR(str_append_printf(str, (i+1 == c->argc ? "\t%s" : "\t%s\n"), c->argv[i])); + } + } +end: + return res; +error: + goto end; +} diff --git a/src/stardis-ssconnect-prog.h b/src/stardis-ssconnect-prog.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2018-2023 |Méso|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_SS_CONNECT_PROG_H +#define SDIS_SS_CONNECT_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct stardis; +struct mem_allocator; +struct program; + +/******************************************************************************* + * Solid-Solid prog data + ******************************************************************************/ +struct solid_solid_connect_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*tcr)(const struct stardis_interface_fragment*, void*); + unsigned connection_id; +}; + +res_T +create_solver_ss_connect_prog + (struct stardis* stardis, + const struct solid_solid_connect_prog* connect); + +res_T +init_ss_connect_prog + (struct mem_allocator* allocator, + struct solid_solid_connect_prog** dst); + +void +release_ss_connect_prog + (struct solid_solid_connect_prog* connect, + struct mem_allocator* allocator); + +res_T +str_print_ss_connect_prog + (struct str* str, + const struct solid_solid_connect_prog* connect); + +#endif + diff --git a/src/stardis-ssconnect.c b/src/stardis-ssconnect.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-ssconnect.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_ss_connect + (struct mem_allocator* allocator, + struct solid_solid_connect** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_initialized = 1; + (*dst)->connection_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) str_release(&(*dst)->name); + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_ss_connect + (struct solid_solid_connect* connect, + struct mem_allocator* allocator) +{ + ASSERT(connect && allocator); + str_release(&connect->name); + MEM_RM(allocator, connect); +} + +res_T +str_print_ss_connect + (struct str* str, + const struct solid_solid_connect* connect) +{ + res_T res = RES_OK; + ASSERT(str && connect); + ERR(str_append_printf(str, + "Solid-Solid connection '%s': contact resistance=%g", + str_cget(&connect->name), connect->tcr)); +end: + return res; +error: + goto end; +} + diff --git a/src/stardis-ssconnect.h b/src/stardis-ssconnect.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2018-2023 |Méso|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_SS_CONNECT_H +#define SDIS_SS_CONNECT_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct mem_allocator; + +/******************************************************************************* + * Solid-Solid connection type + ******************************************************************************/ +struct solid_solid_connect { + struct str name; + double tcr; + unsigned connection_id; +}; + +res_T +init_ss_connect + (struct mem_allocator* allocator, + struct solid_solid_connect** dst); + +void +release_ss_connect + (struct solid_solid_connect* connect, + struct mem_allocator* allocator); + +res_T +str_print_ss_connect + (struct str* str, + const struct solid_solid_connect* cconnect); + +#endif diff --git a/src/stardis-tbound-prog.c b/src/stardis-tbound-prog.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-tbound-prog.h" +#include "stardis-prog-properties.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_t_boundary_prog + (struct mem_allocator* allocator, + struct t_boundary_prog** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_init(allocator, &(*dst)->prog_name); + str_initialized = 1; + (*dst)->mat_id = UINT_MAX; +end: + return res; +error: + if(str_initialized) { + str_release(&(*dst)->name); + str_release(&(*dst)->prog_name); + } + if(*dst) MEM_RM(allocator, *dst); + goto end; +} + +void +release_t_boundary_prog + (struct t_boundary_prog* bound, + struct mem_allocator* allocator) +{ + size_t i; + ASSERT(bound && allocator); + str_release(&bound->name); + str_release(&bound->prog_name); + if(bound->prog_data) + bound->release(bound->prog_data); + for(i = 0; i < bound->argc; i++) MEM_RM(allocator, bound->argv[i]); + MEM_RM(allocator, bound->argv); + /* library_close call is managed at lib_data level */ + MEM_RM(allocator, bound); +} + +res_T +str_print_t_boundary_prog + (struct str* str, + const struct t_boundary_prog* b) +{ + res_T res = RES_OK; + ASSERT(str && b); + ERR(str_append_printf(str, + "programmed T boundary for solid '%s': lib='%s', " + "(using medium %u as external medium)", + str_cget(&b->name), str_cget(&b->prog_name), b->mat_id)); + if(b->argc > 0) { + size_t i; + ERR(str_append_printf(str, ", provided arguments:\n")); + for(i = 0; i < b->argc; i++) { + ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); + } + } +end: + return res; +error: + goto end; +} + diff --git a/src/stardis-tbound-prog.h b/src/stardis-tbound-prog.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2018-2023 |Méso|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_TBOUND_PROG_H +#define SDIS_TBOUND_PROG_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +#include "stardis-prog-properties.h" + +struct mem_allocator; +struct program; + +/******************************************************************************* + * T boundary prog data + ******************************************************************************/ +struct t_boundary_prog { + void* prog_data; /* result of the create() call */ + struct str name; + struct str prog_name; + size_t argc; + char** argv; + /* lib handle and function ptrs */ + struct program* program; + void* (*create) + (const struct stardis_description_create_context*, void*, size_t, char**); + void (*release)(void*); + double (*temperature)(const struct stardis_interface_fragment*, void*); + double* (*t_range)(void*, double trange[2]); + unsigned mat_id; +}; + +res_T +init_t_boundary_prog + (struct mem_allocator* allocator, + struct t_boundary_prog** dst); + +void +release_t_boundary_prog + (struct t_boundary_prog* bound, + struct mem_allocator* allocator); + +res_T +str_print_t_boundary_prog + (struct str* str, + const struct t_boundary_prog* bound); + +#endif + diff --git a/src/stardis-tbound.c b/src/stardis-tbound.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2018-2023 |Méso|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/>. */ + +#include "stardis-app.h" +#include "stardis-tbound.h" +#include "stardis-fluid.h" +#include "stardis-intface.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/str.h> + +#include <sdis.h> + +#include <limits.h> + +/******************************************************************************* + * Public Functions + ******************************************************************************/ +res_T +init_t_boundary + (struct mem_allocator* allocator, + struct t_boundary** dst) +{ + res_T res = RES_OK; + int str_initialized = 0; + ASSERT(allocator && dst && *dst == NULL); + *dst = MEM_CALLOC(allocator, 1, sizeof(**dst)); + if(! *dst) { + res = RES_MEM_ERR; + goto error; + } + str_init(allocator, &(*dst)->name); + str_initialized = 1; + (*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; +} + +void +release_t_boundary + (struct t_boundary* bound, + struct mem_allocator* allocator) +{ + ASSERT(bound && allocator); + str_release(&bound->name); + MEM_RM(allocator, bound); +} + +res_T +str_print_t_boundary + (struct str* str, + const struct t_boundary* b) +{ + res_T res = RES_OK; + ASSERT(str && b); + ERR(str_append_printf(str, + "T boundary for solid '%s': T=%g (using medium %u as external medium)", + str_cget(&b->name), b->imposed_temperature, b->mat_id)); +end: + return res; +error: + goto end; +} diff --git a/src/stardis-tbound.h b/src/stardis-tbound.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2018-2023 |Méso|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_TBOUND_H +#define SDIS_TBOUND_H + +#include <rsys/rsys.h> +#include <rsys/str.h> + +struct mem_allocator; + +/******************************************************************************* + * H boundary type + ******************************************************************************/ +struct t_boundary { + struct str name; + double imposed_temperature; + unsigned mat_id; +}; + +res_T +init_t_boundary + (struct mem_allocator* allocator, + struct t_boundary** dst); + +void +release_t_boundary + (struct t_boundary* bound, + struct mem_allocator* allocator); + +res_T +str_print_t_boundary + (struct str* str, + const struct t_boundary* bound); + +#endif diff --git a/src/stardis-version.h.in b/src/stardis-version.h.in @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2020 |Meso|Star> +/* Copyright (C) 2018-2022 |Meso|Star> * * 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/stardis-green-types/stardis-green-types-config-version.cmake.in b/stardis-green-types/stardis-green-types-config-version.cmake.in @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +# Copyright (C) 2018-2023 |Méso|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/stardis-green-types/stardis-green-types-config.cmake b/stardis-green-types/stardis-green-types-config.cmake @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2017, 2021 Vincent Forest (vaplv@free.fr) +# Copyright (C) 2018-2023 |Méso|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/stardis-prog-properties/stardis-prog-properties-config-version.cmake.in b/stardis-prog-properties/stardis-prog-properties-config-version.cmake.in @@ -0,0 +1,22 @@ +# Copyright (C) 2018-2023 |Méso|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_PROG_PROPERTIES_VERSION@) + +IF (${PACKAGE_FIND_VERSION_MAJOR} EQUAL @STARDIS_PROG_PROPERTIES_VERSION@) + SET(PACKAGE_VERSION_COMPATIBLE 1) +ELSE() + SET(PACKAGE_VERSION_UNSUITABLE 1) +ENDIF() diff --git a/stardis-prog-properties/stardis-prog-properties-config.cmake b/stardis-prog-properties/stardis-prog-properties-config.cmake @@ -0,0 +1,28 @@ +# Copyright (C) 2018-2023 |Méso|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.1) +include(SelectLibraryConfigurations) + +# Try to find stardis-prog-properties + +# Look for stardis-prog-properties header +find_path(SPROG_INCLUDE_DIR stardis/stardis-prog-properties.h) + +# Check the package +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(stardis-prog-properties DEFAULT_MSG + SPROG_INCLUDE_DIR) +