commit 1fad7bc43ce62dd0b3db024032a01b2396080b4a
parent fdd2431a225245debc5df9119953058b3807f21f
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 20 Nov 2020 09:23:13 +0100
Merge branch 'release_0.1'
Diffstat:
15 files changed, 795 insertions(+), 354 deletions(-)
diff --git a/README.md b/README.md
@@ -26,7 +26,6 @@ variable the install directories of its dependencies.
### Version 0.1
-Postprocess a binary Green function file, as created by stardis. Main features are:
-
-- produce a summary of a Green function in HTML format,
-- apply a Green function to new settings and output the corresponding Monte-Carlo results.
-\ No newline at end of file
+- Compatible with stardis v0.5.0 binary Green function files.
+- Can produce a summary of a Green function in HTML format.
+- Can apply a Green function to new settings and output the corresponding Monte-Carlo results.
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -19,7 +19,7 @@ project(sgreen C)
set(GREEN_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src)
if(CMAKE_HOST_UNIX)
- set(GREEN_DOC "TROFF & HTML" CACHE STRING
+ set(GREEN_DOC "TROFF" CACHE STRING
"Type of documentation to generate and install.")
else()
set(GREEN_DOC "HTML" CACHE STRING
@@ -56,6 +56,7 @@ configure_file(${GREEN_SOURCE_DIR}/green-version.h.in
###############################################################################
find_package(RCMake 0.4 REQUIRED)
find_package(RSys 0.9 REQUIRED)
+find_package(OpenMP 2.0 REQUIRED)
if(MSVC)
find_package(MuslGetopt REQUIRED)
endif()
@@ -116,11 +117,13 @@ add_executable(sgreen
if(CMAKE_COMPILER_IS_GNUCC)
set(MATH_LIB m)
set_target_properties(sgreen PROPERTIES
- COMPILE_FLAGS "-std=c99"
+ COMPILE_FLAGS "-std=c99 ${OpenMP_C_FLAGS}"
+ LINK_FLAGS "${OpenMP_C_FLAGS}"
VERSION ${GREEN_VERSION})
elseif(MSVC)
set(GETOPT_LIB MuslGetopt)
set_target_properties(sgreen PROPERTIES
+ COMPILE_FLAGS ${OpenMP_C_FLAGS}
VERSION ${GREEN_VERSION})
endif()
diff --git a/cmake/doc/CMakeLists.txt b/cmake/doc/CMakeLists.txt
@@ -113,7 +113,7 @@ if(_html)
-bxhtml11
-dmanpage
--attribute themedir=${GREEN_DOC_DIR}
- --theme=green-man)
+ --theme=sgreen-man)
set(MAN_FILES)
set(MAN5_FILES)
@@ -143,7 +143,7 @@ if(_html)
endforeach()
add_custom_target(man-html ALL DEPENDS ${MAN_FILES})
- install(FILES ${MAN1_FILES} DESTINATION share/man/man1)
- install(FILES ${MAN5_FILES} DESTINATION share/man/man5)
+ install(FILES ${MAN1_FILES} DESTINATION share/doc/sgreen/html)
+ install(FILES ${MAN5_FILES} DESTINATION share/doc/sgreen/html)
endif()
diff --git a/doc/sgreen-input.5.txt b/doc/sgreen-input.5.txt
@@ -20,29 +20,26 @@ sgreen-input(5)
NAME
----
-green-input - settings description for green(1)
+sgreen-input - settings description for sgreen(1)
DESCRIPTION
-----------
-*green-input* is the format used by the *green*(1) program to describe a
+*sgreen-input* is the format used by the *sgreen*(1) program to describe
settings when applying a Green function. It relies on a line-based ad-hoc
syntax.
A settings file is composed of lines of text, each one describing the settings
-to apply for a Green function call. Each line contains *variable = value" pairs
+to apply for a Green function call. Each line contains *variable = value* pairs
in any number (at least one pair for a line to be meaningful). A list of all
legit variable names can be found in the Green function summary, as produced
-by option *-s*.
+by *sgreen*(1) option *-s*.
GRAMMAR
-------
-In what follows, some lines end in *\*. This is used as a convenience to
-continue a description next line. However, this trick cannot be used in
-actual description files and actual description lines must be kept single-line.
-Also, text appearing between quote marks has to be used verbatim in the input,
-except the quote characters. Finally, text introduced by the *#* character in
-descriptions, when not verbatim, is a comment and is not part of the
-description.
+In what follows, text appearing between quote marks has to be used verbatim in
+the input, except the quote characters. Also, text introduced by the *#*
+character in descriptions, when not verbatim, is a comment and is not part of
+the description.
[verse]
_______
@@ -68,36 +65,38 @@ _______
______________
-TRIANGLE SIDES
---------------
-Side descriptions in side specifiers rely on the following convention: we
-first consider the direct triangle's normal (right-hand rule), then we define
-the BACK side of a triangle to be the side this normal comes out from. That
-means that a closed set of triangles with normals pointing outside should be
-used with the FRONT side specifier to describe inside medium.
-
NAMES
-----
-Names, either file names, medium names or boundary names, are a sequence of
-one or ore ASCII characters, including numbers and special characters like
-*.* *_* *-* as one may consider using in standard file names, *without any
-spacing* either escaped or not. Two different description lines cannot use
-the same name.
+Except the name AMBIENT, that refers to the ambient radiative temperature and
+is always a legit name in settings, the list of names that can be used to form
+settings is the list of medium and boundary case-sensitive names defined in the
+*stardis-input*(5) files used when creating the Green function applied to the
+settings.
+
+UNITS
+-----
+Any physical quantity involved in settings files is expected in the
+International System of Units (metre, kelvin, Watt).
EXAMPLES
--------
-Define a solid named Cube with a h boundary. The cube geometry is read from
-the file cube.stl and the solid medium properties are lambda=0.1, rho=25, cp=2.
-The numerical parameter delta, that is used for solid conductive walks, is
-0.05. The initial temperature of the cube is 0°K and its volumic power is 0.
-The boundary properties are emisivity=0, specular-fraction=0, h=10 and
-external-temperature = 100°K.
+Apply a Green function with *AMBIENT* radiative temperature set to 0 K.
+.......
+AMBIENT = 0
+.......
+
+First apply a Green function with volumic power in medium *AL* set to 100 W/m^3^
+and temperature of the *Left* boundary set to 300 K. Then apply it with the
+same variables set to 120 and 350 respectively. Finally, apply it with the
+same variables set to 140 and 360 respectively and temperature of the *Right*
+boundary set to 380 K.
.......
-SOLID Cube 0.1 25 2 0.05 0 0 FRONT cube.stl
-H_BOUNDARY_FOR_SOLID HdT 0 0 10 100 cube.stl
+AL.VP=100 Left.T=300
+AL.VP=120 Left.T=350
+AL.VP=140 Left.T=360 Right.T=380
.......
SEE ALSO
--------
-*green*(1),
-*green-input*(5)
+*sgreen*(1),
+*sgreen-input*(5)
diff --git a/doc/sgreen-output.5.txt b/doc/sgreen-output.5.txt
@@ -20,24 +20,21 @@ sgreen-output(5)
NAME
----
-green-output - output format of green(1) results
+sgreen-output - output format of sgreen(1) results
DESCRIPTION
-----------
-*green-output* describes the output format of option *-a* of the *green*(1)
-program.
-
The type of the data that are generated depends on the options used when
-*green*(1) is invoked. When invoked with the option *-a*, *green*(1) outputs
+*sgreen*(1) is invoked. When invoked with option *-a*, *sgreen*(1) outputs
Monte-Carlo results, either in extended or compact format, whether option *-e*
-is used or not. Also, when invoked whith option *-s* *green*(1) outputs an
+is used or not. Also, when invoked whith option *-s* *sgreen*(1) outputs an
HTML file contening a summary of the Green function used.
GRAMMAR
-------
As Green summaries comply with HTML format, that can be found in HTML
-specification documents [1], they will not be further described. Only
-Monte-Carlo results are described in this section.
+specification documents [1], they will not be further described thereafter.
+Only Monte-Carlo results grammar is described in this section.
In what follows, text appearing between quote marks is a verbatim part of the
output, except the quote characters, and text introduced by the *#* character
@@ -67,7 +64,7 @@ _______
HTML SUMMARY
------------
-When using option *-s*, *green*(1) creates a summary of the Green function in
+When using option *-s*, *sgreen*(1) creates a summary of the Green function in
HTML format. This document contains the following sections:
* List of variables
@@ -98,5 +95,5 @@ NOTES
SEE ALSO
--------
-*green*(1),
-*green-input*(5)
+*sgreen*(1),
+*sgreen-input*(5)
diff --git a/doc/sgreen.1.txt.in b/doc/sgreen.1.txt.in
@@ -30,17 +30,17 @@ SYNOPSIS
DESCRIPTION
-----------
*sgreen* is a post processing tool that can be used on *stardis*(1) Green
-functions, as contained in binary green files. The main functionality is to
-apply different boundary conditions to a system once solved by *stardis*(1)
-in Green mode (*-G* option of *stardis*(1)). The provided file should comply
-with the *sgreen-input*(5) format, that is also the output format of
-*stardis*(1) in binary Green mode (see *stardis-output*(5)).
+functions (a.k.a propagators), as contained in binary files. The main
+functionality is to apply different boundary conditions to a system once solved
+by *stardis*(1) in Green mode (*-G* option of *stardis*(1)). The provided file
+should comply with the *sgreen-input*(5) format, that is also the
+*stardis-output*(1) format in binary Green mode.
-Using this Green function (a.k.a propagator) approach, when possible, produces
-the very same results as a full Monte-Carlo computation, but only requires a
-fraction of the computation time.
+Using this Green function approach, when possible, produces the very same
+results as a full Monte-Carlo computation, but only requires a fraction of the
+computation time.
-The propagator is of great value for thermicist engineers as it gives some
+The propagator is of great value to thermal engineers as it gives some
crucial information to analyse heat transfers in the system. It helps engineers
answer questions like _"Where from does the heat come at this location?"_.
Propagators seamlessly agregate all the provided geometrical and physical
@@ -53,7 +53,7 @@ simulated system.
OPTIONS
-------
*-a* _FILE_NAME_::
- Apply a Green function using the variable settings read in a file. Can only
+ Apply a Green function using the variable settings read from a file. Can only
be applied in conjunction with option *-g*.
*-e*::
@@ -101,7 +101,7 @@ Create a summary of the *heatsink.green* Green function and write it in the
*heatsink_settings.txt* and output the corresponding Monte-Carlo results to
stdout in compact format.
- $ sgreen -g heatsink.green -s heatsink_green.html -a heatsink_green.html
+ $ sgreen -g heatsink.green -s heatsink_green.html -a heatsink_settings.txt
COPYRIGHT
---------
diff --git a/src/green-args.c b/src/green-args.c
@@ -56,7 +56,7 @@ init_args
args->command_filename = NULL;
args->green_filename = NULL;
args->info_filename = NULL;
- args->nthreads = DEFAULT_NTHREADS;
+ args->nthreads = (unsigned)omp_get_num_procs();
args->verbose = GREEN_DEFAULT_VERBOSE_LEVEL;
}
diff --git a/src/green-args.h b/src/green-args.h
@@ -22,8 +22,6 @@ struct logger;
struct mem_allocator;
struct args;
-#define DEFAULT_NTHREADS UINT_MAX
-
struct args {
struct logger* logger;
struct mem_allocator* allocator;
diff --git a/src/green-compute.c b/src/green-compute.c
@@ -13,14 +13,72 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#define _POSIX_C_SOURCE 200112L /* strtok_r */
+
+#include "green-compute.h"
#include "green-types.h"
#include <rsys/str.h>
#include <rsys/cstr.h>
#include <rsys/logger.h>
#include <rsys/text_reader.h>
+#include <rsys/dynamic_array.h>
+#include <rsys/mem_allocator.h>
#include <math.h>
+#include <string.h>
+#include <ctype.h>
+#include <omp.h>
+
+enum log_record_type {
+ RECORD_INVALID = BIT(0),
+ RECORD_UNKNOWN = BIT(1),
+ RECORD_UNUSED = BIT(2),
+ RECORD_DEFAULT = BIT(3),
+ RECORD_TYPES_UNDEF__ = BIT(4)
+};
+
+struct log_record {
+ enum log_record_type type;
+ int line_num, var_num;
+ struct str name;
+ const char* keep_line;
+ double default_value;
+ struct mem_allocator* allocator;
+};
+
+static FINLINE res_T
+log_record_create
+ (struct mem_allocator* allocator,
+ const enum log_record_type type,
+ struct log_record** out_record)
+{
+ struct log_record* record;
+ ASSERT(allocator && out_record);
+ record = MEM_ALLOC(allocator, sizeof(*record));
+ if(!record) return RES_MEM_ERR;
+ record->type = type;
+ record->line_num = -1;
+ record->var_num = -1;
+ record->keep_line = NULL;
+ record->default_value = INF;
+ str_init(allocator, &record->name);
+ record->allocator = allocator;
+ *out_record = record;
+ return RES_OK;
+}
+
+static FINLINE void
+log_record_release
+ (struct log_record* data)
+{
+ str_release(&data->name);
+ MEM_RM(data->allocator, data);
+}
+
+#define DARRAY_NAME logs
+#define DARRAY_DATA struct log_record*
+#include <rsys/dynamic_array.h>
void
check_green_table_variables_use
@@ -32,51 +90,54 @@ check_green_table_variables_use
ASSERT(green);
ASSERT(!green->references_checked); /* Fix double call in caller */
- /* Clear previous data */
- FOR_EACH(i, 0, 1 + green->counts.desc_count) {
- green->table[i].end_references_count = 0;
- green->table[i].other_references_weight = 0;
- }
FOR_EACH(i, 0, green->counts.ok_count) {
const struct sample* sample = green->samples + i;
unsigned id = sample->header.end_id;
- enum description_type type = green->descriptions[id].type;
- ASSERT(!DESC_IS_H(type));
- ASSERT(id <= green->counts.desc_count); /* Ambient ID is desc_count */
- green->table[id].end_references_count++;
+ /* Ambient ID is desc_count */
+ ASSERT(id <= green->counts.desc_count);
+ ASSERT(id == green->counts.desc_count
+ || DESC_HOLDS_T(green->descriptions[id].type));
+ if(sample->header.at_initial)
+ green->table[id].initial_T_weight++;
+ else
+ green->table[id].imposed_T_weight++;
FOR_EACH(j, 0, sample->header.pw_count) {
const double w = sample->pw_weights[j];
id = sample->pw_ids[j];
ASSERT(id < green->counts.desc_count);
- type = green->descriptions[id].type;
- ASSERT(DESC_IS_MEDIUM(type));
- green->table[id].other_references_weight += w;
+ ASSERT(DESC_IS_MEDIUM(green->descriptions[id].type));
+ green->table[id].other_weight += w;
}
FOR_EACH(j, 0, sample->header.fx_count) {
const double w = sample->fx_weights[j];
id = sample->fx_ids[j];
ASSERT(id < green->counts.desc_count);
- type = green->descriptions[id].type;
- ASSERT(DESC_IS_F(type));
- green->table[id].other_references_weight += w;
+ ASSERT(DESC_IS_F(green->descriptions[id].type));
+ green->table[id].other_weight += w;
}
}
green->references_checked = 1;
}
-#define INSERT(Name, Val, Used) { \
+#define INSERT(Elt, Field) { \
struct variable_data vd___; \
- vd___.value = (Val); vd___.used = (Used) != 0;\
- if(!vd___.used) green->unused_variables = 1; \
- if(htable_variable_ptr_find(&green->variable_ptrs, &(Name))) \
- FATAL("Name already known"); \
- ERR(htable_variable_ptr_set(&green->variable_ptrs, &(Name), &vd___)); \
+ vd___.idx = ((Elt) * sizeof(struct applied_settings_elt) \
+ + offsetof(struct applied_settings_elt, Field ## _value)) / sizeof(double); \
+ vd___.used = (green->table[Elt].Field ## _weight != 0); \
+ vd___.unknown = green->table[Elt].Field ## _unknown; \
+ if(vd___.unknown) green->unknown_variables = 1; \
+ else if(!vd___.used) green->unused_variables = 1; \
+ if(htable_variable_ptr_find(&green->variable_ptrs, \
+ &(green->table[Elt].Field ## _name))) \
+ FATAL("Name already known"); /* Should have been detected by stardis */ \
+ ERR(htable_variable_ptr_set(&green->variable_ptrs, \
+ &(green->table[Elt].Field ## _name), &vd___)); \
} (void)0
#define MK_VAR(Str) \
for(;;) { \
- int n = snprintf(buf, bufsz, (Str), str_cget(name));\
+ size_t n = (size_t)snprintf(buf, bufsz, (Str), str_cget(name));\
if(n < bufsz) break; \
buf = MEM_REALLOC(green->allocator, buf, n + 1); \
bufsz = n + 1; \
@@ -106,64 +167,83 @@ build_green_table
init_table_elt(green->allocator, green->table + i);
check_green_table_variables_use(green);
+
FOR_EACH(i, 0, green->counts.desc_count) {
desc = green->descriptions + i;
name = get_description_name(desc);
if(DESC_IS_T(desc->type)) {
MK_VAR("%s.T");
- str_set(&green->table[i].end_name, buf);
- green->table[i].end_value = desc->d.t_boundary.imposed_temperature;
- green->table[i].end_defined = 1;
- INSERT(green->table[i].end_name, green->table[i].end_value,
- green->table[i].end_references_count);
+ ERR(str_set(&green->table[i].imposed_T_name, buf));
+ ASSERT(desc->d.t_boundary.imposed_temperature >= 0);
+ green->table[i].imposed_T_value = desc->d.t_boundary.imposed_temperature;
+ green->table[i].imposed_T_defined = 1;
+ INSERT(i, imposed_T);
}
else if(DESC_IS_H(desc->type)) {
MK_VAR("%s.T");
- str_set(&green->table[i].end_name, buf);
- green->table[i].end_value = desc->d.h_boundary.imposed_temperature;
- green->table[i].end_defined = 1;
- INSERT(green->table[i].end_name, green->table[i].end_value,
- green->table[i].end_references_count);
+ ERR(str_set(&green->table[i].imposed_T_name, buf));
+ ASSERT(desc->d.h_boundary.imposed_temperature >= 0);
+ green->table[i].imposed_T_value = desc->d.h_boundary.imposed_temperature;
+ green->table[i].imposed_T_defined = 1;
+ INSERT(i, imposed_T);
}
else if(DESC_IS_F(desc->type)) {
MK_VAR("%s.F");
- str_set(&green->table[i].other_name, buf);
+ ERR(str_set(&green->table[i].other_name, buf));
green->table[i].other_value = desc->d.f_boundary.imposed_flux;
green->table[i].other_defined = 1;
- INSERT(green->table[i].other_name, green->table[i].other_value,
- green->table[i].other_references_weight);
+ INSERT(i, other);
}
else if(DESC_IS_MEDIUM(desc->type)) {
- MK_VAR("%s.T");
- str_set(&green->table[i].end_name, buf);
- green->table[i].end_defined = 1;
- INSERT(green->table[i].end_name, green->table[i].end_value,
- green->table[i].end_references_count);
if(desc->type == DESC_MAT_SOLID) {
- green->table[i].end_value = desc->d.solid.imposed_temperature;
+ MK_VAR("%s.T");
+ ERR(str_set(&green->table[i].imposed_T_name, buf));
+ green->table[i].imposed_T_value = desc->d.solid.imposed_temperature;
+ green->table[i].imposed_T_defined = 1;
+ if(green->table[i].imposed_T_value < 0)
+ green->table[i].imposed_T_unknown = 1;
+ INSERT(i, imposed_T);
+ MK_VAR("%s.Tinit");
+ ERR(str_set(&green->table[i].initial_T_name, buf));
+ green->table[i].initial_T_value = desc->d.solid.tinit;
+ green->table[i].initial_T_defined = 1;
+ if(green->table[i].initial_T_value < 0)
+ green->table[i].initial_T_unknown = 1;
+ INSERT(i, initial_T);
MK_VAR("%s.VP");
- str_set(&green->table[i].other_name, buf);
+ ERR(str_set(&green->table[i].other_name, buf));
green->table[i].other_value = desc->d.solid.vpower;
green->table[i].other_defined = 1;
- INSERT(green->table[i].other_name, green->table[i].other_value,
- green->table[i].other_references_weight);
- } else { /* No VP for fluids yet */
- green->table[i].end_value = desc->d.fluid.imposed_temperature;
+ INSERT(i, other);
+ } else {
+ MK_VAR("%s.T");
+ ERR(str_set(&green->table[i].imposed_T_name, buf));
+ green->table[i].imposed_T_value = desc->d.fluid.imposed_temperature;
+ green->table[i].imposed_T_defined = 1;
+ if(green->table[i].imposed_T_value < 0)
+ green->table[i].imposed_T_unknown = 1;
+ INSERT(i, imposed_T);
+ MK_VAR("%s.Tinit");
+ ERR(str_set(&green->table[i].initial_T_name, buf));
+ green->table[i].initial_T_value = desc->d.fluid.tinit;
+ green->table[i].initial_T_defined = 1;
+ if(green->table[i].initial_T_value < 0)
+ green->table[i].initial_T_unknown = 1;
+ INSERT(i, initial_T);
}
}
else if(desc->type == DESC_SOLID_FLUID_CONNECT) {
/* No variables here */
}
- else FATAL("Invalid desc type.");
+ else FATAL("Invalid desc type."); /* Should have been detected by stardis */
}
/* Ambient ID is desc_count */
ambient_id = green->counts.desc_count;
desc = green->descriptions + ambient_id;
- str_set(&green->table[ambient_id].end_name, "AMBIENT");
- green->table[ambient_id].end_value = green->ambient_temp;
- green->table[ambient_id].end_defined = 1;
- INSERT(green->table[ambient_id].end_name, green->table[ambient_id].end_value,
- green->table[ambient_id].end_references_count);
+ ERR(str_set(&green->table[ambient_id].imposed_T_name, "AMBIENT"));
+ green->table[ambient_id].imposed_T_value = green->ambient_temp;
+ green->table[ambient_id].imposed_T_defined = 1;
+ INSERT(ambient_id, imposed_T);
end:
MEM_RM(green->allocator, buf);
@@ -175,8 +255,22 @@ error:
#undef INSERT
static void
+applied_settings_set_defaults
+ (const struct green* green,
+ struct applied_settings_elt* settings)
+{
+ unsigned i;
+ FOR_EACH(i, 0, 1 + green->counts.desc_count) {
+ settings[i].imposed_T_value = green->table[i].imposed_T_value;
+ settings[i].initial_T_value = green->table[i].initial_T_value;
+ settings[i].other_value = green->table[i].other_value;
+ }
+}
+
+static void
green_compute_1
(const struct green* green,
+ const struct applied_settings_elt* settings,
double* E,
double* STD)
{
@@ -189,29 +283,36 @@ green_compute_1
FOR_EACH(i, 0, green->counts.ok_count) {
const struct sample* sample = green->samples + i;
unsigned id = sample->header.end_id;
- enum description_type type = green->descriptions[id].type;
- ASSERT(DESC_IS_T(type) || DESC_IS_H(type));
ASSERT(id <= green->counts.desc_count); /* Ambient ID is desc_count */
- ASSERT(green->table[id].end_defined);
- Ti = green->table[id].end_value;
+ ASSERT(id == green->counts.desc_count
+ || DESC_IS_T(green->descriptions[id].type)
+ || DESC_IS_H(green->descriptions[id].type)
+ || DESC_IS_MEDIUM(green->descriptions[id].type));
+ if(sample->header.at_initial) {
+ ASSERT(green->table[id].initial_T_defined
+ && !green->table[id].initial_T_unknown);
+ Ti = settings[id].initial_T_value;
+ } else {
+ ASSERT(green->table[id].imposed_T_defined
+ && !green->table[id].imposed_T_unknown);
+ Ti = settings[id].imposed_T_value;
+ }
FOR_EACH(j, 0, sample->header.pw_count) {
const double w = sample->pw_weights[j];
id = sample->pw_ids[j];
ASSERT(id < green->counts.desc_count);
- type = green->descriptions[id].type;
- ASSERT(DESC_IS_MEDIUM(type));
- ASSERT(green->table[id].other_defined);
- Ti += w * green->table[id].other_value;
+ ASSERT(DESC_IS_MEDIUM(green->descriptions[id].type));
+ ASSERT(green->table[id].other_defined && !green->table[id].other_unknown);
+ Ti += w * settings[id].other_value;
}
FOR_EACH(j, 0, sample->header.fx_count) {
const double w = sample->fx_weights[j];
id = sample->fx_ids[j];
ASSERT(id < green->counts.desc_count);
- type = green->descriptions[id].type;
- ASSERT(DESC_IS_F(type));
- ASSERT(green->table[id].other_defined);
- Ti += w * green->table[id].other_value;
+ ASSERT(DESC_IS_F(green->descriptions[id].type));
+ ASSERT(green->table[id].other_defined && !green->table[id].other_unknown);
+ Ti += w * settings[id].other_value;
}
T += Ti;
T2 += Ti * Ti;
@@ -221,128 +322,268 @@ green_compute_1
*STD = (V > 0) ? sqrt(V / (double)green->counts.ok_count) : 0;
}
+static int
+cmp_records
+ (void const* r1, void const* r2)
+{
+ ASSERT(r1 && r2);
+ const struct log_record* record1 = *(struct log_record**)r1;
+ const struct log_record* record2 = *(struct log_record**)r2;
+ if(record1->line_num == record2->line_num)
+ return record1->var_num - record2->var_num;
+ return record1->line_num - record2->line_num;
+}
+
+static void
+do_log
+ (const char* file_name,
+ struct green* green,
+ struct darray_logs* logs)
+{
+ size_t i;
+ int prev_line_num = INT_MAX;
+ enum log_type log_type = LOG_WARNING;
+ ASSERT(file_name && green && logs);
+
+ if(darray_logs_size_get(logs) == 0) return;
+
+ /* Sort records by #line */
+ qsort(darray_logs_data_get(logs),
+ darray_logs_size_get(logs),
+ sizeof(*darray_logs_data_get(logs)),
+ cmp_records);
+
+ FOR_EACH(i, 0, darray_logs_size_get(logs)) {
+ struct log_record* record = darray_logs_data_get(logs)[i];
+ if(record->type & (RECORD_INVALID | RECORD_UNKNOWN)) {
+ log_type = LOG_ERROR;
+ break;
+ }
+ }
+ logger_print(green->logger, log_type, "In file '%s':\n", file_name);
+ FOR_EACH(i, 0, darray_logs_size_get(logs)) {
+ struct log_record* record = darray_logs_data_get(logs)[i];
+ switch (record->type) {
+ case RECORD_INVALID:
+ if(record->line_num != prev_line_num) {
+ logger_print(green->logger, LOG_ERROR,
+ "In line #%d: '%s':\n",
+ record->line_num, record->keep_line);
+ logger_print(green->logger, LOG_ERROR,
+ (str_is_empty(&record->name)
+ ? "Invalid data (missing name)\n" : "Invalid data (missing value)\n"));
+ } else
+ logger_print(green->logger, LOG_ERROR,
+ (str_is_empty(&record->name)
+ ? "Invalid data (missing name)\n" : "Invalid data (missing value)\n"));
+ break;
+ case RECORD_UNKNOWN:
+ if(record->line_num != prev_line_num) {
+ logger_print(green->logger, LOG_ERROR,
+ "In line #%d: '%s':\n",
+ record->line_num, record->keep_line);
+ logger_print(green->logger, LOG_ERROR,
+ "Unknown variable name: '%s'\n",
+ str_cget(&record->name));
+ } else
+ logger_print(green->logger, LOG_ERROR,
+ "\tUnknown variable name: '%s'\n",
+ str_cget(&record->name));
+ break;
+ case RECORD_UNUSED:
+ if(record->line_num != prev_line_num) {
+ logger_print(green->logger, LOG_WARNING,
+ "In line #%d: '%s':\n",
+ record->line_num, record->keep_line);
+ logger_print(green->logger, LOG_WARNING,
+ "Attempt to change unused variable '%s'.\n",
+ str_cget(&record->name));
+ } else
+ logger_print(green->logger, LOG_WARNING,
+ "\tAttempt to change unused variable '%s'.\n",
+ str_cget(&record->name));
+ break;
+ case RECORD_DEFAULT:
+ if(record->line_num != prev_line_num) {
+ logger_print(green->logger, LOG_WARNING,
+ "In line #%d: '%s':\n",
+ record->line_num, record->keep_line);
+ logger_print(green->logger, LOG_WARNING,
+ "Change variable '%s' to its default value %g.\n",
+ str_cget(&record->name), record->default_value);
+ } else
+ logger_print(green->logger, LOG_WARNING,
+ "Change variable '%s' to its default value %g.\n",
+ str_cget(&record->name), record->default_value);
+ break;
+ default:
+ FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n");
+ }
+ prev_line_num = record->line_num;
+ }
+}
+
static res_T
parse_line
(const char* file_name,
- char* line,
- struct green* green)
+ const int idx,
+ struct green* green,
+ struct applied_settings_elt* settings,
+ struct darray_logs* logs)
{
res_T res = RES_OK;
- struct str keep;
- int name_count = 0;
+ int name_count;
struct str name;
- char* tk = NULL, * tok_ctx = NULL;
+ char* tk_name = NULL;
+ char* tk_value = NULL;
+ char* tok_ctx = NULL;
+ const struct str* keep_line;
+ struct str line;
+ ASSERT(file_name && green && settings && logs && idx >= 0);
- ASSERT(file_name && line && green);
-
- str_init(green->allocator, &keep);
+ keep_line = darray_str_cdata_get(&green->settings) + idx;
+ str_init(green->allocator, &line);
str_init(green->allocator, &name);
- ERR(str_set(&keep, line));
+ ERR(str_set(&line, str_cget(keep_line)));
/* At least one name=value, no name without value */
- for(;;) {
+ for(name_count = 0; ; name_count++) {
struct variable_data* vd;
- tk = strtok_r(name_count ? NULL : line, "=", &tok_ctx);
- if(tk) {
+ struct log_record* record = NULL;
+ double prev;
+
+ if(res != RES_OK) goto error;
+
+ tk_name = strtok_r(name_count ? NULL : str_get(&line), "=", &tok_ctx);
+ if(tk_name) {
char* c;
- c = tk + strlen(tk) - 1;
- while(c >= tk && isspace(*tk)) tk++;
- while(c >= tk && isspace(*c)) {
+ c = tk_name + strlen(tk_name) - 1;
+ while(c >= tk_name && isspace(*tk_name)) tk_name++;
+ while(c >= tk_name && isspace(*c)) {
*c = '\0';
c--;
}
- if(c < tk) tk = NULL;
+ if(c < tk_name) tk_name = NULL;
}
- if(!tk) {
- if(name_count == 0) {
- /* At least 1 name */
- logger_print(green->logger, LOG_ERROR,
- "Invalid data (missing name)\n");
- res = RES_BAD_ARG;
- goto error;
- }
- else break;
+ tk_value = strtok_r(NULL, " \t", &tok_ctx);
+ if((tk_name == NULL) != (tk_value == NULL)) {
+ /* '<name> = <value>' or '' */
+ ERR(log_record_create(green->allocator, RECORD_INVALID, &record));
+ if(tk_name) { ERR(str_set(&record->name, tk_name)); }
+ res = RES_BAD_ARG;
+ goto push_record;
}
- str_set(&name, tk);
- CHK_TOK(strtok_r(NULL, " \t", &tok_ctx), "value");
+ if(!tk_name) break; /* End of data */
+ /* Check name validity */
+ ERR(str_set(&name, tk_name));
vd = htable_variable_ptr_find(&green->variable_ptrs, &name);
- if(!vd || !vd->used) {
- /* Name should exist */
- if(!vd) {
- logger_print(green->logger, LOG_ERROR,
- "Invalid data (unknown name: '%s')",
- str_cget(&name));
- res = RES_BAD_ARG;
- goto error;
- }
- logger_print(green->logger, LOG_WARNING,
- "Attempt to change unused variable '%s'\n", str_cget(&name));
- logger_print(green->logger, LOG_WARNING, "In file '%s':\n", file_name);
- logger_print(green->logger, LOG_WARNING, "%s\n", str_cget(&keep));
+ if(!vd) {
+ ERR(log_record_create(green->allocator, RECORD_UNKNOWN, &record));
+ ERR(str_set(&record->name, tk_name));
+ res = RES_BAD_ARG;
+ goto push_record;
+ }
+ if(!vd->used) {
+ ERR(log_record_create(green->allocator, RECORD_UNUSED, &record));
+ ERR(str_set(&record->name, tk_name));
+ goto push_record;
+ }
+ /* Variable exists and is used in Green function: check if really changed */
+ prev = ((double*)settings)[vd->idx];
+ ERR(cstr_to_double(tk_value, ((double*)settings) + vd->idx));
+ if(prev == ((double*)settings)[vd->idx]) {
+ ERR(log_record_create(green->allocator, RECORD_DEFAULT, &record));
+ ERR(str_set(&record->name, tk_name));
+ record->default_value = prev;
+ goto push_record;
+ }
+ continue;
+push_record:
+ #pragma omp critical
+ {
+ res_T tmp_res;
+ ASSERT(record && record->type != RECORD_TYPES_UNDEF__);
+ record->line_num = idx;
+ record->var_num = name_count;
+ record->keep_line = str_cget(keep_line);
+ tmp_res = darray_logs_push_back(logs, &record);
+ if(res == RES_OK) res = tmp_res;
}
- ERR(cstr_to_double(tk, &vd->value));
- name_count++;
}
end:
- str_release(&keep);
+ str_release(&line);
str_release(&name);
return res;
error:
- logger_print(green->logger, LOG_ERROR,
- "Invalid line in file '%s':\n", file_name);
- logger_print(green->logger, LOG_ERROR, "%s\n", str_cget(&keep));
goto end;
}
res_T
green_compute
(struct green* green,
- const char* in_name,
- const int mode,
- FILE* out_stream)
+ const char* in_name)
{
res_T res = RES_OK;
- struct txtrdr* txtrdr = NULL;
- FILE* stream = NULL;
- struct str keep;
- double E, STD;
+ size_t sz, n;
+ int i;
+ struct applied_settings_elt** settings = NULL;
+ struct darray_logs logs;
ASSERT(green && in_name);
+ sz = darray_str_size_get(&green->settings);
+ ASSERT(sz < INT_MAX);
- str_init(green->allocator, &keep);
- stream = fopen(in_name, "r");
- if(!stream) {
- logger_print(green->logger, LOG_ERROR,
- "Cannot open model file '%s'\n",
- in_name);
- res = RES_IO_ERR;
+ settings = MEM_CALLOC(green->allocator, green->nthreads, sizeof(*settings));
+ if(settings == NULL) {
+ res = RES_MEM_ERR;
goto error;
}
- txtrdr_stream(green->allocator, stream, in_name, '#', &txtrdr);
- for(;;) {
- char* line;
- ERR(txtrdr_read_line(txtrdr));
- line = txtrdr_get_line(txtrdr);
- if(!line) break;
- if(mode & MODE_EXTENTED_RESULTS) str_set(&keep, line);
+ darray_logs_init(green->allocator, &logs);
+
+ omp_set_num_threads((int)green->nthreads);
+ #pragma omp parallel for schedule(static)
+ for(i = 0; i < (int)sz; i++) {
+ struct result* result = darray_result_data_get(&green->results) + i;
+ res_T tmp_res = RES_OK;
+ int t = omp_get_thread_num();
+
+ if(res != RES_OK) continue;
+
+ if(settings[t] == NULL) {
+ /* desc_count + 1 for AMBIENT */
+ settings[t] = MEM_CALLOC(green->allocator, 1 + green->counts.desc_count,
+ sizeof(**settings));
+ if(settings[t] == NULL) {
+ res = RES_MEM_ERR;
+ continue;
+ }
+ }
+
/* Apply settings */
- ERR(parse_line(in_name, line, green));
+ applied_settings_set_defaults(green, settings[t]);
+ tmp_res = parse_line(in_name, i, green, settings[t], &logs);
+ if(tmp_res != RES_OK) {
+ res = tmp_res;
+ continue;
+ }
/* Compute */
- green_compute_1(green, &E, &STD);
- /* Print results */
- if(mode & MODE_EXTENTED_RESULTS)
- fprintf(out_stream, "%g +/- %g ; %s\n", E, STD, str_cget(&keep));
- else fprintf(out_stream, "%g %g\n", E, STD);
- }
- txtrdr_ref_put(txtrdr);
- txtrdr = NULL;
+ green_compute_1(green, settings[t], &result->E, &result->STD);
+ } /* Implicit barrier */
+ if(res != RES_OK) goto error;
exit:
- str_release(&keep);
- if(stream) fclose(stream);
- if(txtrdr) txtrdr_ref_put(txtrdr);
+ do_log(in_name, green, &logs);
+ if(settings) {
+ FOR_EACH(n, 0, green->nthreads) MEM_RM(green->allocator, settings[n]);
+ MEM_RM(green->allocator, settings);
+ }
+ FOR_EACH(n, 0, darray_logs_size_get(&logs)) {
+ struct log_record* record = darray_logs_data_get(&logs)[n];
+ log_record_release(record);
+ }
+ darray_logs_release(&logs);
return res;
error:
goto exit;
diff --git a/src/green-compute.h b/src/green-compute.h
@@ -33,8 +33,6 @@ build_green_table
res_T
green_compute
(struct green* green,
- const char* in_name,
- const int mode,
- FILE* out_stream);
+ const char* in_name);
#endif /* GREEN_COMPUTE_H */
\ No newline at end of file
diff --git a/src/green-input.c b/src/green-input.c
@@ -20,6 +20,7 @@
#include <rsys/str.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
+#include <rsys/text_reader.h>
#include <stdlib.h>
@@ -53,7 +54,7 @@ error:
}
res_T
-read_green
+read_green_function
(struct green* green,
FILE* stream)
{
@@ -106,6 +107,9 @@ read_green
FR(&green->ambient_temp, 1);
FR(&green->ref_temp, 1);
+ /* Read time range */
+ FR(&green->time_range, 2);
+
/* Read samples*/
green->samples = MEM_CALLOC(green->allocator, green->counts.ok_count,
sizeof(*green->samples));
@@ -125,3 +129,46 @@ end:
error:
goto end;
}
+
+res_T
+green_read_settings
+ (struct green* green,
+ const char* in_name)
+{
+ res_T res = RES_OK;
+ struct txtrdr* txtrdr = NULL;
+ FILE* stream = NULL;
+
+ ASSERT(green && in_name);
+
+ stream = fopen(in_name, "r");
+ if(!stream) {
+ logger_print(green->logger, LOG_ERROR,
+ "Cannot open model file '%s'\n",
+ in_name);
+ res = RES_IO_ERR;
+ goto error;
+ }
+ txtrdr_stream(green->allocator, stream, in_name, '#', &txtrdr);
+ for(;;) {
+ char* line;
+ size_t sz;
+ ERR(txtrdr_read_line(txtrdr));
+ line = txtrdr_get_line(txtrdr);
+ if(!line) break;
+ sz = darray_str_size_get(&green->settings);
+ ERR(darray_str_resize(&green->settings, 1 + sz));
+ ERR(str_set(darray_str_data_get(&green->settings) + sz, line));
+ }
+ ERR(darray_result_resize(&green->results,
+ darray_str_size_get(&green->settings)));
+ txtrdr_ref_put(txtrdr);
+ txtrdr = NULL;
+
+exit:
+ if(stream) fclose(stream);
+ if(txtrdr) txtrdr_ref_put(txtrdr);
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/green-main.c b/src/green-main.c
@@ -23,6 +23,7 @@
#include <rsys/logger.h>
#include <stdlib.h>
+#include <omp.h>
int
main
@@ -31,8 +32,7 @@ main
{
int err = EXIT_SUCCESS;
res_T res = RES_OK;
- int logger_initialized = 0, allocator_initialized = 0,
- green_initialized = 0;
+ int logger_initialized = 0, green_initialized = 0, allocator_initialized = 0;
struct mem_allocator allocator;
struct logger logger;
struct green green;
@@ -69,20 +69,33 @@ main
if(args.verbose < 3)
logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL);
- if(args.green_filename) {
- stream = fopen(args.green_filename, "rb");
- if(!stream) {
- logger_print(&logger, LOG_ERROR,
- "Cannot open model file '%s'\n", args.green_filename);
- res = RES_IO_ERR;
- goto error;
+ green_init(&allocator, &logger, args.nthreads, &green);
+ green_initialized = 1;
+ #pragma omp parallel sections num_threads(args.nthreads)
+ {
+ /* If there are some settings to apply read the 2 files at the same time*/
+ #pragma omp section
+ if(args.green_filename) {
+ stream = fopen(args.green_filename, "rb");
+ if(!stream) {
+ logger_print(&logger, LOG_ERROR,
+ "Cannot open model file '%s'\n", args.green_filename);
+ res = RES_IO_ERR;
+ } else {
+ res_T tmp_err;
+ tmp_err = read_green_function(&green, stream);
+ fclose(stream);
+ if(tmp_err != RES_OK) res = tmp_err;
+ }
}
- green_init(&allocator, &logger, &green);
- green_initialized = 1;
- ERR(read_green(&green, stream));
- fclose(stream); stream = NULL;
- }
-
+ #pragma omp section
+ if(args.mode & MODE_APPLY_GREEN) {
+ res_T tmp_res;
+ tmp_res = green_read_settings(&green, args.command_filename);
+ if(tmp_res != RES_OK) res = tmp_res;
+ }
+ } /* Implicit barrier */
+ if(res != RES_OK) goto error;
if(args.mode & MODE_HTML_SUMMARY) {
ASSERT(args.info_filename);
stream = fopen(args.info_filename, "w");
@@ -97,12 +110,24 @@ main
}
if(args.mode & MODE_APPLY_GREEN) {
- ERR(green_compute(&green, args.command_filename, args.mode, stdout));
+ ERR(green_compute(&green, args.command_filename));
+ green_print_result(&green, args.mode, stdout);
}
exit:
if(green_initialized) green_release(&green);
+ if(logger_initialized) logger_release(&logger);
if(stream) fclose(stream);
+ 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;
diff --git a/src/green-output.c b/src/green-output.c
@@ -17,22 +17,30 @@
#include <rsys/str.h>
#include <rsys/mem_allocator.h>
+#include "green-output.h"
#include "green-types.h"
#include "green-version.h"
+#include <stdio.h>
+
#define CELL(T,Val) \
fprintf(stream, " <td>%" #T "</td>\n", (Val))
-#define MCELL(T,Used,Name,Val) { \
- if(Used) \
- fprintf(stream, " <td><u><b>%s = %" #T "</b></u></td>\n", (Name), (Val)); \
- else fprintf(stream, " <td>%s = %" #T "</td>\n", (Name), (Val)); \
+#define VAR_CELL(Elt, Field) { \
+ const char* name___ = str_cget(&(green->table[Elt].Field ## _name)); \
+ if((green->table[Elt]). Field ## _unknown) { \
+ fprintf(stream, " <td>%s = Unknown</td>\n", name___); \
+ } else if(green->table[Elt].Field ## _defined \
+ && green->table[Elt].Field ## _weight > 0) \
+ { \
+ fprintf(stream, " <td><u><b>%s = %g</b></u></td>\n", \
+ name___, green->table[Elt].Field ## _value); \
+ } else { \
+ fprintf(stream, " <td>%s = %g</td>\n", \
+ name___, green->table[Elt].Field ## _value); \
+ } \
} (void)0
-#define MCELLif(T,Used,Name,Val) \
- if((Val) != 0) { MCELL(T,(Used),(Name),(Val)); } \
- else { CELL(T,(Val)); } (void)0
-
void
print_version
(FILE* stream)
@@ -65,19 +73,21 @@ short_help
name);
fprintf(stream, "\n -a <FILE>\n");
- fprintf(stream, " Apply a Green function using the variable settings read from file.\n");
+ fprintf(stream, " Apply a Green function using the variable settings "
+ "read from a file.\n");
fprintf(stream, "\n -e\n");
fprintf(stream, " Use extended format to output Monte-Carlo results.\n");
fprintf(stream, "\n -g <FILE>\n");
- fprintf(stream, " Read a Green function from file.\n");
+ fprintf(stream, " Read a Green function from a file.\n");
fprintf(stream, "\n -h\n");
fprintf(stream, " Print this help and exit.\n");
fprintf(stream, "\n -s <FILE>\n");
- fprintf(stream, " Create a summary of a Green function and write it to file.\n");
+ fprintf(stream, " Create a summary of a Green function and write it to "
+ "a file.\n");
fprintf(stream, "\n -t NUM_OF_THREADS\n");
fprintf(stream, " Hint on the number of threads.\n");
@@ -90,6 +100,26 @@ short_help
}
void
+green_print_result
+ (struct green* green,
+ const int mode,
+ FILE* out_stream)
+{
+ size_t i, sz;
+
+ ASSERT(green && out_stream);
+ sz = darray_str_size_get(&green->settings);
+
+ for(i = 0; i < sz; i++) {
+ struct result* result = darray_result_data_get(&green->results) + i;
+ const char* line = str_cget(darray_str_data_get(&green->settings) + i);
+ if(mode & MODE_EXTENTED_RESULTS)
+ fprintf(out_stream, "%g +/- %g ; %s\n", result->E, result->STD, line);
+ else fprintf(out_stream, "%g %g\n", result->E, result->STD);
+ }
+}
+
+void
dump_green_info
(struct green* green,
FILE* stream)
@@ -127,7 +157,7 @@ dump_green_info
fprintf(stream, "<h2>List of variables</h2>\n");
- fprintf(stream, "<h3>Variable used in the Green function</h3>\n");
+ fprintf(stream, "<h3>Variables used in the Green function</h3>\n");
fprintf(stream, "<p>These variable names are used in the following formula. "
"Using the syntax NAME=value in a settings file, their values are "
@@ -137,34 +167,83 @@ dump_green_info
fst = 1;
FOR_EACH(i, 0, green->counts.desc_count + 1) {
struct table_elt* elt = green->table + i;
- if(elt->end_defined && elt->end_references_count) {
- if(!fst) fprintf(stream, ", "); fst = 0;
- fprintf(stream, "%s", str_cget(&elt->end_name));
+ if(elt->imposed_T_defined && elt->imposed_T_weight > 0) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->imposed_T_name));
+ }
+ if(elt->initial_T_defined && elt->initial_T_weight > 0) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->initial_T_name));
}
- if(elt->other_defined && elt->other_references_weight) {
- if(!fst) fprintf(stream, ", "); fst = 0;
+ if(elt->other_defined && elt->other_weight) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
fprintf(stream, "%s", str_cget(&elt->other_name));
}
}
if(green->unused_variables) {
fprintf(stream,
- "<h3>Variable not used in the Green function</h3>\n");
+ "<h3>Unused variables in the Green function</h3>\n");
fprintf(stream, "<p>These variable names are not used in the following "
- "formula. Changing their values in a settings file has no effect on "
- "the applied Green function results. They are listed NAME = value "
- "in the tables below.</p>\n");
+ "formula, just because they where not sampled. As a consequence, "
+ "changing their values in a settings file has no effect on the applied "
+ "Green function results. They are listed NAME = value in the tables "
+ "below.</p>\n");
+
+ fst = 1;
+ FOR_EACH(i, 0, green->counts.desc_count + 1) {
+ struct table_elt* elt = green->table + i;
+ if(elt->imposed_T_defined
+ && !elt->imposed_T_unknown && elt->imposed_T_weight == 0) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->imposed_T_name));
+ }
+ if(elt->initial_T_defined
+ && !elt->initial_T_unknown && elt->initial_T_weight == 0) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->initial_T_name));
+ }
+ if(elt->other_defined
+ && !elt->other_unknown && !elt->other_weight) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->other_name));
+ }
+ }
+ }
+
+ if(green->unknown_variables) {
+ fprintf(stream,
+ "<h3>Unknown variables in the Green function</h3>\n");
+
+ fprintf(stream, "<p>These names are not true variable names because their "
+ "values where defined as <i>unknown</i> in the system, meaning they "
+ "required to be solved. Attempting to change their values in a settings "
+ "file is an error. They are listed NAME = Unknown in the tables below."
+ "</p>\n");
fst = 1;
FOR_EACH(i, 0, green->counts.desc_count + 1) {
struct table_elt* elt = green->table + i;
- if(elt->end_defined && !elt->end_references_count) {
- if(!fst) fprintf(stream, ", "); fst = 0;
- fprintf(stream, "%s", str_cget(&elt->end_name));
+ if(elt->imposed_T_unknown) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->imposed_T_name));
+ }
+ if(elt->initial_T_unknown) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
+ fprintf(stream, "%s", str_cget(&elt->initial_T_name));
}
- if(elt->other_defined && !elt->other_references_weight) {
- if(!fst) fprintf(stream, ", "); fst = 0;
+ if(elt->other_defined && !elt->other_weight) {
+ if(!fst) fprintf(stream, ", ");
+ fst = 0;
fprintf(stream, "%s", str_cget(&elt->other_name));
}
}
@@ -172,47 +251,57 @@ dump_green_info
fprintf(stream, "<h2>Formula of the Monte-Carlo estimate</h2>\n");
- fprintf(stream, "<p>The Monte-Carlo estimate of the Green function of the "
- "system is as follows:</p>\n");
+ if(green->time_range[0] == green->time_range[1])
+ fprintf(stream, "<p>The Monte-Carlo estimate of the Green function of the "
+ "system at t=%g is as follows:</p>\n",
+ green->time_range[0]);
+ else
+ fprintf(stream, "<p>The Monte-Carlo estimate of the Green function of the "
+ "system with t in [%g %g] is as follows:</p>\n",
+ SPLIT2(green->time_range));
/* Print result */
fst = 1;
FOR_EACH(i, 0, 1 + green->counts.desc_count) {
- if(green->table[i].end_references_count) {
+ if(green->table[i].imposed_T_weight > 0) {
+ double k;
+ CHK(green->table[i].imposed_T_defined
+ && green->table[i].imposed_T_value >= 0);
+ if(fst) fprintf(stream, "<p>E[T] = ");
+ else fprintf(stream, " + ");
+ fst = 0;
+ k = (double)green->table[i].imposed_T_weight
+ / (double)green->counts.ok_count;
+ t += k * green->table[i].imposed_T_value;
+ fprintf(stream, "%g * <b>%s</b>",
+ k, str_cget(&green->table[i].imposed_T_name));
+ }
+ if(green->table[i].initial_T_weight > 0) {
double k;
- ASSERT(green->table[i].end_defined);
+ CHK(green->table[i].initial_T_defined
+ && green->table[i].initial_T_value >= 0);
if(fst) fprintf(stream, "<p>E[T] = ");
else fprintf(stream, " + ");
fst = 0;
- k = (double)green->table[i].end_references_count
+ k = (double)green->table[i].initial_T_weight
/ (double)green->counts.ok_count;
- t += k * green->table[i].end_value;
- fprintf(stream, "%g * <b>%s</b>", k, str_cget(&green->table[i].end_name));
+ t += k * green->table[i].initial_T_value;
+ fprintf(stream, "%g * <b>%s</b>",
+ k, str_cget(&green->table[i].initial_T_name));
}
}
ASSERT(!fst);
FOR_EACH(i, 0, green->counts.desc_count) {
- if(green->table[i].other_references_weight) {
+ if(green->table[i].other_weight) {
double k;
- ASSERT(green->table[i].other_defined);
- k = (double)green->table[i].other_references_weight
+ CHK(green->table[i].other_defined);
+ k = (double)green->table[i].other_weight
/ (double)green->counts.ok_count;
t += k * green->table[i].other_value;
- fprintf(stream, " + %g * <b>%s</b>", k, str_cget(&green->table[i].other_name));
+ fprintf(stream, " + %g * <b>%s</b>",
+ k, str_cget(&green->table[i].other_name));
}
}
- if(green->table[green->counts.desc_count].end_references_count) {
- double ww = 0, k;
- /* Some paths end here */
- if(fst) fprintf(stream, "<p>E(T) = ");
- else fprintf(stream, " + ");
- fst = 0;
- ww = green->ambient_temp;
- k = (double)green->table[green->counts.desc_count].end_references_count
- / (double)green->counts.ok_count;
- t += ww * k;
- fprintf(stream, "%g * <b>Ambient</b>", k);
- }
fprintf(stream, " = %g</p>", t);
/* Counts table */
@@ -254,7 +343,8 @@ dump_green_info
fprintf(stream, " <th>Rho</th>\n");
fprintf(stream, " <th>Cp</th>\n");
fprintf(stream, " <th>Volumic Power</th>\n");
- fprintf(stream, " <th>Temperature</th>\n");
+ fprintf(stream, " <th>Imposed temperature</th>\n");
+ fprintf(stream, " <th>Initial temperature</th>\n");
fprintf(stream, "</tr>\n");
}
sl = &desc->d.solid;
@@ -263,15 +353,9 @@ dump_green_info
CELL(g, sl->lambda);
CELL(g, sl->rho);
CELL(g, sl->cp);
- ASSERT(green->table[i].other_defined);
- MCELLif(g, green->table[i].other_references_weight,
- str_cget(&green->table[i].other_name), sl->vpower);
- if(sl->imposed_temperature >= 0) {
- ASSERT(green->table[i].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[i].end_name), sl->imposed_temperature);
- }
- else CELL(s, "Unknown");
+ VAR_CELL(i, other);
+ VAR_CELL(i, imposed_T);
+ VAR_CELL(i, initial_T);
fprintf(stream, "</tr>\n");
local_count++;
}
@@ -290,7 +374,8 @@ dump_green_info
fprintf(stream, " <th>Name</th>\n");
fprintf(stream, " <th>Rho</th>\n");
fprintf(stream, " <th>Cp</th>\n");
- fprintf(stream, " <th>Temperature</th>\n");
+ fprintf(stream, " <th>Imposed temperature</th>\n");
+ fprintf(stream, " <th>Initial temperature</th>\n");
fprintf(stream, "</tr>\n");
}
fl = &desc->d.fluid;
@@ -298,12 +383,8 @@ dump_green_info
CELL(s, str_cget(&fl->name));
CELL(g, fl->rho);
CELL(g, fl->cp);
- if(fl->imposed_temperature >= 0) {
- ASSERT(green->table[i].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[i].end_name), fl->imposed_temperature);
- }
- else CELL(s, "Unknown");
+ VAR_CELL(i, imposed_T);
+ VAR_CELL(i, initial_T);
fprintf(stream, "</tr>\n");
local_count++;
}
@@ -326,9 +407,8 @@ dump_green_info
bd = &desc->d.t_boundary;
fprintf(stream, "<tr>\n");
CELL(s, str_cget(&bd->name));
- ASSERT(green->table[i].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[i].end_name), bd->imposed_temperature);
+ ASSERT(green->table[i].imposed_T_defined);
+ VAR_CELL(i, imposed_T);
fprintf(stream, "</tr>\n");
local_count++;
}
@@ -353,9 +433,8 @@ dump_green_info
bd = &desc->d.t_boundary;
fprintf(stream, "<tr>\n");
CELL(s, str_cget(&bd->name));
- ASSERT(green->table[i].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[i].end_name), bd->imposed_temperature);
+ ASSERT(green->table[i].imposed_T_defined);
+ VAR_CELL(i, imposed_T);
CELL(g, bd->emissivity);
CELL(g, bd->specular_fraction);
CELL(g, bd->hc);
@@ -387,9 +466,8 @@ dump_green_info
CELL(g, bd->emissivity);
CELL(g, bd->specular_fraction);
CELL(g, bd->hc);
- ASSERT(green->table[i].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[i].end_name), bd->imposed_temperature);
+ ASSERT(green->table[i].imposed_T_defined);
+ VAR_CELL(i, imposed_T);
fprintf(stream, "</tr>\n");
local_count++;
}
@@ -417,10 +495,8 @@ dump_green_info
CELL(g, bd->emissivity);
CELL(g, bd->specular_fraction);
CELL(g, bd->hc);
- ASSERT(green->table[i].end_defined);
- ASSERT(green->table[i].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[i].end_name), bd->imposed_temperature);
+ ASSERT(green->table[i].imposed_T_defined);
+ VAR_CELL(i, imposed_T);
fprintf(stream, "</tr>\n");
local_count++;
}
@@ -444,8 +520,7 @@ dump_green_info
fprintf(stream, "<tr>\n");
CELL(s, str_cget(&bd->name));
ASSERT(green->table[i].other_defined);
- MCELL(g, green->table[i].other_references_weight,
- str_cget(&green->table[i].other_name), bd->imposed_flux);
+ VAR_CELL(i, other);
fprintf(stream, "</tr>\n");
local_count++;
}
@@ -460,10 +535,8 @@ dump_green_info
fprintf(stream, "</tr>\n");
fprintf(stream, "<tr>\n");
CELL(s, "Ambient");
- ASSERT(green->table[green->counts.desc_count].end_defined);
- MCELL(g, green->table[i].end_references_count,
- str_cget(&green->table[green->counts.desc_count].end_name),
- green->ambient_temp);
+ ASSERT(green->table[green->counts.desc_count].imposed_T_defined);
+ VAR_CELL(green->counts.desc_count, imposed_T);
fprintf(stream, "</tr>\n");
fprintf(stream, "<tr>\n");
CELL(s, "Linearization");
@@ -477,5 +550,4 @@ dump_green_info
}
#undef CELL
-#undef MCELL
-#undef MCELLif
-\ No newline at end of file
+#undef VAR_CELL
+\ No newline at end of file
diff --git a/src/green-output.h b/src/green-output.h
@@ -20,6 +20,8 @@
#include <stdio.h>
+struct green;
+
void
print_version
(FILE* stream);
@@ -30,6 +32,12 @@ short_help
FILE* stream);
void
+green_print_result
+ (struct green* green,
+ const int mode,
+ FILE* out_stream);
+
+void
dump_green_info
(struct green* green,
FILE* stream);
diff --git a/src/green-types.h b/src/green-types.h
@@ -19,8 +19,12 @@
#include <rsys/str.h>
#include <rsys/mem_allocator.h>
#include <rsys/hash_table.h>
+#include <rsys/dynamic_array.h>
+#include <rsys/dynamic_array_char.h>
+#include <rsys/dynamic_array_str.h>
#include <string.h>
+#include <omp.h>
/* Utility macros */
#define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0
@@ -118,8 +122,8 @@ enum green_mode {
*/
struct sample_header {
unsigned end_id;
- unsigned pw_count;
- unsigned fx_count;
+ unsigned pw_count, fx_count;
+ char at_initial;
};
struct sample {
@@ -130,7 +134,7 @@ struct sample {
double* fx_weights;
};
-static res_T
+static INLINE res_T
alloc_sample_buffers
(struct mem_allocator* alloc,
struct sample* sample)
@@ -176,17 +180,22 @@ release_sample
}
/*
- * Table used to compute green
+ * Types used to compute green
*/
-struct table_elt {
- struct str end_name;
- struct str other_name;
- double end_value;
+struct applied_settings_elt {
+ double imposed_T_value, initial_T_value;
double other_value;
- int end_defined, other_defined;
- int end_references_count;
- double other_references_weight;
+};
+
+/* other is used both for power and flux, as no description can have both */
+struct table_elt {
+ struct str imposed_T_name, initial_T_name, other_name;
+ double imposed_T_value, initial_T_value, other_value;
+ int imposed_T_defined, initial_T_defined, other_defined;
+ int imposed_T_unknown, initial_T_unknown, other_unknown;
+ unsigned imposed_T_weight, initial_T_weight;
+ double other_weight;
};
static INLINE void
@@ -195,14 +204,21 @@ init_table_elt
struct table_elt* elt)
{
ASSERT(alloc && elt);
- str_init(alloc, &elt->end_name);
+ str_init(alloc, &elt->imposed_T_name);
+ str_init(alloc, &elt->initial_T_name);
str_init(alloc, &elt->other_name);
- elt->end_value = 0;
+ elt->imposed_T_value = 0;
+ elt->initial_T_value = 0;
elt->other_value = 0;
- elt->end_defined = 0;
+ elt->imposed_T_defined = 0;
+ elt->initial_T_defined = 0;
elt->other_defined = 0;
- elt->end_references_count = 0;
- elt->other_references_weight = 0;
+ elt->imposed_T_unknown = 0;
+ elt->initial_T_unknown = 0;
+ elt->other_unknown = 0;
+ elt->imposed_T_weight = 0;
+ elt->initial_T_weight = 0;
+ elt->other_weight = 0;
}
static INLINE void
@@ -210,13 +226,15 @@ release_table_elt
(struct table_elt* elt)
{
ASSERT(elt);
- str_release(&elt->end_name);
+ str_release(&elt->imposed_T_name);
+ str_release(&elt->initial_T_name);
str_release(&elt->other_name);
}
struct variable_data {
- double value;
+ size_t idx;
int used;
+ int unknown;
};
#define HTABLE_NAME variable_ptr
@@ -230,6 +248,14 @@ struct variable_data {
#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
#include <rsys/hash_table.h>
+struct result {
+ double E, STD;
+};
+
+#define DARRAY_NAME result
+#define DARRAY_DATA struct result
+#include <rsys/dynamic_array.h>
+
/*
* Main type to store binary file content
*/
@@ -240,16 +266,21 @@ struct green {
char* names_pool;
struct description* descriptions;
double ambient_temp, ref_temp;
+ double time_range[2];
struct table_elt* table;
struct sample* samples;
- int references_checked, unused_variables;
+ int references_checked, unused_variables, unknown_variables;
+ unsigned nthreads;
struct htable_variable_ptr variable_ptrs;
+ struct darray_str settings;
+ struct darray_result results;
};
static INLINE void
green_init
(struct mem_allocator* alloc,
struct logger* logger,
+ const unsigned nthreads,
struct green* green)
{
ASSERT(alloc && green);
@@ -264,7 +295,11 @@ green_init
green->ref_temp = 0;
green->references_checked = 0;
green->unused_variables = 0;
+ green->unknown_variables = 0;
+ green->nthreads = MMIN(nthreads, (unsigned)omp_get_num_procs());
htable_variable_ptr_init(alloc, &green->variable_ptrs);
+ darray_str_init(alloc, &green->settings);
+ darray_result_init(alloc, &green->results);
}
static INLINE void
@@ -279,18 +314,25 @@ green_release
FOR_EACH(i, 0, green->counts.ok_count)
release_sample(green->allocator, green->samples + i);
FOR_EACH(i, 0, 1 + green->counts.desc_count)
- release_table_elt(&green->table[i]);
+ if(&green->table[i]) release_table_elt(&green->table[i]);
MEM_RM(green->allocator, green->table);
MEM_RM(green->allocator, green->samples);
green->allocator = NULL;
htable_variable_ptr_release(&green->variable_ptrs);
+ darray_str_release(&green->settings);
+ darray_result_release(&green->results);
}
res_T
-read_green
+read_green_function
(struct green* green,
FILE* stream);
+res_T
+green_read_settings
+ (struct green* green,
+ const char* in_name);
+
/*
* Different types of descriptions read from the binary file
*/
@@ -315,50 +357,62 @@ enum description_type {
((D) == DESC_BOUND_T_FOR_SOLID || (D) == DESC_BOUND_T_FOR_FLUID)
#define DESC_IS_F(D) \
((D) == DESC_BOUND_F_FOR_SOLID)
+#define DESC_IS_SF(D) \
+ ((D) == DESC_SOLID_FLUID_CONNECT)
+#define DESC_HOLDS_T(D) \
+ (DESC_IS_MEDIUM(D) || DESC_IS_H(D) || DESC_IS_T(D))
struct mat_fluid {
struct str name;
- unsigned fluid_id;
- double rho;
- double cp;
+ double rho; /* Volumic mass */
+ double cp; /* Calorific capacity */
double tinit;
double imposed_temperature;
+ double t0; /* End time of tinit */
+ int is_outside; /* the fluid is used for a boundary */
+ int is_green; /* green computation nothing to do with fluid itself) */
+ unsigned desc_id; /* id of the boundary; meaningful if is_outside */
+ unsigned fluid_id;
};
struct mat_solid {
struct str name;
- unsigned solid_id;
- double lambda;
- double rho;
- double cp;
- double delta;
- double tinit;
- double imposed_temperature;
+ double lambda; /* Conductivity */
+ double rho; /* Volumic mass */
+ double cp; /* Calorific capacity */
+ double delta; /* Numerical parameter */
+ double tinit; /* Initial temperature */
+ double imposed_temperature; /* allow to impose a T; -1 if unset */
double vpower;
+ double t0; /* End time of tinit */
+ int is_outside; /* the fluid is used for a boundary */
+ int is_green; /* green computation nothing to do with fluid itself) */
+ unsigned desc_id; /* id of the boundary; meaningful if is_outside */
+ unsigned solid_id;
};
struct h_boundary {
struct str name;
- unsigned mat_id;
double emissivity;
double specular_fraction;
double hc;
double imposed_temperature;
+ unsigned mat_id;
};
struct t_boundary {
struct str name;
- unsigned mat_id;
double emissivity;
double specular_fraction;
double hc;
double imposed_temperature;
+ unsigned mat_id;
};
struct f_boundary {
struct str name;
- unsigned mat_id;
double imposed_flux;
+ unsigned mat_id;
};
struct solid_fluid_connect {
@@ -366,6 +420,7 @@ struct solid_fluid_connect {
double emissivity;
double specular_fraction;
double hc;
+ unsigned connection_id;
};
struct description {