stardis

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

commit fa4a588eb0995685844b71be6ad2cd0cd9f2e3a5
parent 2653c1f473a47f6af6e5e5547a2ab7a3e34392fb
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 30 Apr 2020 13:49:05 +0200

Add Bin mode for Green and a few renames

Diffstat:
Mcmake/CMakeLists.txt | 19+++++++++----------
Mdoc/stardis-input.5.txt | 36+++++++++++++++++++-----------------
Mdoc/stardis-output.5.txt | 372+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mdoc/stardis.1.txt.in | 51++++++++++++++++++++++++++++++++++-----------------
Dsrc/main.c | 114-------------------------------------------------------------------------------
Msrc/stardis-app.c | 24+++++++++++++++---------
Msrc/stardis-app.h | 20++++++++++++--------
Msrc/stardis-compute.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/stardis-intface.c | 13+++++++++----
Msrc/stardis-intface.h | 2+-
Asrc/stardis-main.c | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-output.c | 676+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/stardis-output.h | 8+++++++-
Msrc/stardis-parsing.c | 190+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/stardis-parsing.h | 47+++++++++++++++++++++++++++--------------------
Msrc/stardis-version.h.in | 6+++---
16 files changed, 1222 insertions(+), 576 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -53,10 +53,10 @@ set(STARDIS_ARGS_DEFAULT_VERBOSE_LEVEL "1") configure_file(${SDIS_SOURCE_DIR}/../doc/stardis.1.txt.in ${CMAKE_CURRENT_BINARY_DIR}/doc/stardis.1.txt @ONLY) -set(VERSION_MAJOR 0) -set(VERSION_MINOR 4) -set(VERSION_PATCH 0) -set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) +set(SDIS_VERSION_MAJOR 0) +set(SDIS_VERSION_MINOR 4) +set(SDIS_VERSION_PATCH 0) +set(SDIS_VERSION ${SDIS_VERSION_MAJOR}.${SDIS_VERSION_MINOR}.${SDIS_VERSION_PATCH}) configure_file(${SDIS_SOURCE_DIR}/stardis-default.h.in ${CMAKE_CURRENT_BINARY_DIR}/stardis-default.h @ONLY) @@ -114,10 +114,10 @@ set(SDIS_FILES_SRC stardis-compute.c stardis-fluid.c stardis-intface.c + stardis-main.c stardis-output.c stardis-parsing.c - stardis-solid.c - main.c) + stardis-solid.c) set(SDIS_FILES_INC stardis-app.h @@ -145,11 +145,11 @@ if(CMAKE_COMPILER_IS_GNUCC) set(MATH_LIB m) set_target_properties(sdis-app PROPERTIES COMPILE_FLAGS "-std=c99" - VERSION ${VERSION}) + VERSION ${SDIS_VERSION}) elseif(MSVC) set(GETOPT_LIB MuslGetopt) set_target_properties(sdis-app PROPERTIES - VERSION ${VERSION}) + VERSION ${SDIS_VERSION}) endif() target_link_libraries(sdis-app @@ -165,4 +165,4 @@ install(TARGETS sdis-app install(FILES ${SDIS_FILES_DOC} DESTINATION share/doc/stardis-app) -rcmake_copy_runtime_libraries(sdis-app) -\ No newline at end of file +rcmake_copy_runtime_libraries(sdis-app) diff --git a/doc/stardis-input.5.txt b/doc/stardis-input.5.txt @@ -41,7 +41,7 @@ part in 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 -of the *-M* option. +of option *-M*. UNITS ----- @@ -55,7 +55,7 @@ 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 following the *#* character in +except the quote characters. Finally, text introduced by the *#* character in descriptions, when not verbatim, is a comment and is not part of the description. @@ -64,44 +64,46 @@ _______ <thermal-system> ::= <description-line> [ <thermal-system> ] -<description-line> ::= [ <medium-frontier> ... ] - [ <medium-boundary> ... ] - [ <media-connection> ... ] +<description-line> ::= [ <medium-frontier> ] [ <comment> ] + | [ <medium-boundary> ] [ <comment> ] + | [ <media-connection> ] [ <comment> ] ------------------------------------- <medium-frontier> ::= <solid-frontier> | <fluid-frontier> -<medium-boundary> ::= <h-bound-for-solid> - | <h-bound-for-fluid> - | <t-bound-for-solid> +<medium-boundary> ::= <t-bound-for-solid> | <t-bound-for-fluid> + | <h-bound-for-solid> + | <h-bound-for-fluid> | <f-bound-for-solid> <media-connection> ::= <solid-fluid-connect> +<comment> ::= "#" Any text introduced by the # character + <solid-frontier> ::= "SOLID" <medium-name> <lambda> <rho> <cp> <delta> \ <initial-temp> <volumic-power> <triangle-sides> <fluid-frontier> ::= "FLUID" <medium-name> <rho> <cp> <initial-temp> <triangle-sides> -<h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID" <bound-name> <emissivity> \ - <specular-fraction> <hc> <external-temp> <triangles> - -<h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID" <bound-name> <emissivity> \ - <specular-fraction> <hc> <external-temperature> <triangles> - <t-bound-for-solid> ::= "T_BOUNDARY_FOR_SOLID" <bound-name> <temperature> <triangles> <t-bound-for-fluid> ::= "T_BOUNDARY_FOR_FLUID" <bound-name> <temperature> \ <emissivity> <specular-fraction> <hc> <triangles> -<f-bound-for-solid> ::= "T_BOUNDARY_FOR_SOLID" <bound-name> <flux> <triangles> +<h-bound-for-solid> ::= "H_BOUNDARY_FOR_SOLID" <bound-name> <emissivity> \ + <specular-fraction> <hc> <outside-temperature> <triangles> + +<h-bound-for-fluid> ::= "H_BOUNDARY_FOR_FLUID" <bound-name> <emissivity> \ + <specular-fraction> <hc> <outside-temperature> <triangles> + +<f-bound-for-solid> ::= "F_BOUNDARY_FOR_SOLID" <bound-name> <flux> <triangles> <solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION" <bound-name> <emissivity> \ <specular-fraction> <hc> <triangles> - + ------------------------------------- <medium-name> ::= STRING # no space allowed @@ -128,7 +130,7 @@ _______ <hc> ::= REAL # in [0, INF) -<external-temp> ::= REAL # in [0, INF) +<outside-temperature> ::= REAL # in [0, INF) <flux> ::= REAL # in (-INF , INF) diff --git a/doc/stardis-output.5.txt b/doc/stardis-output.5.txt @@ -25,16 +25,17 @@ stardis-output - output format of stardis(1) results DESCRIPTION ----------- *stardis-output* describes the output format of the *stardis*(1) program. -All the data generated by a *stardis*(1) invocation are written to _standard -output_. +Any *stardis*(1) result is written to _standard output_, even though some +additional information can be written in files. The type of the data that are generated depends on the options used when *stardis*(1) is invoked. When invoked with one of the basic computation options (*-p*, *-P*, *-m*, *-s* or *-F*), *stardis*(1) outputs a single Monte-Carlo result. On the opposite, *stardis*(1) ouputs compound results when invoked with -option *-S* or *-R*. Additionally, options *-g* and *-D* are output modifiers. -Most if not all complex data output are in VTK [1] format that can be displayed -and manipulated by the open-source software Paraview [2]. +option *-S* or *-R*. Additionally, options *-g* and *-G* make *stardis*(1) +compute and output a Green function. Most if not all complex data output are in +VTK [1] format that can be displayed and manipulated by the open-source +software Paraview [2]. Finaly, some special options (*-v*, *-h* or *-d*) that does not involve any computation produce output including information on the *stardis*(1) software @@ -59,13 +60,14 @@ correspondance: *-F*: produces <mean-flux> -*-p*, *-P*, *-m* or *-s* with *-g*: produce <green> +*-p*, *-P*, *-m* or *-s* with *-g* or *-G*: produce <ascii-green> or +<binary-green> respectively. -*-p*, *-P*, *-m*, *-s*, *-S* or *-F* with *-D*: produce <heat-paths> +*-D*: produces <heat-path> files in addition to the simulation output -*-R*: produces <image-file> +*-R*: produces <infrared-image> -*-d*: produces <geometry-file> +*-d*: produces <geometry-dump> GRAMMAR ------- @@ -74,17 +76,21 @@ continue a description next line. However, this trick is not part of the actual output, that continues on a single line. On the other hand, multiple lines not using the *\* convenience in multi-lines descriptions are truly different lines of output. Also, text appearing between quote marks is a -verbatim part of the output, except the quote characters, *<#something>* +verbatim part of the output, except the quote characters, *#something* denotes a count (the number of something), and the math symbols '*\+*' and '***', when not verbatim, are used with the usual meaning (like in -1+<#something>). Finally, text following the *#* character in a description, -when not verbatim, is a comment and is not part of the output. +#something+1). Finally, text introduced by the *#* character in a description, +when neither verbatim nor count, is a comment and is not part of the output. + +OUTPUT +------ [verse] _______ <output> ::= <single-MC-result> - | <green-output> + | <binary-green> + | <ascii-green> | <geometry-dump> | <infrared-image> _______ @@ -98,78 +104,221 @@ was used too. [verse] _______ -<single-MC-result> ::= <probe-temp> - | <medium-temp> - | <mean-temp> - | <mean-flux> +<single-MC-result> ::= <probe-temp> + | <medium-temp> + | <mean-temp> + | <mean-flux> ------------------------------------- -<probe-temp> ::= "Temperature at" <probe-position> <time> <MC-estimate> - <failures-report> +<probe-temp> ::= "Temperature at" <probe-position> <time> <MC-estimate> + <failures-report> -<mean-temp> ::= "Temperature at boundary" <file-name> <time> <MC-estimate> - <failures-report> +<mean-temp> ::= "Temperature at boundary" <file-name> <time> <MC-estimate> + <failures-report> -<mean-flux> ::= "Temperature at boundary" <file-name> <time> <MC-estimate> - "Convective flux at boundary " <file-name> <time> \ - <MC-estimate> - "Radiative flux at boundary" <file-name> <time> <MC-estimate> - "Total flux at boundary" <file-name> <time> <MC-estimate> - <failures-report> +<mean-flux> ::= "Temperature at boundary" <file-name> <time> <MC-estimate> + "Convective flux at boundary " <file-name> <time> \ + <MC-estimate> + "Radiative flux at boundary" <file-name> <time> <MC-estimate> + "Total flux at boundary" <file-name> <time> <MC-estimate> + <failures-report> -<medium-temp> ::= "Temperature in medium" <medium-name> <time> <MC-estimate> - <failures-report> +<medium-temp> ::= "Temperature in medium" <medium-name> <time> <MC-estimate> + <failures-report> -<probe-position> ::= "[" <x-value> "," <y-value> "," <z-value> "]" +<probe-position> ::= "[" <x-value> "," <y-value> "," <z-value> "]" -<time> ::= "at t=" <time-value> "=" +<time> ::= "at t=" <time-value> "=" -<MC-estimate> ::= <expected-value> "+/-" <standard-error> +<MC-estimate> ::= <expected-value> "+/-" <standard-deviation> -<failures-report> ::= "#failures:" <error-count> "/" <success-count> +<failures-report> ::= "#failures:" <error-count> "/" <success-count> -<file-name> ::= STRING # as provided in input data +<file-name> ::= STRING # as provided in input data -<medium-name> ::= STRING # as provided in input data +<medium-name> ::= STRING # as provided in input data ------------------------------------- -<x-value> ::= REAL +<x-value> ::= REAL -<y-value> ::= REAL +<y-value> ::= REAL -<z-value> ::= REAL +<z-value> ::= REAL -<time-value> ::= REAL # in [0, INF) +<time-value> ::= REAL # in [0, INF) -<error-count> ::= INTEGER # in [0, SAMPLES_COUNT] +<error-count> ::= INTEGER # in [0, #samples] -<success-count> ::= INTEGER # in [0, SAMPLES_COUNT] +<success-count> ::= INTEGER # in [0, #samples] -<expected-value> ::= REAL # depending on value semantics, range can be restricted +<expected-value> ::= REAL # depending on value semantics, range can be restricted -<standard-error> ::= REAL # in [0, INF) +<standard-deviation> ::= REAL # in [0, INF) _______ -GREEN ------ -The green function is generated when a green-compatible *stardis*(1) simulation -option is used in conjuction with the *-g* option. For every successful heat -path sampled carrying out the simulation, the solver records all the elements -of the path history relevant to link the various imposed temperatures, fluxes -and volumic powers to the simulation result. +ASCII GREEN +----------- +The Green function is generated when a green-compatible *stardis*(1) simulation +option is used in conjuction with the *-&#8288;g* option. For every successful +heat path sampled carrying out the simulation, the solver records all the +elements of the path history relevant to link the various imposed temperature, +fluxe and volumic power values to the simulation result. Note that to be able +to explore different values of volumic power when applying the Green function, +it must have been generated with these values being non-zero. On the other +hand, any temperature or flux value in boundary descriptions can be modified +when applying the Green function, as well as the ambient temperature. + +The output in green mode is made of tables containing the different media and +boundaries and their imposed temperature, flux and volumic power values, +followed by the paths' history. + +The Monte-Carlo estimate and standard deviation for a given set of settings can +be computed as the mean and standard deviation of the samples of the *Green +function* computed using these settings. Each sample can be computed as +follows: + +* Get the temperature of the ending boundary, medium or ambient; +* Add the temperature gain of each power term; +* Add the temperature gain of each flux term. + +[verse] +_______ +<ascii-green> ::= "---BEGIN GREEN---" + "# #solids #fluids #t_boundaries #h_boundaries #f_boundaries \ + #ok #failures" + #solids #fluids #t_boundaries #h_boundaries #f_boundaries #ok \ + #failures + "# Solids" + "# ID Name lambda rho cp power" + <solids> + "# Fluids" + "# ID Name rho cp" + <fluids> + "# T Boundaries" + "# ID Name temperature" + <t-bounds> + "# H Boundaries" + "# ID Name emissivity specular_fraction hc T_env" + <h-bounds> + "# F Boundaries" + "# ID Name flux" + <f-bounds> + "# Radiative Temperatures" + "# ID Rad_Temp Lin_Temp" + <rad-temps> + "# Samples" + "# end #power_terms #flux_terms power_term_1 ... power_term_n \ + flux_term_1 ... flux_term_n" + "# end = end_type end_id; end_type = T | H | X | R | F | S" + "# power_term_i = power_id_i factor_i" + "# flux_term_i = flux_id_i factor_i" + <samples> + "---END GREEN---" + +<solids> ::= <solid> + <solids> # #solids solid descriptions + +<fluids> ::= <fluid> + <fluids> # #fluids fluid descriptions + +<t-bounds> ::= <t-bound> + <t-bounds> # #t-bounds t-bound descriptions + +<h-bounds> ::= <h-bound> + <h-bounds> # #h-bounds h-bound descriptions + +<f-bounds> ::= <f-bound> + <f-bounds> # #f-bounds f-bound descriptions + +<rad-temps> ::= <green-id> <rad-temp> <lin-temp> + +<samples> ::= <sample> + <samples> # #samples sample descriptions + +------------------------------------- + +<sample> ::= <end-spec> <power-count> <flux-count> <power-terms> <flux-terms> + +<solid> ::= <green-id> <name> <lambda> <rho> <cp> <power> + +<fluid> ::= <green-id> <name> <rho> <cp> + +<t-bound> ::= <green-id> <name> <temperature> + +<h-bound> ::= <green-id> <name> <emissivity> <specular_fraction> <hc> \ + <temperature> + +<f-bound> ::= <green-id> <name> <flux> + +<rad-temps> ::= <green-id> <ambient-temp> <lin-temp> + +<name> ::= STRING # no space allowed + +<lambda> ::= REAL # in ]0, INF) + +<rho> ::= REAL # in ]0, INF) + +<cp> ::= REAL # in ]0, INF) + +<power> ::= REAL # in (-INF , INF) + +<temperature> ::= REAL # in [0, INF) + +<emissivity> ::= REAL # in [0, 1] + +<specular-fraction> ::= REAL # in [0, 1] + +<hc> ::= REAL # in [0, INF) + +<flux> ::= REAL # in (-INF , INF) -The output in green mode is a made of tables containing the different media and -boundaries and their imposed temperatures, fluxes and volumic powers, followed -by the paths' history. +<ambient-temp> ::= REAL # in [0, INF) + +<lin-temp> ::= REAL # in [0, INF) + +<green-id> ::= INTEGER # in [0 #solids] + +------------------------------------- + +<end-spec> ::= <end-type> <green-id> +<end-type> ::= "T" # sample ends at an t-bound + | "H" # sample ends at an h-bound + # a sample cannot end at an f-bound + | "A" # sample ends with ambient temperature + | "F" # sample ends in a fluid with known temperature + | "S" # sample ends in a solid with known temperature + +<power-count> ::= INTEGER # in [0 INF) + +<flux-count> ::= INTEGER # in [0 INF) + +<power-terms> ::= <power-term> + | <power-terms> # <power-count> power terms + +<flux-terms> ::= <flux-term> + | <flux-terms> # <flux-count> flux terms + +------------------------------------- + +<power-term> ::= "S" <green-id> <power-factor> + +<flux-term> ::= <green-id> <flux-factor> + +<power-factor> ::= REAL # in ]0, INF); the temperature gain is power-factor * Power(green-id) + +<flux-factor> ::= REAL # in ]0, INF); the temperature gain is flux-factor * Flux(green-id) + + +_______ GEOMETRY DUMP ------------- -A *geometry-file* is generated when *stardis*(1) is invoked with the *-d* -option. In this mode, *stardis*(1) outputs the system geometry, as submitted -in *stardis-input*(5) description, to _standard output_ in the VTK [1] format. +A *geometry-file* is generated when *stardis*(1) is invoked with option *-d*. +In this mode, *stardis*(1) outputs the system geometry, as submitted in +*stardis-input*(5) description, to _standard output_ in the VTK [1] format. The output geometry is not the concatenation of the various geometry files used in *stardis-input*(5) description. It is the result of a deduplication process that removes duplicate and degenerated triangles in the submited @@ -183,11 +332,82 @@ If errors are detected, some optional error-related data fields are included in the geometry file. Some errors report a by-triangle error status, other errors report a by-enclosure error status. +[verse] +_______ +<geometry-file> ::= "# vtk DataFile Version 2.0" + "Dump of star-geometry-3d geometry" + "ASCII" + "DATASET POLYDATA" + "POINTS" #vertices "double" + <geometry-vertices> + "POLYGONS" #triangles #triangles*4 + <geometry-triangles> + "CELL_DATA" #triangles + "SCALARS Front_medium unsigned_int 1" + "LOOKUP_TABLE default" + <front_medium_ids> + +<front_medium_ids> ::= UNSIGNED # in [0, INF) + <front_medium_ids> # #media ids + +<trg-conflict-code> ::= NO_CONFLICT + | BOUND_H_FOR_FLUID_BETWEEN_2_DEFS + | BOUND_H_FOR_FLUID_BETWEEN_2_UNDEFS + | BOUND_H_FOR_FLUID_ENCLOSING_SOLID + | BOUND_H_FOR_SOLID_BETWEEN_2_DEFS + | BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS + | BOUND_H_FOR_SOLID_ENCLOSING_FLUID + | BOUND_T_FOR_FLUID_BETWEEN_2_DEFS + | BOUND_T_FOR_FLUID_BETWEEN_2_UNDEFS + | BOUND_T_FOR_FLUID_ENCLOSING_SOLID + | BOUND_T_FOR_SOLID_BETWEEN_2_DEFS + | BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS + | BOUND_T_FOR_SOLID_ENCLOSING_FLUID + | BOUND_F_FOR_SOLID_BETWEEN_2_DEFS + | BOUND_F_FOR_SOLID_BETWEEN_2_UNDEFS + | BOUND_F_FOR_SOLID_ENCLOSING_FLUID + | SFCONNECT_BETWEEN_2_SOLIDS + | SFCONNECT_BETWEEN_2_FLUIDS + | SFCONNECT_USED_AS_BOUNDARY + | SFCONNECT_BETWEEN_2_UNDEFS + | NO_CONNECTION_BETWEEN_2_FLUIDS + | NO_CONNECTION_BETWEEN_SOLID_AND_FLUID + | NO_BOUND_BETWEEN_FLUID_AND_UNDEF + | NO_BOUND_BETWEEN_SOLID_AND_UNDEF + +TRG_WITH_NO_PROPERTY + +NO_CONFLICT ::= 0 +BOUND_H_FOR_FLUID_BETWEEN_2_DEFS ::= 1 +BOUND_H_FOR_FLUID_BETWEEN_2_UNDEFS ::= 2 +BOUND_H_FOR_FLUID_ENCLOSING_SOLID ::= 3 +BOUND_H_FOR_SOLID_BETWEEN_2_DEFS ::= 4 +BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS ::= 5 +BOUND_H_FOR_SOLID_ENCLOSING_FLUID ::= 6 +BOUND_T_FOR_FLUID_BETWEEN_2_DEFS ::= 7 +BOUND_T_FOR_FLUID_BETWEEN_2_UNDEFS ::= 8 +BOUND_T_FOR_FLUID_ENCLOSING_SOLID ::= 9 +BOUND_T_FOR_SOLID_BETWEEN_2_DEFS ::= 10 +BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS ::= 11 +BOUND_T_FOR_SOLID_ENCLOSING_FLUID ::= 12 +BOUND_F_FOR_SOLID_BETWEEN_2_DEFS ::= 13 +BOUND_F_FOR_SOLID_BETWEEN_2_UNDEFS ::= 14 +BOUND_F_FOR_SOLID_ENCLOSING_FLUID ::= 15 +SFCONNECT_BETWEEN_2_SOLIDS ::= 16 +SFCONNECT_BETWEEN_2_FLUIDS ::= 17 +SFCONNECT_USED_AS_BOUNDARY ::= 18 +SFCONNECT_BETWEEN_2_UNDEFS ::= 19 +NO_CONNECTION_BETWEEN_2_FLUIDS ::= 20 +NO_CONNECTION_BETWEEN_SOLID_AND_FLUID ::= 21 +NO_BOUND_BETWEEN_FLUID_AND_UNDEF ::= 22 +NO_BOUND_BETWEEN_SOLID_AND_UNDEF ::= 23 + +_______ INFRARED IMAGE -------------- -When invoked with the *-R* option, *stardis*(1) generates an infrared image of +When invoked with option *-R*, *stardis*(1) generates an infrared image of the system and write it to _standard output_ in VTK [1] file format. The image is on an XY plane with coordinates in the [0 pixel_count[ range. By convention, the origine (0,0) pixel is at the top-left corner of the image. @@ -224,27 +444,29 @@ _______ <failures_counts> <temperatures> ::= REAL # in [0, INF) - <temperatures> # <image-width> * <image-height> temperatures + <temperatures> # <image-width>*<image-height> temperatures <temp_std_devs> ::= REAL # in [0, INF) - <temperature_std_devs> # <image-width> * <image-height> std_devs + <temperature_std_devs> # <image-width>*<image-height> std_devs <computation_times> ::= REAL # in [0, INF) - <computation_times> # <image-width> * <image-height> times + <computation_times> # <image-width>*<image-height> times <comp_time_std_devs> ::= REAL # in [0, INF) - <comp_time_std_devs> # <image-width> * <image-height> std_devs + <comp_time_std_devs> # <image-width>*<image-height> std_devs <failures_counts> ::= INTEGER # in [0, SAMPLES_COUNT] - <failures_counts> # <image-width> * <image-height> failures_counts + <failures_counts> # <image-width>*<image-height> failures_counts _______ + DUMP HEAT PATHS --------------- -When the *stardis*(1) option *-D* is used, some of the heat paths (successful -paths, erroneous paths, or both) sampled during the simulation are written to -files. Each path is written in VTK [1] format, one VTK file per path. The path -description includes vertices' time it it makes sense, that is if the -computation time is not INF. +When the *stardis*(1) option *-D* is used in conjunction with an option that +computes a result, some of the heat paths (successful paths, erroneous paths, +or both) sampled during the simulation are written to files. Each path is +written in VTK [1] format, one VTK file per path. The path description can +include vertices' time if it makes sense, that is if the computation time is +not INF. [verse] _______ @@ -253,11 +475,11 @@ _______ "Heat path" "ASCII" "DATASET POLYDATA" - "POINTS" <#vertices> "double" + "POINTS" #vertices "double" <path-vertices> - "LINES 1" 1+<#vertices> + "LINES 1" #vertices+1 <heat-path> - "POINT_DATA" <#vertices> + "POINT_DATA" #vertices "SCALARS Vertex_Type unsigned_char 1" "LOOKUP_TABLE default" <vertices-types> @@ -271,15 +493,15 @@ _______ [ <vertices-time> ] <path-vertices> ::= <real3> - <path-vertices> # <#vertices> vertices + <path-vertices> # #vertices vertices -<heat-path> ::= <#vertices> "0" "1" ... <#vertices>-1 +<heat-path> ::= #vertices "0" "1" ... #vertices-1 <vertices-types> ::= <vertice-type> - <vertices-types> # <#vertices> types + <vertices-types> # #vertices types <weigths> ::= REAL - <weigths> # <#vertices> weigths + <weigths> # #vertices weigths <vertices-time> ::= "SCALARS Time double 1" "LOOKUP_TABLE default" @@ -290,7 +512,7 @@ _______ <real3> ::= REAL REAL REAL <durations> ::= REAL # in [0, INF) - <durations> # <#vertices> durations + <durations> # #vertices durations <vertice-type> ::= 0 # CONDUCTION | 1 # CONVECTION diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -130,8 +130,9 @@ EXCLUSIVE OPTIONS *-R* [__sub-option__:...]:: Render an infrared image of the system through a pinhole camera and write it to _standard output_ in VTK format. One can use all-default sub-options by - simply providing the colon character (*:*) alone as an argument. Available - sub-options are: + simply providing the colon character (*:*) alone as an argument. Please note + that the camera position must be outside the geometry or in a fluid. + Available sub-options are: **fov=**_angle_;; Horizontal field of view of the camera in [30, 120] degrees. By default @@ -181,16 +182,21 @@ specifies a compute region (-F, -S, -s) has the effect to include the region in the output. This option cannot be used in conjunction with other options that write to _standard output_ (-g, -h, -R, -v). -*-D* _type,file_name_prefix_:: +*-D* _type,files_name_prefix_:: Write sampled heat paths of the given *type* to files in VTK format, one file per path. Possible values for *type* are *error* (write paths ending in error), *success* (write successful paths), and *all* (write all paths). - Actual file names are produced by appending *file_name_prefix* and the path + Actual file names are produced by appending *files_name_prefix* and the path rank starting at index 00000000: prefix00000000.vtk, prefix00000001.vtk, ... + -This option can only be used in conjuction with options that compute a -result (-F, -m, -P, -p, -R, -S, -s) and cannot be used in conjunction with the --g option. +This option can only be used in conjuction with options that compute a +result (-F, -m, -P, -p, -R, -S, -s) and cannot be used in conjunction with +options -g or -G. + +*-e*:: + Use extended format to output Monte-Carlo results. Can only be used in + conjunction with options that compute a single Monte-Carlo (-F, -m, -P, -p, + or -s without options -g or -G). **-f** _factor_:: Rescale the geometry by the given *factor* before sending it to the solver, @@ -198,12 +204,22 @@ result (-F, -m, -P, -p, -R, -S, -s) and cannot be used in conjunction with the is @STARDIS_ARGS_DEFAULT_SCALE_FACTOR@. *-g*:: - Write the green function at steady state to _standard output_ after the - specified computation. + Compute the Green function at steady state and write in ASCII to _standard + output_. ++ +This option can only be used in conjunction with one these options: -p, -P, +-m, -s and cannot be used in conjunction with option -D. Any compute time +provided through one of these options is silently ignored. + +*-G* _file_name_:: + Compute the Green function at steady state and write it to an binary file. + This option can only be used in conjunction with one these options: -p, -P, --m, -s and cannot be used in conjunction with the -D option. Any compute time +-m, -s and cannot be used in conjunction with option -D. Any compute time provided through one of these options is silently ignored. ++ +The resulting file can be further used through the *sgreen*(1) command to apply +different temperature, flux or volumic power values. *-h*:: Output short help and exit. @@ -220,15 +236,15 @@ provided through one of these options is silently ignored. Hint on the number of threads to use. By default use as many threads as CPU cores. +*-v*:: + Output version information and exit. + *-V* _level_:: Set the verbosity level. Possible values are *0* (no message), *1* (error messages only), *2* (error and warning messages), and *3* (error, warning and informative messages). All the messages are written to _standard error_. Default verbosity *level* is @STARDIS_ARGS_DEFAULT_VERBOSE_LEVEL@. -*-v*:: - Output version information and exit. - EXAMPLES -------- Preprocess the system as described in *scene 5.txt* when intending to compute @@ -244,9 +260,10 @@ samples is set to *1000000*: $ stardis -M media.txt -M bounds.txt -p 0,0.5,0 -n 1000000 Compute the mean temperature in the medium *med05* at *t=100* s. The system is -read from the 2 files *media.txt* and *bounds.txt*: +read from the 2 files *media.txt* and *bounds.txt* and the result is output +with extended format: - $ stardis -M media.txt -M bounds.txt -m med05,100 + $ stardis -M media.txt -M bounds.txt -m med05,100 -e Render the system as described in *scene.txt* with default settings: @@ -270,4 +287,5 @@ permitted by law. SEE ALSO -------- *stardis-input*(5), -*stardis-output*(5) -\ No newline at end of file +*stardis-output*(5), +*sgreen*(1) diff --git a/src/main.c b/src/main.c @@ -1,114 +0,0 @@ -/* Copyright (C) 2018-2020 |Meso|Star> (contact@meso-star.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "stardis-app.h" -#include "stardis-parsing.h" -#include "stardis-output.h" -#include "stardis-compute.h" - -#include <rsys/rsys.h> -#include <rsys/mem_allocator.h> -#include <rsys/logger.h> - -#include <stdio.h> - -int -main - (int argc, - char** argv) -{ - struct args* args = NULL; - struct stardis stardis; - int logger_initialized = 0, allocator_initialized = 0, - args_initialized = 0, stardis_initialized = 0; - int err = EXIT_SUCCESS; - struct mem_allocator allocator; - struct logger logger; - res_T res = RES_OK; - - ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - allocator_initialized = 1; - - ERR(logger_init(&allocator, &logger)); - logger_initialized = 1; - /* Active loggin for args pasing */ - logger_set_stream(&logger, LOG_OUTPUT, log_prt, NULL); - logger_set_stream(&logger, LOG_ERROR, log_err, NULL); - logger_set_stream(&logger, LOG_WARNING, log_warn, NULL); - - ERR(init_args(&logger, &allocator, &args)); - args_initialized = 1; - ERR(parse_args(argc, argv, args)); - - if(args->mode & DUMP_HELP) { - short_help(stdout, argv[0]); - goto exit; - } - else if(args->mode & DUMP_VERSION) { - print_version(stdout); - goto exit; - } - - /* Deactivate some loggin according to the -V arg */ - if(args->verbose < 1) - logger_set_stream(&logger, LOG_ERROR, NULL, NULL); - if(args->verbose < 2) - logger_set_stream(&logger, LOG_WARNING, NULL, NULL); - if(args->verbose < 3) - logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL); - - ERR(stardis_init(args, &logger, &allocator, &stardis)); - stardis_initialized = 1; - release_args(args); - args_initialized = 0; - - if(stardis.mode & DUMP_VTK) { - /* Dump all the app-independent information */ - ERR(sg3d_geometry_dump_as_vtk(stardis.geometry.sg3d, stdout)); - /* Dump the compute region if any */ - if(stardis.mode & REGION_COMPUTE_MODES) { - ERR(dump_compute_region_at_the_end_of_vtk(&stardis, stdout)); - } - /* Dump possible holes - * TODO: as this extracts enclosures, it could dump front/back - * enclosure IDs too */ - ERR(dump_enclosure_related_stuff_at_the_end_of_vtk(&stardis, stdout)); - - /* If dump flag set exit after dump done */ - goto exit; - } - - ASSERT(stardis.mode & COMPUTE_MODES); - ERR(stardis_compute(&stardis)); - -exit: - if(args_initialized) release_args(args); - if(stardis_initialized) stardis_release(&stardis); - if(logger_initialized) logger_release(&logger); - if(allocator_initialized) { - if(MEM_ALLOCATED_SIZE(&allocator) != 0) { - char dump[4096] = { '\0' }; - MEM_DUMP(&allocator, dump, sizeof(dump)); - fprintf(stderr, "%s\n", dump); - fprintf(stderr, "\nMemory leaks: %zu Bytes\n", - MEM_ALLOCATED_SIZE(&allocator)); - } - mem_shutdown_proxy_allocator(&allocator); - } - return err; -error: - err = EXIT_FAILURE; - goto exit; -} diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -451,7 +451,8 @@ stardis_init stardis->counts = COUNTS_NULL; init_camera(&stardis->camera); str_init(stardis->allocator, &stardis->solve_name); - str_init(stardis->allocator, &stardis->out_filename); + str_init(stardis->allocator, &stardis->paths_filename); + str_init(stardis->allocator, &stardis->bin_green_filename); darray_size_t_init(stardis->allocator, &stardis->compute_surface.primitives); darray_sides_init(stardis->allocator, &stardis->compute_surface.sides); darray_uint_init(stardis->allocator, &stardis->compute_surface.err_triangles); @@ -470,15 +471,15 @@ stardis_init /* If a dump is expected, we won't process any computation */ is_for_compute = - (stardis->mode & COMPUTE_MODES) && !(stardis->mode & DUMP_VTK); + (stardis->mode & COMPUTE_MODES) && !(stardis->mode & MODE_DUMP_VTK); ERR(init_geometry(stardis->logger, stardis->allocator, stardis->verbose, &stardis->geometry)); - if(args->mode & IR_COMPUTE) { + if(args->mode & MODE_IR_COMPUTE) { ERR(parse_camera(stardis->logger, args->camera, &stardis->camera)); } - else if(args->mode & MEDIUM_COMPUTE) { + else if(args->mode & MODE_MEDIUM_COMPUTE) { ERR(str_set(&stardis->solve_name, args->medium_name)); } else if(args->mode & SURFACE_COMPUTE_MODES) { @@ -492,7 +493,8 @@ stardis_init /* Create media and property holders for those found in descriptions */ str_init(stardis->allocator, &str); for(i = 0; i < darray_descriptions_size_get(&stardis->descriptions); i++) { - ERR(create_holder(stardis, &dummies, i, stardis->mode & GREEN_MODE)); + ERR(create_holder(stardis, &dummies, i, + stardis->mode & (MODE_BIN_GREEN | MODE_GREEN))); str_clear(&str); str_printf(&str, "Description %d: ", i); ERR(print_description(&str, @@ -525,8 +527,11 @@ stardis_init for(i = 0; i < tcount; ++i) { ERR(create_intface(stardis, i, &htable_interfaces)); } - if(args->out_filename) { - ERR(str_set(&stardis->out_filename, args->out_filename)); + if(args->paths_filename) { + ERR(str_set(&stardis->paths_filename, args->paths_filename)); + } + if(args->bin_green_filename) { + ERR(str_set(&stardis->bin_green_filename, args->bin_green_filename)); } } @@ -554,7 +559,7 @@ stardis_init } } /* If computation is on a volume, check medium is known */ - if(args->mode & MEDIUM_COMPUTE) { + if(args->mode & MODE_MEDIUM_COMPUTE) { if(!find_medium_by_name(stardis, &stardis->solve_name, NULL)) { logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), "Cannot find medium '%s'\n", str_cget(&stardis->solve_name)); @@ -608,7 +613,8 @@ stardis_release(struct stardis* stardis) if(stardis->dev) SDIS(device_ref_put(stardis->dev)); if(stardis->sdis_scn) SDIS(scene_ref_put(stardis->sdis_scn)); str_release(&stardis->solve_name); - str_release(&stardis->out_filename); + str_release(&stardis->paths_filename); + str_release(&stardis->bin_green_filename); darray_descriptions_release(&stardis->descriptions); release_geometry(&stardis->geometry); darray_size_t_release(&stardis->compute_surface.primitives); diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -56,6 +56,11 @@ enum description_type { 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 || (D) == DESC_BOUND_T_FOR_FLUID) + #define DARRAY_NAME interface_ptrs #define DARRAY_DATA struct sdis_interface* #include <rsys/dynamic_array.h> @@ -298,8 +303,7 @@ print_h_boundary const enum description_type type) { res_T res = RES_OK; - ASSERT(str && b - && (type == DESC_BOUND_H_FOR_SOLID || type == DESC_BOUND_H_FOR_FLUID)); + ASSERT(str && b && DESC_IS_H(type)); ERR(str_printf(str, "H boundary for %s '%s': emissivity=%g specular_fraction=%g hc=%g T=%g " "(using medium %u as external medium)", @@ -357,8 +361,7 @@ print_t_boundary const enum description_type type) { res_T res = RES_OK; - ASSERT(str && b - && (type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID)); + ASSERT(str && b && DESC_IS_T(type)); ERR(str_printf(str, "T boundary for %s' %s': T=%g ", (type == DESC_BOUND_T_FOR_SOLID ? "solid" : "fluid"), str_cget(&b->name), b->imposed_temperature)); @@ -574,9 +577,9 @@ error: goto end; } -static INLINE struct str* +static INLINE const struct str* get_description_name - (struct description* desc) + (const struct description* desc) { ASSERT(desc); switch (desc->type) { @@ -721,7 +724,7 @@ log_prt(const char* msg, void* ctx) } struct counts { - size_t smed_count, fmed_count, tbound_count, hbound_count, + unsigned smed_count, fmed_count, tbound_count, hbound_count, fbound_count, sfconnect_count; }; #define COUNTS_NULL__ {\ @@ -761,7 +764,8 @@ struct stardis { struct compute_surface compute_surface; /* 2D compute region when mode is [FLUX_]BOUNDARY_COMPUTE or MAP_COMPUTE */ - struct str out_filename; + struct str paths_filename; + struct str bin_green_filename; int mode; size_t samples; unsigned nthreads; diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -164,13 +164,14 @@ compute_probe(struct stardis* stardis) struct sdis_green_function* green = NULL; struct sdis_estimator* estimator = NULL; struct dump_path_context dump_ctx; + FILE* stream = NULL; - ASSERT(stardis && (stardis->mode & PROBE_COMPUTE)); + ASSERT(stardis && (stardis->mode & MODE_PROBE_COMPUTE)); d3_set(pos, stardis->probe); ERR(select_probe_type(stardis, 0, pos, &iprim, uv)); - if(stardis->mode & GREEN_MODE) { + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { ASSERT(iprim == SIZE_MAX); ERR(sdis_solve_probe_green_function(stardis->sdis_scn, stardis->samples, @@ -179,7 +180,19 @@ compute_probe(struct stardis* stardis) stardis->ambient_temp, stardis->ref_temp, &green)); - ERR(dump_green(green, stardis, stdout)); + if(stardis->mode & MODE_BIN_GREEN) { + ASSERT(!str_is_empty(&stardis->bin_green_filename)); + stream = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream) { + res = RES_IO_ERR; + goto error; + } + ERR(dump_green_bin(green, stardis, stream)); + fclose(stream); stream = NULL; + } + if(stardis->mode & MODE_GREEN) { + ERR(dump_green_ascii(green, stardis, stdout)); + } } else { ASSERT(iprim == SIZE_MAX); d2_splat(time, stardis->probe[3]); @@ -200,6 +213,7 @@ compute_probe(struct stardis* stardis) } end: + if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); return res; @@ -216,13 +230,14 @@ compute_probe_on_interface(struct stardis* stardis) struct sdis_estimator* estimator = NULL; struct sdis_green_function* green = NULL; struct dump_path_context dump_ctx; + FILE* stream = NULL; - ASSERT(stardis && (stardis->mode & PROBE_COMPUTE_ON_INTERFACE)); + ASSERT(stardis && (stardis->mode & MODE_PROBE_COMPUTE_ON_INTERFACE)); d3_set(pos, stardis->probe); ERR(select_probe_type(stardis, 1, pos, &iprim, uv)); + ASSERT(iprim != SIZE_MAX); - if(stardis->mode & GREEN_MODE) { - ASSERT(iprim == SIZE_MAX); + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { ERR(sdis_solve_probe_boundary_green_function(stardis->sdis_scn, stardis->samples, iprim, @@ -232,9 +247,20 @@ compute_probe_on_interface(struct stardis* stardis) stardis->ambient_temp, stardis->ref_temp, &green)); - ERR(dump_green(green, stardis, stdout)); + if(stardis->mode & MODE_BIN_GREEN) { + ASSERT(!str_is_empty(&stardis->bin_green_filename)); + stream = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream) { + res = RES_IO_ERR; + goto error; + } + ERR(dump_green_bin(green, stardis, stream)); + fclose(stream); stream = NULL; + } + if(stardis->mode & MODE_GREEN) { + ERR(dump_green_ascii(green, stardis, stdout)); + } } else { - ASSERT(iprim == SIZE_MAX); d2_splat(time, stardis->probe[3]); ERR(sdis_solve_probe_boundary(stardis->sdis_scn, stardis->samples, @@ -255,6 +281,7 @@ compute_probe_on_interface(struct stardis* stardis) } end: + if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); return res; @@ -353,7 +380,8 @@ compute_camera(struct stardis* stardis) size_t ix, iy; ASSERT(stardis - && !(stardis->mode & GREEN_MODE) && (stardis->mode & IR_COMPUTE)); + && !(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) + && (stardis->mode & MODE_IR_COMPUTE)); width = (size_t)stardis->camera.img_width; height = (size_t)stardis->camera.img_height; @@ -420,8 +448,9 @@ compute_medium(struct stardis* stardis) struct sdis_estimator* estimator = NULL; struct sdis_green_function* green = NULL; struct dump_path_context dump_ctx; + FILE* stream = NULL; - ASSERT(stardis && (stardis->mode & MEDIUM_COMPUTE)); + ASSERT(stardis && (stardis->mode & MODE_MEDIUM_COMPUTE)); /* Find medium */ medium = find_medium_by_name(stardis, &stardis->solve_name, NULL); @@ -433,7 +462,7 @@ compute_medium(struct stardis* stardis) goto error; } - if(stardis->mode & GREEN_MODE) { + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { ERR(sdis_solve_medium_green_function(stardis->sdis_scn, stardis->samples, medium, @@ -441,7 +470,19 @@ compute_medium(struct stardis* stardis) stardis->ambient_temp, stardis->ref_temp, &green)); - ERR(dump_green(green, stardis, stdout)); + if(stardis->mode & MODE_BIN_GREEN) { + ASSERT(!str_is_empty(&stardis->bin_green_filename)); + stream = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream) { + res = RES_IO_ERR; + goto error; + } + ERR(dump_green_bin(green, stardis, stream)); + fclose(stream); stream = NULL; + } + if(stardis->mode & MODE_GREEN) { + ERR(dump_green_ascii(green, stardis, stdout)); + } } else { d2_splat(time, stardis->probe[3]); time[0] = time[1] = stardis->probe[3]; @@ -462,6 +503,7 @@ compute_medium(struct stardis* stardis) } end: + if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); return res; @@ -525,12 +567,13 @@ compute_boundary(struct stardis* stardis) struct sdis_green_function* green = NULL; struct sdis_estimator* estimator = NULL; struct dump_path_context dump_ctx; + FILE* stream = NULL; - ASSERT(stardis && (stardis->mode & BOUNDARY_COMPUTE)); + ASSERT(stardis && (stardis->mode & MODE_BOUNDARY_COMPUTE)); d3_set(pos, stardis->probe); - if(stardis->mode & GREEN_MODE) { + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { ERR(sdis_solve_boundary_green_function(stardis->sdis_scn, stardis->samples, darray_size_t_cdata_get(&stardis->compute_surface.primitives), @@ -540,7 +583,19 @@ compute_boundary(struct stardis* stardis) stardis->ambient_temp, stardis->ref_temp, &green)); - ERR(dump_green(green, stardis, stdout)); + if(stardis->mode & MODE_BIN_GREEN) { + ASSERT(!str_is_empty(&stardis->bin_green_filename)); + stream = fopen(str_cget(&stardis->bin_green_filename), "wb"); + if(!stream) { + res = RES_IO_ERR; + goto error; + } + ERR(dump_green_bin(green, stardis, stream)); + fclose(stream); stream = NULL; + } + if(stardis->mode & MODE_GREEN) { + ERR(dump_green_ascii(green, stardis, stdout)); + } } else { d2_splat(time, stardis->probe[3]); ERR(sdis_solve_boundary(stardis->sdis_scn, @@ -562,6 +617,7 @@ compute_boundary(struct stardis* stardis) } end: + if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); return res; @@ -578,7 +634,7 @@ compute_flux_boundary(struct stardis* stardis) struct sdis_estimator* estimator = NULL; struct dump_path_context dump_ctx; - ASSERT(stardis && (stardis->mode & FLUX_BOUNDARY_COMPUTE)); + ASSERT(stardis && (stardis->mode & MODE_FLUX_BOUNDARY_COMPUTE)); d3_set(pos, stardis->probe); d2_splat(time, stardis->probe[3]); @@ -617,7 +673,8 @@ compute_map(struct stardis* stardis) size_t p; ASSERT(stardis - && (stardis->mode & MAP_COMPUTE) && !(stardis->mode & GREEN_MODE)); + && (stardis->mode & MODE_MAP_COMPUTE) + && !(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN))); darray_estimators_init(stardis->allocator, &estimators); estimators_initialized = 1; @@ -758,19 +815,19 @@ stardis_compute ASSERT(stardis && (stardis->mode & COMPUTE_MODES)); /* Compute */ - if(stardis->mode & PROBE_COMPUTE) + if(stardis->mode & MODE_PROBE_COMPUTE) ERR(compute_probe(stardis)); - else if(stardis->mode & PROBE_COMPUTE_ON_INTERFACE) + else if(stardis->mode & MODE_PROBE_COMPUTE_ON_INTERFACE) ERR(compute_probe_on_interface(stardis)); - else if(stardis->mode & IR_COMPUTE) + else if(stardis->mode & MODE_IR_COMPUTE) ERR(compute_camera(stardis)); - else if(stardis->mode & MEDIUM_COMPUTE) + else if(stardis->mode & MODE_MEDIUM_COMPUTE) ERR(compute_medium(stardis)); - else if(stardis->mode & BOUNDARY_COMPUTE) + else if(stardis->mode & MODE_BOUNDARY_COMPUTE) ERR(compute_boundary(stardis)); - else if(stardis->mode & FLUX_BOUNDARY_COMPUTE) + else if(stardis->mode & MODE_FLUX_BOUNDARY_COMPUTE) ERR(compute_flux_boundary(stardis)); - else if(stardis->mode & MAP_COMPUTE) + else if(stardis->mode & MODE_MAP_COMPUTE) ERR(compute_map(stardis)); else FATAL("Unknown mode.\n"); diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -130,19 +130,22 @@ create_intface interface_props = sdis_data_get(data); interface_props->imposed_temperature = -1; interface_props->imposed_flux = SDIS_FLUX_NONE; - interface_props->front_boundary_id = UINT_MAX; - interface_props->back_boundary_id = UINT_MAX; + interface_props->front_medium_id = UINT_MAX; + interface_props->back_medium_id = UINT_MAX; + interface_props->connect_id = UINT_MAX; if(front_defined) { switch (descriptions[fd].type) { 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: 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; @@ -155,11 +158,13 @@ create_intface 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: fluid_count++; id = descriptions[bd].d.fluid.fluid_id; + interface_props->back_medium_id = id; back_med = media[id]; fluid_side_shader = &interface_shader.back; break; @@ -185,14 +190,14 @@ create_intface || descriptions[fd].type == DESC_MAT_FLUID); fluid_side_shader = (descriptions[fd].type == DESC_MAT_SOLID) ? &interface_shader.back : &interface_shader.front; - interface_props->front_boundary_id = cd; + interface_props->connect_id = cd; } else { ASSERT(back_defined); ASSERT(descriptions[bd].type == DESC_MAT_SOLID || descriptions[bd].type == DESC_MAT_FLUID); fluid_side_shader = (descriptions[bd].type == DESC_MAT_SOLID) ? &interface_shader.back : &interface_shader.front; - interface_props->back_boundary_id = cd; + interface_props->connect_id = cd; } } switch(connect->type) { diff --git a/src/stardis-intface.h b/src/stardis-intface.h @@ -34,7 +34,7 @@ struct intface { double imposed_temperature; double imposed_flux; /* IDs */ - unsigned front_boundary_id, back_boundary_id; + unsigned front_medium_id, back_medium_id, connect_id; }; /* Declare the hash table that map an interface to its descriptor */ diff --git a/src/stardis-main.c b/src/stardis-main.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2018-2020 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "stardis-app.h" +#include "stardis-parsing.h" +#include "stardis-output.h" +#include "stardis-compute.h" + +#include <rsys/rsys.h> +#include <rsys/mem_allocator.h> +#include <rsys/logger.h> + +#include <stdlib.h> +#include <stdio.h> + +int +main + (int argc, + char** argv) +{ + struct args* args = NULL; + struct stardis stardis; + int logger_initialized = 0, allocator_initialized = 0, + args_initialized = 0, stardis_initialized = 0; + int err = EXIT_SUCCESS; + struct mem_allocator allocator; + struct logger logger; + res_T res = RES_OK; + + ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + allocator_initialized = 1; + + ERR(logger_init(&allocator, &logger)); + logger_initialized = 1; + /* Active loggin for args pasing */ + logger_set_stream(&logger, LOG_OUTPUT, log_prt, NULL); + logger_set_stream(&logger, LOG_ERROR, log_err, NULL); + logger_set_stream(&logger, LOG_WARNING, log_warn, NULL); + + ERR(init_args(&logger, &allocator, &args)); + args_initialized = 1; + ERR(parse_args(argc, argv, args)); + + if(args->mode & MODE_DUMP_HELP) { + short_help(stdout, argv[0]); + goto exit; + } + else if(args->mode & MODE_DUMP_VERSION) { + print_version(stdout); + goto exit; + } + + /* Deactivate some loggin according to the -V arg */ + if(args->verbose < 1) + logger_set_stream(&logger, LOG_ERROR, NULL, NULL); + if(args->verbose < 2) + logger_set_stream(&logger, LOG_WARNING, NULL, NULL); + if(args->verbose < 3) + logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL); + + ERR(stardis_init(args, &logger, &allocator, &stardis)); + stardis_initialized = 1; + release_args(args); + args_initialized = 0; + + if(stardis.mode & MODE_DUMP_VTK) { + /* Dump all the app-independent information */ + ERR(sg3d_geometry_dump_as_vtk(stardis.geometry.sg3d, stdout)); + /* Dump the compute region if any */ + if(stardis.mode & REGION_COMPUTE_MODES) { + ERR(dump_compute_region_at_the_end_of_vtk(&stardis, stdout)); + } + /* Dump possible holes + * TODO: as this extracts enclosures, it could dump front/back + * enclosure IDs too */ + ERR(dump_enclosure_related_stuff_at_the_end_of_vtk(&stardis, stdout)); + + /* If dump flag set exit after dump done */ + goto exit; + } + + ASSERT(stardis.mode & COMPUTE_MODES); + ERR(stardis_compute(&stardis)); + +exit: + if(args_initialized) release_args(args); + if(stardis_initialized) stardis_release(&stardis); + if(logger_initialized) logger_release(&logger); + if(allocator_initialized) { + if(MEM_ALLOCATED_SIZE(&allocator) != 0) { + char dump[4096] = { '\0' }; + MEM_DUMP(&allocator, dump, sizeof(dump)); + fprintf(stderr, "%s\n", dump); + fprintf(stderr, "\nMemory leaks: %zu Bytes\n", + MEM_ALLOCATED_SIZE(&allocator)); + } + mem_shutdown_proxy_allocator(&allocator); + } + return err; +error: + err = EXIT_FAILURE; + goto exit; +} diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -33,6 +33,7 @@ #include <rsys/str.h> #include <limits.h> +#include <string.h> #include <stdio.h> #define HTABLE_NAME weigth @@ -41,8 +42,10 @@ #include <rsys/hash_table.h> struct w_ctx { + struct mem_allocator* alloc; const struct darray_descriptions* desc; - struct htable_weigth weigths; + struct htable_weigth pw; + struct htable_weigth flux; FILE* stream; }; @@ -61,39 +64,7 @@ enum enclosure_errors_t { ******************************************************************************/ static res_T -print_power_term - (struct sdis_medium* mdm, - const double power_term, - void* ctx) -{ - res_T res = RES_OK; - struct sdis_data* data = NULL; - enum sdis_medium_type type; - unsigned id; - const struct w_ctx* w_ctx = ctx; - - ASSERT(mdm && ctx); - - data = sdis_medium_get_data(mdm); - type = sdis_medium_get_type(mdm); - - switch (type) { - case SDIS_FLUID: { - FATAL("Unexpected power term in fluid"); - } - case SDIS_SOLID: { - struct solid* d__ = sdis_data_get(data); - id = d__->id; - fprintf(w_ctx->stream, "\tS\t%u\t%g", id, power_term); - break; - } - default: FATAL("Unreachable code.\n"); break; - } - return res; -} - -static res_T -get_flux_terms +merge_flux_terms (struct sdis_interface* interf, const enum sdis_side side, const double flux_term, @@ -102,18 +73,19 @@ get_flux_terms res_T res = RES_OK; struct sdis_data* data = NULL; struct intface* d__; - unsigned id; + unsigned mid, cid; struct w_ctx* w_ctx = ctx; const struct description* descs; - ASSERT(interf && ctx); + ASSERT(interf && w_ctx); data = sdis_interface_get_data(interf); d__ = sdis_data_get(data); - id = (side == SDIS_FRONT) ? d__->front_boundary_id : d__->back_boundary_id; + mid = (side == SDIS_FRONT) ? d__->front_medium_id : d__->back_medium_id; + cid = d__->connect_id; descs = darray_descriptions_cdata_get(w_ctx->desc); - switch (descs[id].type) { + switch (descs[cid].type) { case DESC_BOUND_T_FOR_SOLID: case DESC_BOUND_T_FOR_FLUID: case DESC_BOUND_H_FOR_SOLID: @@ -121,9 +93,47 @@ get_flux_terms FATAL("Cannot have a flux term here.\n"); break; case DESC_BOUND_F_FOR_SOLID: { double* w; - w = htable_weigth_find(&w_ctx->weigths, &id); + w = htable_weigth_find(&w_ctx->flux, &cid); if(w) *w += flux_term; - else ERR(htable_weigth_set(&w_ctx->weigths, &id, &flux_term)); + else ERR(htable_weigth_set(&w_ctx->flux, &cid, &flux_term)); + break; + } + default: FATAL("Unreachable code.\n"); break; + } +end: + return res; +error: + goto end; +} + +static res_T +merge_power_terms + (struct sdis_medium* mdm, + const double power_term, + void* ctx) +{ + res_T res = RES_OK; + struct sdis_data* data = NULL; + enum sdis_medium_type type; + struct w_ctx* w_ctx = ctx; + + ASSERT(mdm && w_ctx); + + data = sdis_medium_get_data(mdm); + type = sdis_medium_get_type(mdm); + + switch (type) { + case SDIS_FLUID: { + /* Could be OK, but unimplemented in stardis */ + FATAL("Unexpected power term in fluid"); + } + case SDIS_SOLID: { + struct solid* d__ = sdis_data_get(data); + double* w; + unsigned mid = d__->id; + w = htable_weigth_find(&w_ctx->pw, &mid); + if(w) *w += power_term; + else ERR(htable_weigth_set(&w_ctx->pw, &mid, &power_term)); break; } default: FATAL("Unreachable code.\n"); break; @@ -152,16 +162,16 @@ dump_path ASSERT(path && dump_ctx && dump_ctx->stardis - && !str_is_empty(&dump_ctx->stardis->out_filename)); + && !str_is_empty(&dump_ctx->stardis->paths_filename)); - name_sz = 16 + str_len(&dump_ctx->stardis->out_filename); + name_sz = 16 + str_len(&dump_ctx->stardis->paths_filename); name = MEM_CALLOC(dump_ctx->stardis->allocator, name_sz, sizeof(*name)); if(!name) { res = RES_MEM_ERR; goto error; } snprintf(name, name_sz, "%s%08zu.vtk", - str_cget(&dump_ctx->stardis->out_filename), dump_ctx->rank++); + str_cget(&dump_ctx->stardis->paths_filename), dump_ctx->rank++); stream = fopen(name, "w"); if(!stream) { @@ -229,7 +239,7 @@ dump_path } end: - if(name) MEM_RM(dump_ctx->stardis->allocator, name); + MEM_RM(dump_ctx->stardis->allocator, name); if(stream) fclose(stream); return res; error: @@ -237,112 +247,6 @@ error: } res_T -print_sample - (struct sdis_green_path* path, - void* ctx) -{ - res_T res = RES_OK; - struct sdis_point pt = SDIS_POINT_NULL; - struct sdis_data* data = NULL; - enum sdis_medium_type type; - struct htable_weigth_iterator it, end; - unsigned id; - size_t pcount, fcount; - struct w_ctx* w_ctx = ctx; - const struct description* descs; - CHK(path && ctx); - - ERR(sdis_green_path_get_limit_point(path, &pt)); - - /* For each path, prints: - * # end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n - * with: - * - end = end_type end_id; end_type = T | H | X | A | F | S - * - power_term_i = power_type_i power_id_i factor_i - * - flux_term_i = flux_id_i factor_i - */ - - descs = darray_descriptions_cdata_get(w_ctx->desc); - switch (pt.type) { - case SDIS_FRAGMENT: { - struct intface* d__; - data = sdis_interface_get_data(pt.data.itfrag.intface); - d__ = sdis_data_get(data); - id = (pt.data.itfrag.fragment.side == SDIS_FRONT) - ? d__->front_boundary_id : d__->back_boundary_id; - ASSERT(id != UINT_MAX); - switch (descs[id].type) { - case DESC_BOUND_T_FOR_SOLID: - case DESC_BOUND_T_FOR_FLUID: - fprintf(w_ctx->stream, "T\t%u", id); - break; - case DESC_BOUND_H_FOR_SOLID: - case DESC_BOUND_H_FOR_FLUID: - fprintf(w_ctx->stream, "H\t%u", id); - break; - case DESC_BOUND_F_FOR_SOLID: - fprintf(w_ctx->stream, "X\t%u", id); - break; - default: FATAL("Unreachable code.\n"); break; - } - break; - } - case SDIS_VERTEX: - type = sdis_medium_get_type(pt.data.mdmvert.medium); - data = sdis_medium_get_data(pt.data.mdmvert.medium); - if(pt.data.mdmvert.vertex.P[0] == INF) { - /* Radiative output (ambient temperature)*/ - size_t sz = darray_descriptions_size_get(w_ctx->desc); - ASSERT(sz <= UINT_MAX); - fprintf(w_ctx->stream, "A\t%u", (unsigned)sz); - } - else if(type == SDIS_FLUID) { - struct fluid* d__ = sdis_data_get(data); - id = d__->id; - if(d__->is_outside) - /* If outside the model and in a fluid with known temperature, - * its a fluid attached to a H boundary */ - fprintf(w_ctx->stream, "H\t%u", id); - /* In a standard fluid with known temperature */ - else fprintf(w_ctx->stream, "F\t%u", id); - } else { - struct solid* d__ = sdis_data_get(data); - ASSERT(type == SDIS_SOLID); - id = d__->id; - ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */ - fprintf(w_ctx->stream, "S\t%u", id); - } - break; - default: FATAL("Unreachable code.\n"); break; - } - - ERR(sdis_green_function_get_power_terms_count(path, &pcount)); - - htable_weigth_clear(&w_ctx->weigths); - ERR(sdis_green_path_for_each_flux_term(path, get_flux_terms, w_ctx)); - fcount = htable_weigth_size_get(&w_ctx->weigths); - - fprintf(w_ctx->stream, "\t%zu\t%zu", pcount, fcount); - - ERR(sdis_green_path_for_each_power_term(path, print_power_term, ctx)); - - htable_weigth_begin(&w_ctx->weigths, &it); - htable_weigth_end(&w_ctx->weigths, &end); - while(!htable_weigth_iterator_eq(&it, &end)) { - double* w = htable_weigth_iterator_data_get(&it); - unsigned* k = htable_weigth_iterator_key_get(&it); - fprintf(w_ctx->stream, "\t%u\t%g", *k, *w); - htable_weigth_iterator_next(&it); - } - fprintf(w_ctx->stream, "\n"); - -end: - return res; -error: - goto end; -} - -res_T dump_image (const struct sdis_estimator_buffer* buf, FILE* stream) @@ -433,23 +337,368 @@ error: goto end; } +#define FW(Ptr, Count) \ + if((Count) != fwrite((Ptr), sizeof(*(Ptr)), (Count), stream)) { \ + res = RES_IO_ERR; \ + goto error; \ + } + +struct path_header { + unsigned id; + unsigned pcount, fcount; +}; + +res_T +dump_sample + (struct sdis_green_path* path, + void* ctx) +{ + res_T res = RES_OK; + struct sdis_point pt = SDIS_POINT_NULL; + struct sdis_data* data = NULL; + enum sdis_medium_type type; + struct htable_weigth_iterator it, end; + struct path_header header; + struct w_ctx* w_ctx = ctx; + const struct description* descs; + FILE* stream; + unsigned* ids = NULL; + double* weights = NULL; + size_t sz, i; + + CHK(path && ctx); + + stream = w_ctx->stream; + ERR(sdis_green_path_get_limit_point(path, &pt)); + + /* For each path, dump: + * # end_id #power_terms #flux_terms power_id_1 ... power_id_n flux_id_1 ... flux_id_n + * power_factor_1 ... power_factor_n flux_factor_1 ... flux_factor_n + */ + + descs = darray_descriptions_cdata_get(w_ctx->desc); + switch (pt.type) { + case SDIS_FRAGMENT: { + struct intface* d__; + unsigned mid, cid; + data = sdis_interface_get_data(pt.data.itfrag.intface); + d__ = sdis_data_get(data); + mid = (pt.data.itfrag.fragment.side == SDIS_FRONT) + ? d__->front_medium_id : d__->back_medium_id; + cid = d__->connect_id; + CHK(DESC_IS_T(descs[cid].type) || DESC_IS_H(descs[cid].type)); + header.id = cid; + break; + } + case SDIS_VERTEX: + type = sdis_medium_get_type(pt.data.mdmvert.medium); + data = sdis_medium_get_data(pt.data.mdmvert.medium); + if(pt.data.mdmvert.vertex.P[0] == INF) { + /* Radiative output (ambient temperature)*/ + sz = darray_descriptions_size_get(w_ctx->desc); + ASSERT(sz <= UINT_MAX); + header.id = (unsigned)sz; /* Ambient ID */ + } + else if(type == SDIS_FLUID) { + struct fluid* d__ = sdis_data_get(data); + header.id = d__->id; + } else { + struct solid* d__ = sdis_data_get(data); + ASSERT(type == SDIS_SOLID); + ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */ + header.id = d__->id; + } + break; + default: FATAL("Unreachable code.\n"); break; + } + + /* Merge power and flux terms */ + htable_weigth_clear(&w_ctx->pw); + htable_weigth_clear(&w_ctx->flux); + ERR(sdis_green_path_for_each_power_term(path, merge_power_terms, w_ctx)); + ERR(sdis_green_path_for_each_flux_term(path, merge_flux_terms, w_ctx)); + sz = htable_weigth_size_get(&w_ctx->pw); + ASSERT(sz <= UINT_MAX); + header.pcount = (unsigned)sz; + sz = htable_weigth_size_get(&w_ctx->flux); + ASSERT(sz <= UINT_MAX); + header.fcount = (unsigned)sz; + + /* Write path's header */ + FW(&header, 1); + + /* Allocate buffers */ + sz = header.pcount + header.fcount; + ids = MEM_CALLOC(w_ctx->alloc, sz, sizeof(*ids)); + weights = MEM_CALLOC(w_ctx->alloc, sz, sizeof(*weights)); + if(!ids || !weights) { + res = RES_MEM_ERR; + goto error; + } + + /* Write terms */ + htable_weigth_begin(&w_ctx->pw, &it); + htable_weigth_end(&w_ctx->pw, &end); + i = 0; + while(!htable_weigth_iterator_eq(&it, &end)) { + double* w = htable_weigth_iterator_data_get(&it); + unsigned* k = htable_weigth_iterator_key_get(&it); + ids[i] = *k; + weights[i] = *w; + htable_weigth_iterator_next(&it); + i++; + } + CHK(i == header.pcount); + + htable_weigth_begin(&w_ctx->flux, &it); + htable_weigth_end(&w_ctx->flux, &end); + while (!htable_weigth_iterator_eq(&it, &end)) { + double* w = htable_weigth_iterator_data_get(&it); + unsigned* k = htable_weigth_iterator_key_get(&it); + ids[i] = *k; + weights[i] = *w; + htable_weigth_iterator_next(&it); + i++; + } + CHK(i == header.pcount + header.fcount); + + FW(ids, sz); + FW(weights, sz); + + +end: + MEM_RM(w_ctx->alloc, ids); + MEM_RM(w_ctx->alloc, weights); + return res; +error: + goto end; +} + res_T -dump_green +dump_green_bin (struct sdis_green_function* green, const struct stardis* stardis, FILE* stream) { res_T res = RES_OK; - size_t ok_count, failed_count, sz; + size_t ok_count, failed_count; + size_t sz; struct w_ctx w_ctx; int table_initialized = 0; unsigned i, szd; const struct description* descs; + unsigned name_pool_sz = 0; + char* name_pool = NULL; + char* pool_ptr; + char green_string[] = "BINGREEN"; ASSERT(green && stardis && stream); - ERR(sdis_green_function_get_invalid_paths_count(green, &failed_count)); ERR(sdis_green_function_get_paths_count(green, &ok_count)); + ERR(sdis_green_function_get_invalid_paths_count(green, &failed_count)); + sz = darray_descriptions_size_get(&stardis->descriptions); + ASSERT(sz <= UINT_MAX); + szd = (unsigned)sz; + descs = darray_descriptions_cdata_get(&stardis->descriptions); + + /* Save names that donot fit inplace */ + FOR_EACH(i, 0, szd) { + const struct description* desc = descs + i; + const struct str* name = get_description_name(desc); + const size_t len = str_len(name); + ASSERT(name_pool_sz + len + 1 <= UINT_MAX); + name_pool_sz += (unsigned)(len + 1); + } + pool_ptr = name_pool = MEM_ALLOC(stardis->allocator, name_pool_sz); + if(!name_pool) { + res = RES_MEM_ERR; + goto error; + } + FOR_EACH(i, 0, szd) { + const struct description* desc = descs + i; + const struct str* name = get_description_name(desc); + const size_t len = str_len(name); + strcpy(pool_ptr, name->cstr); + pool_ptr += len + 1; + } + ASSERT(pool_ptr == name_pool + name_pool_sz); + /*Write Green string */ + FW(green_string, sizeof(green_string)); + + /* Write counts */ + FW(&szd, 1); + FW(&stardis->counts, 1); + FW(&name_pool_sz, 1); + FW(&ok_count, 1); + FW(&failed_count, 1); + + /* Write descriptions*/ + FW(descs, szd); + + /* Write names */ + if(name_pool_sz) + FW(name_pool, name_pool_sz); + + FW(&stardis->ambient_temp, 1); + FW(&stardis->ref_temp, 1); + + w_ctx.alloc = stardis->allocator; + w_ctx.desc = &stardis->descriptions; + htable_weigth_init(NULL, &w_ctx.pw); + htable_weigth_init(NULL, &w_ctx.flux); + w_ctx.stream = stream; + table_initialized = 1; + + /* Write samples */ + ERR(sdis_green_function_for_each_path(green, dump_sample, &w_ctx)); + +end: + MEM_RM(stardis->allocator, name_pool); + if(table_initialized) htable_weigth_release(&w_ctx.pw); + if(table_initialized) htable_weigth_release(&w_ctx.flux); + return res; +error: + goto end; +} + +res_T +print_sample + (struct sdis_green_path* path, + void* ctx) +{ + res_T res = RES_OK; + struct sdis_point pt = SDIS_POINT_NULL; + struct sdis_data* data = NULL; + enum sdis_medium_type type; + struct htable_weigth_iterator it, end; + unsigned mid, cid; + size_t pcount, fcount; + struct w_ctx* w_ctx = ctx; + const struct description* descs; + CHK(path && ctx); + + ERR(sdis_green_path_get_limit_point(path, &pt)); + + /* For each path, prints: + * # end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n + * with: + * - end = end_type end_id; end_type = T | H | A | F | S + * - power_term_i = power_type_i power_id_i factor_i + * - flux_term_i = flux_id_i factor_i + */ + + descs = darray_descriptions_cdata_get(w_ctx->desc); + switch (pt.type) { + case SDIS_FRAGMENT: { + struct intface* d__; + data = sdis_interface_get_data(pt.data.itfrag.intface); + d__ = sdis_data_get(data); + mid = (pt.data.itfrag.fragment.side == SDIS_FRONT) + ? d__->front_medium_id : d__->back_medium_id; + cid = d__->connect_id; + ASSERT(mid != UINT_MAX); + switch (descs[cid].type) { + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + fprintf(w_ctx->stream, "T\t%u", cid); + break; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + fprintf(w_ctx->stream, "H\t%u", cid); + break; + case DESC_BOUND_F_FOR_SOLID: + FATAL("Heat path cannot end at a flux boundary.\n"); break; + break; + default: FATAL("Unreachable code.\n"); break; + } + break; + } + case SDIS_VERTEX: + type = sdis_medium_get_type(pt.data.mdmvert.medium); + data = sdis_medium_get_data(pt.data.mdmvert.medium); + if(pt.data.mdmvert.vertex.P[0] == INF) { + /* Radiative output (ambient temperature)*/ + size_t sz = darray_descriptions_size_get(w_ctx->desc); + ASSERT(sz <= UINT_MAX); + fprintf(w_ctx->stream, "A\t%u", (unsigned)sz); + } + else if(type == SDIS_FLUID) { + struct fluid* d__ = sdis_data_get(data); + mid = d__->id; + if(d__->is_outside) + /* If outside the model and in a fluid with known temperature, + * its a fluid attached to a H boundary */ + fprintf(w_ctx->stream, "H\t%u", mid); + /* In a standard fluid with known temperature */ + else fprintf(w_ctx->stream, "F\t%u", mid); + } else { + struct solid* d__ = sdis_data_get(data); + ASSERT(type == SDIS_SOLID); + mid = d__->id; + ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */ + fprintf(w_ctx->stream, "S\t%u", mid); + } + break; + default: FATAL("Unreachable code.\n"); break; + } + + ERR(sdis_green_function_get_power_terms_count(path, &pcount)); + + htable_weigth_clear(&w_ctx->pw); + htable_weigth_clear(&w_ctx->flux); + ERR(sdis_green_path_for_each_power_term(path, merge_power_terms, w_ctx)); + ERR(sdis_green_path_for_each_flux_term(path, merge_flux_terms, w_ctx)); + fcount = htable_weigth_size_get(&w_ctx->flux); + + fprintf(w_ctx->stream, "\t%zu\t%zu", pcount, fcount); + + htable_weigth_begin(&w_ctx->pw, &it); + htable_weigth_end(&w_ctx->pw, &end); + while(!htable_weigth_iterator_eq(&it, &end)) { + double* w = htable_weigth_iterator_data_get(&it); + unsigned* k = htable_weigth_iterator_key_get(&it); + fprintf(w_ctx->stream, "\t%u\t%g", *k, *w); + htable_weigth_iterator_next(&it); + } + + htable_weigth_begin(&w_ctx->flux, &it); + htable_weigth_end(&w_ctx->flux, &end); + while (!htable_weigth_iterator_eq(&it, &end)) { + double* w = htable_weigth_iterator_data_get(&it); + unsigned* k = htable_weigth_iterator_key_get(&it); + fprintf(w_ctx->stream, "\t%u\t%g", *k, *w); + htable_weigth_iterator_next(&it); + } + fprintf(w_ctx->stream, "\n"); + +end: + return res; +error: + goto end; +} + +res_T +dump_green_ascii + (struct sdis_green_function* green, + const struct stardis* stardis, + FILE* stream) +{ + res_T res = RES_OK; + unsigned ok_count, failed_count; + size_t sz; + struct w_ctx w_ctx; + int table_initialized = 0; + unsigned i, szd; + const struct description* descs; + + ASSERT(green && stardis && stream); + + ERR(sdis_green_function_get_paths_count(green, &sz)); + ASSERT(sz <= UINT_MAX); + ok_count = (unsigned)sz; + ERR(sdis_green_function_get_invalid_paths_count(green, &sz)); + ASSERT(sz <= UINT_MAX); + failed_count = (unsigned)sz; sz = darray_descriptions_size_get(&stardis->descriptions); ASSERT(sz <= UINT_MAX); szd = (unsigned)sz; @@ -459,7 +708,7 @@ dump_green fprintf(stream, "---BEGIN GREEN---\n"); fprintf(stream, "# #solids #fluids #t_boundaries #h_boundaries #f_boundaries #ok #failures\n"); - fprintf(stream, "%zu %zu %zu %zu %zu %zu %zu\n", + fprintf(stream, "%u %u %u %u %u %u %u\n", stardis->counts.smed_count, stardis->counts.fmed_count, stardis->counts.tbound_count, stardis->counts.hbound_count, stardis->counts.fbound_count, ok_count, failed_count); @@ -483,7 +732,7 @@ dump_green FOR_EACH(i, 0, szd) { const struct description* desc = descs + i; const struct mat_fluid* fl; - if (desc->type != DESC_MAT_FLUID) continue; + if(desc->type != DESC_MAT_FLUID) continue; fl = &desc->d.fluid; fprintf(stream, "%u\t%s\t%g\t%g\n", i, str_cget(&fl->name), fl->rho, fl->cp); @@ -540,12 +789,14 @@ dump_green fprintf(stream, "# Samples\n"); fprintf(stream, "# end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n\n"); - fprintf(stream, "# end = end_type end_id; end_type = T | H | X | A | F | S\n"); - fprintf(stream, "# power_term_i = power_type_i power_id_i factor_i\n"); + fprintf(stream, "# end = end_type end_id; end_type = T | H | A | F | S\n"); + fprintf(stream, "# power_term_i = power_id_i factor_i\n"); fprintf(stream, "# flux_term_i = flux_id_i factor_i\n"); + w_ctx.alloc = stardis->allocator; w_ctx.desc = &stardis->descriptions; - htable_weigth_init(NULL, &w_ctx.weigths); + htable_weigth_init(NULL, &w_ctx.pw); + htable_weigth_init(NULL, &w_ctx.flux); w_ctx.stream = stream; table_initialized = 1; @@ -554,7 +805,8 @@ dump_green fprintf(stream, "---END GREEN---\n"); end: - if(table_initialized) htable_weigth_release(&w_ctx.weigths); + if(table_initialized) htable_weigth_release(&w_ctx.pw); + if(table_initialized) htable_weigth_release(&w_ctx.flux); return res; error: goto end; @@ -655,8 +907,8 @@ dump_enclosure_related_stuff_at_the_end_of_vtk } exit: - if(trgs) MEM_RM(stardis->allocator, trgs); - if(enc_status) MEM_RM(stardis->allocator, enc_status); + MEM_RM(stardis->allocator, trgs); + MEM_RM(stardis->allocator, enc_status); if(senc3d_scn) senc3d_scene_ref_put(senc3d_scn); if(senc_dev) senc3d_device_ref_put(senc_dev); return res; @@ -682,54 +934,78 @@ print_single_MC_result /* Print the results */ switch (stardis->mode & COMPUTE_MODES) { - case PROBE_COMPUTE: - case PROBE_COMPUTE_ON_INTERFACE: - fprintf(stream, "Temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", - SPLIT4(stardis->probe), - result.E, /* Expected value */ - result.SE); /* Standard error */ + case MODE_PROBE_COMPUTE: + case MODE_PROBE_COMPUTE_ON_INTERFACE: + if(stardis->mode & MODE_EXTENDED_RESULTS) { + fprintf(stream, "Temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", + SPLIT4(stardis->probe), + result.E, /* Expected value */ + result.SE); /* Standard error */ + } + else fprintf(stream, "%g %g %zu %zu\n", + result.E, result.SE, nfailures, stardis->samples); break; - case MEDIUM_COMPUTE: - fprintf(stream, "Temperature in medium %s at t=%g = %g +/- %g\n", - str_cget(&stardis->solve_name), stardis->probe[3], - result.E, /* Expected value */ - result.SE); /* Standard error */ + case MODE_MEDIUM_COMPUTE: + if(stardis->mode & MODE_EXTENDED_RESULTS) { + fprintf(stream, "Temperature in medium %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->probe[3], + result.E, /* Expected value */ + result.SE); /* Standard error */ + } + else fprintf(stream, "%g %g %zu %zu\n", + result.E, result.SE, nfailures, stardis->samples); break; - case BOUNDARY_COMPUTE: - fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", - str_cget(&stardis->solve_name), stardis->probe[3], - result.E, /* Expected value */ - result.SE); /* Standard error */ + case MODE_BOUNDARY_COMPUTE: + if(stardis->mode & MODE_EXTENDED_RESULTS) { + fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->probe[3], + result.E, /* Expected value */ + result.SE); /* Standard error */ + } + else fprintf(stream, "%g %g %zu %zu\n", + result.E, result.SE, nfailures, stardis->samples); break; - case FLUX_BOUNDARY_COMPUTE: { + case MODE_FLUX_BOUNDARY_COMPUTE: { enum sdis_estimator_type type; ERR(sdis_estimator_get_type(estimator, &type)); ASSERT(type == SDIS_ESTIMATOR_FLUX); - fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", - str_cget(&stardis->solve_name), stardis->probe[3], - result.E, /* Expected value */ - result.SE); /* Standard error */ - ERR(sdis_estimator_get_convective_flux(estimator, &result)); - fprintf(stream, "Convective flux at boundary %s at t=%g = %g +/- %g\n", - str_cget(&stardis->solve_name), stardis->probe[3], - result.E, /* Expected value */ - result.SE); /* Standard error */ - ERR(sdis_estimator_get_radiative_flux(estimator, &result)); - fprintf(stream, "Radiative flux at boundary %s at t=%g = %g +/- %g\n", - str_cget(&stardis->solve_name), stardis->probe[3], - result.E, /* Expected value */ - result.SE); /* Standard error */ - ERR(sdis_estimator_get_total_flux(estimator, &result)); - fprintf(stream, "Total flux Flux at boundary %s at t=%g = %g +/- %g\n", - str_cget(&stardis->solve_name), stardis->probe[3], - result.E, /* Expected value */ - result.SE); /* Standard error */ + if(stardis->mode & MODE_EXTENDED_RESULTS) { + fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->probe[3], + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_convective_flux(estimator, &result)); + fprintf(stream, "Convective flux at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->probe[3], + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_radiative_flux(estimator, &result)); + fprintf(stream, "Radiative flux at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->probe[3], + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_total_flux(estimator, &result)); + fprintf(stream, "Total flux Flux at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->probe[3], + result.E, /* Expected value */ + result.SE); /* Standard error */ + } else { + fprintf(stream, "%g %g ", result.E, result.SE); + ERR(sdis_estimator_get_convective_flux(estimator, &result)); + fprintf(stream, "%g %g ", result.E, result.SE); + ERR(sdis_estimator_get_radiative_flux(estimator, &result)); + fprintf(stream, "%g %g ", result.E, result.SE); + ERR(sdis_estimator_get_total_flux(estimator, &result)); + fprintf(stream, "%g %g ", result.E, result.SE); + fprintf(stream, "%zu %zu\n", nfailures, stardis->samples); + } break; } default: FATAL("Invalid mode."); } - fprintf(stream, "#failures: %zu/%zu\n", nfailures, stardis->samples); + if(stardis->mode & MODE_EXTENDED_RESULTS) + fprintf(stream, "#failures: %zu/%zu\n", nfailures, stardis->samples); if(nfailures) logger_print(stardis->logger, LOG_ERROR, "#failures: %zu/%zu\n", nfailures, stardis->samples); @@ -875,7 +1151,7 @@ dump_compute_region_at_the_end_of_vtk unsigned prop[SG3D_PROP_TYPES_COUNT__]; struct sdis_medium* medium; unsigned medium_id; - ASSERT(stardis->mode & MEDIUM_COMPUTE); + ASSERT(stardis->mode & MODE_MEDIUM_COMPUTE); medium = find_medium_by_name(stardis, &stardis->solve_name, &medium_id); ASSERT(medium != NULL); (void)medium; FOR_EACH(i, 0, tsz) { @@ -898,7 +1174,7 @@ dump_compute_region_at_the_end_of_vtk fprintf(stream, "%u\n", v[i] == UCHAR_MAX ? UINT_MAX : v[i]); exit: - if(v) MEM_RM(stardis->allocator, v); + MEM_RM(stardis->allocator, v); return res; error: goto exit; diff --git a/src/stardis-output.h b/src/stardis-output.h @@ -53,7 +53,13 @@ dump_image FILE* stream); extern res_T -dump_green +dump_green_ascii + (struct sdis_green_function* green, + const struct stardis* stardis, + FILE* stream); + +extern res_T +dump_green_bin (struct sdis_green_function* green, const struct stardis* stardis, FILE* stream); diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -188,7 +188,7 @@ read_sides_and_files add_geom_ctx.properties[SG3D_BACK] = SG3D_UNSPECIFIED_PROPERTY; add_geom_ctx.properties[SG3D_INTFACE] = id; } else { - tk = strtok_r(NULL, " ", tok_ctx); + tk = strtok_r(NULL, " \t", tok_ctx); if(!tk) { if(file_count == 0) { /* At least 1 side */ @@ -220,7 +220,7 @@ read_sides_and_files goto error; } } - tk = strtok_r(NULL, " ", tok_ctx); + tk = strtok_r(NULL, " \t", tok_ctx); if(!tk) { if(!side_is_intface /* Has read a side */ || !file_count) /* Need at least 1 file */ @@ -314,26 +314,30 @@ release_args(struct args* args) { ASSERT(args); darray_str_release(&args->model_files); + free(args); } char mode_option - (const enum stardis_mode m) + (const int m) { int found = 0; char res = '?'; - if(m & PROBE_COMPUTE) { found++; res = 'p'; } - if(m & PROBE_COMPUTE_ON_INTERFACE) { found++; res = 'P'; } - if(m & MEDIUM_COMPUTE) { found++; res = 'm'; } - if(m & BOUNDARY_COMPUTE) { found++; res = 's'; } - if(m & FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; } - if(m & IR_COMPUTE) { found++; res = 'R'; } - if(m & MAP_COMPUTE) { found++; res = 'S'; } - if(m & DUMP_VTK) { found++; res = 'd'; } - if(m & DUMP_PATHS) { found++; res = 'D'; } - if(m & DUMP_HELP) { found++; res = 'h'; } - if(m & DUMP_VERSION) { found++; res = 'v'; } - if(m & GREEN_MODE) { found++; res = 'g'; } + if(m & MODE_DUMP_VTK) { found++; res = 'd'; } + if(m & MODE_DUMP_PATHS) { found++; res = 'D'; } + if(m & MODE_EXTENDED_RESULTS) { found++; res = 'e'; } + if(m & MODE_FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; } + if(m & MODE_GREEN) { found++; res = 'g'; } + if(m & MODE_BIN_GREEN) { found++; res = 'G'; } + if(m & MODE_DUMP_HELP) { found++; res = 'h'; } + if(m & MODE_MEDIUM_COMPUTE) { found++; res = 'm'; } + if(m & MODE_PROBE_COMPUTE) { found++; res = 'p'; } + if(m & MODE_PROBE_COMPUTE_ON_INTERFACE) { found++; res = 'P'; } + if(m & MODE_IR_COMPUTE) { found++; res = 'R'; } + if(m & MODE_BOUNDARY_COMPUTE) { found++; res = 's'; } + if(m & MODE_MAP_COMPUTE) { found++; res = 'S'; } + if(m & MODE_VERBOSITY) { found++; res = 'V'; } + if(m & MODE_DUMP_VERSION) { found++; res = 'v'; } ASSERT(found == 1); return res; } @@ -424,14 +428,20 @@ short_help fprintf(stream, "\n -d\n"); fprintf(stream, " Dump the geometry to stdout in VTK format along with various properties.\n"); - fprintf(stream, "\n -D TYPE\n"); - fprintf(stream, " Dump thermal paths of the given TYPE to stdout in VTK format.\n"); + fprintf(stream, "\n -D TYPE,FILE_NAMES_PREFIX\n"); + fprintf(stream, " Write thermal paths of the given TYPE in VTK format.\n"); + + fprintf(stream, "\n -e\n"); + fprintf(stream, " Use extended format to output Monte-Carlo results.\n"); fprintf(stream, "\n -f SCALE_FACTOR\n"); fprintf(stream, " Rescale the geometry before sending it to the solver.\n"); fprintf(stream, "\n -g\n"); - fprintf(stream, " Change the required computation to produce the green function.\n"); + fprintf(stream, " Change the computation to produce the green function.\n"); + + fprintf(stream, "\n -G BIN_FILE_NAME\n"); + fprintf(stream, " Change the computation to produce the green function.\n"); fprintf(stream, "\n -h\n"); fprintf(stream, " Print this help and exit.\n"); @@ -460,7 +470,7 @@ parse_args { int opt = 0, n_used = 0; size_t len = 0; - const char option_list[] = "a:dD:f:F:ghm:M:n:p:P:r:R:s:S:t:vV:"; + const char option_list[] = "a:dD:ef:F:gG:hm:M:n:p:P:r:R:s:S:t:vV:"; char buf[128]; res_T res = RES_OK; @@ -500,13 +510,17 @@ parse_args case 'd': if(args->mode & USE_STDOUT_MODES) { res = RES_BAD_ARG; - print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_VTK); + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_VTK); logger_print(args->logger, LOG_ERROR, "Option -%c cannot be used in conjunction with other dump options (%s).\n", (char)opt, buf); goto error; } - args->mode |= DUMP_VTK; + args->mode |= MODE_DUMP_VTK; + break; + + case 'e': + args->mode |= MODE_EXTENDED_RESULTS; break; case 'D': { @@ -514,7 +528,7 @@ parse_args if(!ptr || ptr != strchr(optarg, ',')) res = RES_BAD_ARG; /* Single ',' expected */ else { - args->out_filename = ptr + 1; + args->paths_filename = ptr + 1; *ptr = '\0'; } if(res == RES_OK) { @@ -535,7 +549,7 @@ parse_args opt, optarg); goto error; } - args->mode |= DUMP_PATHS; + args->mode |= MODE_DUMP_PATHS; break; } @@ -555,19 +569,24 @@ parse_args /*case 'F': see 's' */ case 'g': - args->mode |= GREEN_MODE; + args->mode |= MODE_GREEN; + break; + + case 'G': + args->mode |= MODE_BIN_GREEN; + args->bin_green_filename = optarg; break; case 'h': if(args->mode & USE_STDOUT_MODES) { res = RES_BAD_ARG; - print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_HELP); + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_HELP); logger_print(args->logger, LOG_ERROR, "Option -%c cannot be used in conjunction with other dump options (%s).\n", (char)opt, buf); goto error; } - args->mode |= DUMP_HELP; + args->mode |= MODE_DUMP_HELP; break; case 'm': { @@ -579,7 +598,7 @@ parse_args (char)opt, mode_option(args->mode)); goto error; } - args->mode |= MEDIUM_COMPUTE; + args->mode |= MODE_MEDIUM_COMPUTE; ptr = strrchr(optarg, ','); if(ptr) { if(ptr != strchr(optarg, ',')) @@ -633,7 +652,7 @@ parse_args (char)opt, mode_option(args->mode)); goto error; } - args->mode |= PROBE_COMPUTE; + args->mode |= MODE_PROBE_COMPUTE; res = cstr_to_list_double(optarg, ',', args->probe, &len, 4); if(res != RES_OK || len < 3 @@ -656,7 +675,7 @@ parse_args (char)opt, mode_option(args->mode)); goto error; } - args->mode |= PROBE_COMPUTE_ON_INTERFACE; + args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE; res = cstr_to_list_double(optarg, ',', args->probe, &len, 4); if(res != RES_OK || len < 3 @@ -692,7 +711,7 @@ parse_args (char)opt, mode_option(args->mode)); goto error; } - args->mode |= IR_COMPUTE; + args->mode |= MODE_IR_COMPUTE; args->camera = optarg; break; @@ -709,13 +728,13 @@ parse_args } switch (opt) { case 's': - args->mode |= BOUNDARY_COMPUTE; + args->mode |= MODE_BOUNDARY_COMPUTE; break; case 'S': - args->mode |= MAP_COMPUTE; + args->mode |= MODE_MAP_COMPUTE; break; case 'F': - args->mode |= FLUX_BOUNDARY_COMPUTE; + args->mode |= MODE_FLUX_BOUNDARY_COMPUTE; break; } ptr = strrchr(optarg, ','); @@ -755,13 +774,13 @@ parse_args case 'v': if(args->mode & USE_STDOUT_MODES) { res = RES_BAD_ARG; - print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_VERSION); + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, MODE_DUMP_VERSION); logger_print(args->logger, LOG_ERROR, "Option -%c cannot be used in conjunction with other dump options (%s).\n", (char)opt, buf); goto error; } - args->mode |= DUMP_VERSION; + args->mode |= MODE_DUMP_VERSION; break; case 'V': @@ -806,7 +825,9 @@ parse_args goto error; } - if(args->mode & GREEN_MODE && !(args->mode & GREEN_COMPATIBLE_MODES)) { + if(args->mode & (MODE_BIN_GREEN | MODE_GREEN) + && !(args->mode & GREEN_COMPATIBLE_MODES)) + { print_multiple_modes(buf, sizeof(buf), GREEN_COMPATIBLE_MODES, 0); logger_print(args->logger, LOG_ERROR, "Option -g can only be used in conjunction with: %s\n", @@ -815,7 +836,7 @@ parse_args goto error; } - if(args->mode & IR_COMPUTE && n_used) { + if(args->mode & MODE_IR_COMPUTE && n_used) { logger_print(args->logger, LOG_ERROR, "The -n option has no effect in rendering mode;" " use rendering's SPP suboption instead.\n"); @@ -823,21 +844,42 @@ parse_args goto error; } - if(args->mode & DUMP_PATHS) { + if(args->mode & MODE_DUMP_PATHS) { if(!(args->mode & COMPUTE_MODES)) { res = RES_BAD_ARG; print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0); logger_print(args->logger, LOG_ERROR, "Option -%c can only be used in conjunction with an option" " that samples heat paths (%s).\n", - mode_option(DUMP_PATHS), buf); + mode_option(MODE_DUMP_PATHS), buf); + goto error; + } + if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) { + res = RES_BAD_ARG; + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used in conjunction with -%c nor -%c.\n", + mode_option(MODE_DUMP_PATHS), mode_option(MODE_GREEN) + , mode_option(MODE_BIN_GREEN)); goto error; } - if(args->mode & GREEN_MODE) { + } + + if(args->mode & MODE_EXTENDED_RESULTS) { + if(!(args->mode & COMPUTE_MODES)) { res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), EXT_COMPATIBLE_MODES, 0); logger_print(args->logger, LOG_ERROR, - "Option -%c cannot be used in conjunction with -%c.\n", - mode_option(DUMP_PATHS), mode_option(GREEN_MODE)); + "Option -%c can only be used in conjunction with an option" + " that computes a single Monte-Carlo (%s).\n", + mode_option(MODE_EXTENDED_RESULTS), buf); + goto error; + } + if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) { + res = RES_BAD_ARG; + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used in conjunction with -%c nor -%c.\n", + mode_option(MODE_EXTENDED_RESULTS), mode_option(MODE_GREEN) + , mode_option(MODE_BIN_GREEN)); goto error; } } @@ -968,7 +1010,7 @@ process_h desc->d.h_boundary.mat_id = (unsigned)sz; desc->type = type; - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "h boundary name"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "h boundary name"); ERR(str_set(&desc->d.h_boundary.name, tk)); if(find_description_by_name(stardis, &desc->d.h_boundary.name, NULL) != desc) @@ -979,7 +1021,7 @@ process_h goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "emissivity"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "emissivity"); res = cstr_to_double(tk, &desc->d.h_boundary.emissivity); if(res != RES_OK || desc->d.h_boundary.emissivity < 0 @@ -989,7 +1031,7 @@ process_h if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "specular fraction"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "specular fraction"); res = cstr_to_double(tk, &desc->d.h_boundary.specular_fraction); if(res != RES_OK || desc->d.h_boundary.specular_fraction < 0 @@ -1000,7 +1042,7 @@ process_h if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "hc"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc"); res = cstr_to_double(tk, &desc->d.h_boundary.hc); if(res != RES_OK || desc->d.h_boundary.hc < 0) @@ -1009,7 +1051,7 @@ process_h if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "temperature"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature"); res = cstr_to_double(tk, &desc->d.h_boundary.imposed_temperature); if(res != RES_OK || desc->d.h_boundary.imposed_temperature < 0) @@ -1051,7 +1093,7 @@ process_t desc->d.t_boundary.mat_id = (unsigned)sz; desc->type = type; - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "temperature boundary name"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature boundary name"); ERR(str_set(&desc->d.t_boundary.name, tk)); if(find_description_by_name(stardis, &desc->d.t_boundary.name, NULL) != desc) @@ -1062,7 +1104,7 @@ process_t goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "temperature"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature"); res = cstr_to_double(tk, &desc->d.t_boundary.imposed_temperature); if(res != RES_OK || desc->d.t_boundary.imposed_temperature < 0) @@ -1072,7 +1114,7 @@ process_t goto end; } if(type == DESC_BOUND_T_FOR_FLUID) { - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "emissivity"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "emissivity"); res = cstr_to_double(tk, &desc->d.t_boundary.emissivity); if(res != RES_OK || desc->d.t_boundary.emissivity < 0 @@ -1082,7 +1124,7 @@ process_t if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "specular fraction"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "specular fraction"); res = cstr_to_double(tk, &desc->d.t_boundary.specular_fraction); if(res != RES_OK || desc->d.t_boundary.specular_fraction < 0 @@ -1093,7 +1135,7 @@ process_t if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "hc"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc"); res = cstr_to_double(tk, &desc->d.t_boundary.hc); if(res != RES_OK || desc->d.t_boundary.hc < 0) @@ -1134,7 +1176,7 @@ process_flx desc->d.f_boundary.mat_id = (unsigned)sz; desc->type = DESC_BOUND_F_FOR_SOLID; - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "flux boundary name"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "flux boundary name"); ERR(str_set(&desc->d.f_boundary.name, tk)); if(find_description_by_name(stardis, &desc->d.f_boundary.name, NULL) != desc) @@ -1145,10 +1187,12 @@ process_flx goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "flux"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "flux"); res = cstr_to_double(tk, &desc->d.f_boundary.imposed_flux); - if(res != RES_OK) { - /* Flux can be < 0 */ + if(res != RES_OK + || desc->d.f_boundary.imposed_flux == SDIS_FLUX_NONE) { + /* Flux can be < 0 but not undefined */ + if(res == RES_OK) res = RES_BAD_ARG; logger_print(stardis->logger, LOG_ERROR, "Invalid flux: %s\n", tk); goto end; } @@ -1184,7 +1228,7 @@ process_sfc connection_id = (unsigned)sz; desc->type = DESC_SOLID_FLUID_CONNECT; - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "solid fluid connection name"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid fluid connection name"); ERR(str_set(&desc->d.sf_connect.name, tk)); if(find_description_by_name(stardis, &desc->d.sf_connect.name, NULL) != desc) @@ -1195,7 +1239,7 @@ process_sfc goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "emissivity"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "emissivity"); res = cstr_to_double(tk, &desc->d.sf_connect.emissivity); if(res != RES_OK || desc->d.sf_connect.emissivity < 0 @@ -1205,7 +1249,7 @@ process_sfc if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "specular fraction"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "specular fraction"); res = cstr_to_double(tk, &desc->d.sf_connect.specular_fraction); if(res != RES_OK || desc->d.sf_connect.specular_fraction < 0 @@ -1216,7 +1260,7 @@ process_sfc if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "hc"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "hc"); res = cstr_to_double(tk, &desc->d.sf_connect.hc); if(res != RES_OK || desc->d.sf_connect.hc < 0) @@ -1256,7 +1300,7 @@ process_solid desc->d.solid.solid_id = (unsigned)sz; desc->type = DESC_MAT_SOLID; - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "solid name"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid name"); ERR(str_set(&desc->d.solid.name, tk)); if(find_description_by_name(stardis, &desc->d.solid.name, NULL) != desc) @@ -1267,7 +1311,7 @@ process_solid goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "lambda"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "lambda"); res = cstr_to_double(tk, &desc->d.solid.lambda); if(res != RES_OK || desc->d.solid.lambda <= 0) @@ -1276,7 +1320,7 @@ process_solid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "rho"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "rho"); res = cstr_to_double(tk, &desc->d.solid.rho); if(res != RES_OK || desc->d.solid.rho <= 0) @@ -1285,7 +1329,7 @@ process_solid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "cp"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "cp"); res = cstr_to_double(tk, &desc->d.solid.cp); if(res != RES_OK || desc->d.solid.cp <= 0) @@ -1294,7 +1338,7 @@ process_solid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "delta"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "delta"); res = cstr_to_double(tk, &desc->d.solid.delta); if(res != RES_OK || desc->d.solid.delta <= 0) @@ -1303,7 +1347,7 @@ process_solid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "Tinit"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Tinit"); res = cstr_to_double(tk, &desc->d.solid.tinit); if(res != RES_OK || desc->d.solid.tinit < 0) @@ -1312,7 +1356,7 @@ process_solid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "volumic power"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "volumic power"); res = cstr_to_double(tk, &desc->d.solid.vpower); if(res != RES_OK) { /* VPower can be < 0 */ @@ -1350,7 +1394,7 @@ process_fluid desc->d.fluid.fluid_id = (unsigned)sz; desc->type = DESC_MAT_FLUID; - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "fluid name"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "fluid name"); ERR(str_set(&desc->d.fluid.name, tk)); if(find_description_by_name(stardis, &desc->d.fluid.name, NULL) != desc) @@ -1361,7 +1405,7 @@ process_fluid goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "rho"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "rho"); res = cstr_to_double(tk, &desc->d.fluid.rho); if(res != RES_OK || desc->d.fluid.rho <= 0) @@ -1370,7 +1414,7 @@ process_fluid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "cp"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "cp"); res = cstr_to_double(tk, &desc->d.fluid.cp); if(res != RES_OK || desc->d.fluid.cp <= 0) @@ -1379,7 +1423,7 @@ process_fluid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - CHK_TOK(strtok_r(NULL, " ", tok_ctx), "Tinit"); + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "Tinit"); res = cstr_to_double(tk, &desc->d.fluid.tinit); if(res != RES_OK || desc->d.fluid.tinit < 0) @@ -1419,11 +1463,11 @@ process_model_line struct str keep; char* tk = NULL, * tok_ctx = NULL; - ASSERT(line && stardis); + ASSERT(file_name && line && stardis); str_init(stardis->allocator, &keep); ERR(str_set(&keep, line)); - CHK_TOK(strtok_r(line, " ", &tok_ctx), "model line type"); + CHK_TOK(strtok_r(line, " \t", &tok_ctx), "model line type"); _strupr(tk); if(0 == strcmp(tk, "H_BOUNDARY_FOR_SOLID")) diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -43,35 +43,41 @@ struct stardis; enum stardis_mode { /* Ordered so that print_multiple_modes() prints in alphabetical order */ UNDEF_MODE = 0, - DUMP_PATHS = BIT(0), /* -D */ - DUMP_VTK = BIT(1), /* -d */ - FLUX_BOUNDARY_COMPUTE = BIT(2), /* -F */ - GREEN_MODE = BIT(3), /* -g */ - DUMP_HELP = BIT(4), /* -h */ - MEDIUM_COMPUTE = BIT(5), /* -m */ - PROBE_COMPUTE_ON_INTERFACE = BIT(6), /* -P */ - PROBE_COMPUTE = BIT(7), /* -p */ - IR_COMPUTE = BIT(8), /* -R */ - MAP_COMPUTE = BIT(9), /* -S */ - BOUNDARY_COMPUTE = BIT(10), /* -s */ - DUMP_VERSION = BIT(11), /* -v */ + MODE_DUMP_PATHS = BIT(0), /* -D */ + MODE_DUMP_VTK = BIT(1), /* -d */ + MODE_EXTENDED_RESULTS = BIT(2), /* -e */ + MODE_FLUX_BOUNDARY_COMPUTE = BIT(3), /* -F */ + MODE_BIN_GREEN = BIT(4), /* -G */ + MODE_GREEN = BIT(5), /* -g */ + MODE_DUMP_HELP = BIT(6), /* -h */ + MODE_MEDIUM_COMPUTE = BIT(7), /* -m */ + MODE_PROBE_COMPUTE_ON_INTERFACE = BIT(8), /* -P */ + MODE_PROBE_COMPUTE = BIT(9), /* -p */ + MODE_IR_COMPUTE = BIT(10), /* -R */ + MODE_MAP_COMPUTE = BIT(11), /* -S */ + MODE_BOUNDARY_COMPUTE = BIT(12), /* -s */ + MODE_VERBOSITY = BIT(13), /* -V */ + MODE_DUMP_VERSION = BIT(14), /* -v */ GREEN_COMPATIBLE_MODES - = PROBE_COMPUTE | PROBE_COMPUTE_ON_INTERFACE | MEDIUM_COMPUTE | BOUNDARY_COMPUTE, + = MODE_PROBE_COMPUTE | MODE_PROBE_COMPUTE_ON_INTERFACE | MODE_MEDIUM_COMPUTE + | MODE_BOUNDARY_COMPUTE, SURFACE_COMPUTE_MODES - = BOUNDARY_COMPUTE | FLUX_BOUNDARY_COMPUTE | MAP_COMPUTE, + = MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE | MODE_MAP_COMPUTE, - REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES | MEDIUM_COMPUTE, + EXT_COMPATIBLE_MODES = GREEN_COMPATIBLE_MODES | MODE_MEDIUM_COMPUTE, - COMPUTE_MODES = GREEN_COMPATIBLE_MODES | IR_COMPUTE | SURFACE_COMPUTE_MODES, + REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES | MODE_MEDIUM_COMPUTE, + + COMPUTE_MODES = GREEN_COMPATIBLE_MODES | MODE_IR_COMPUTE | SURFACE_COMPUTE_MODES, EXCLUSIVE_MODES = COMPUTE_MODES, - SHORT_EXIT_MODES = DUMP_HELP | DUMP_VERSION, + SHORT_EXIT_MODES = MODE_DUMP_HELP | MODE_DUMP_VERSION, USE_STDOUT_MODES - = DUMP_VTK | DUMP_HELP | DUMP_VERSION | IR_COMPUTE | GREEN_MODE + = MODE_DUMP_VTK | MODE_DUMP_HELP | MODE_DUMP_VERSION | MODE_IR_COMPUTE | MODE_GREEN }; STATIC_ASSERT(GREEN_COMPATIBLE_MODES == (COMPUTE_MODES & GREEN_COMPATIBLE_MODES), @@ -90,7 +96,8 @@ struct args { struct darray_str model_files; char* medium_name; char* solve_filename; - char* out_filename; + char* bin_green_filename; + char* paths_filename; size_t samples; unsigned nthreads; double probe[4]; @@ -147,7 +154,7 @@ release_args extern char mode_option - (const enum stardis_mode m); + (const int m); extern void print_multiple_modes diff --git a/src/stardis-version.h.in b/src/stardis-version.h.in @@ -16,9 +16,9 @@ #ifndef STARDIS_APP_VERSION_H #define STARDIS_APP_VERSION_H -#define STARDIS_APP_VERSION_MAJOR @VERSION_MAJOR@ -#define STARDIS_APP_VERSION_MINOR @VERSION_MINOR@ -#define STARDIS_APP_VERSION_PATCH @VERSION_PATCH@ +#define STARDIS_APP_VERSION_MAJOR @SDIS_VERSION_MAJOR@ +#define STARDIS_APP_VERSION_MINOR @SDIS_VERSION_MINOR@ +#define STARDIS_APP_VERSION_PATCH @SDIS_VERSION_PATCH@ #endif /* STARDIS_APP_VERSION_H */