Skip to content

Commit 6d308ad

Browse files
committed
READ_DATA
1 parent c58b194 commit 6d308ad

File tree

12 files changed

+130
-1
lines changed

12 files changed

+130
-1
lines changed

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Current (under development)
22

33
* ...
4+
* keyword `READ_DATA` to read variables and vectors from files
45
* `PROBLEM` can define `MESH` in a single line without an explicit `READ_MESH` instruction
56
* Neo-hookean material model
67
* MMS verification for mechanical with both sdef & ldef

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ TESTS_general = \
4747
tests/petsc_options.sh \
4848
tests/point-kinetics.sh \
4949
tests/print.sh \
50+
tests/read.sh \
5051
tests/solve.sh \
5152
tests/trig.sh \
5253
tests/transient-mesh.sh \

src/Makefile-base.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ feenox_SOURCES = \
5050
./parser/parser.h \
5151
./parser/auxiliary.c \
5252
./io/file.c \
53+
./io/read.c \
5354
./io/print.c \
5455
./io/printf.c \
5556
./math/alias.c \

src/feenox.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ typedef struct printf_t printf_t;
329329
typedef struct print_function_t print_function_t;
330330
typedef struct multidim_range_t multidim_range_t;
331331
typedef struct print_vector_t print_vector_t;
332+
typedef struct read_data_t read_data_t;
333+
332334

333335
typedef struct sort_vector_t sort_vector_t;
334336
typedef struct phase_object_t phase_object_t;
@@ -830,6 +832,15 @@ struct printf_t {
830832
printf_t *next;
831833
};
832834

835+
struct read_data_t {
836+
file_t *file;
837+
// TODO: several things mixed together, this is where I miss C++'s STL
838+
var_t *variable;
839+
vector_t *vector;
840+
841+
read_data_t *next;
842+
};
843+
833844
struct multidim_range_t {
834845
int dimensions;
835846

@@ -2088,6 +2099,10 @@ FILE *feenox_fopen(const char *filepath, const char *mode);
20882099
extern int feenox_instruction_file_open(void *arg);
20892100
extern int feenox_instruction_file_close(void *arg);
20902101

2102+
// read.c
2103+
extern int feenox_instruction_read_data(void *arg);
2104+
2105+
20912106
// abort.c
20922107
extern int feenox_instruction_abort(void *arg);
20932108

src/io/read.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*------------ -------------- -------- --- ----- --- -- - -
2+
* feenox read data from files
3+
*
4+
* Copyright (C) 2025 Jeremy Theler
5+
*
6+
* This file is part of feenox.
7+
*
8+
* feenox is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* FeenoX is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with feenox. If not, see <http://www.gnu.org/licenses/>.
20+
*------------------- ------------ ---- -------- -- - - -
21+
*/
22+
#include "feenox.h"
23+
24+
int feenox_instruction_read_data(void *arg) {
25+
26+
read_data_t *read_data = (read_data_t *)arg;
27+
if (read_data->file->pointer == NULL) {
28+
feenox_call(feenox_instruction_file_open(read_data->file));
29+
}
30+
31+
if (read_data->variable != NULL) {
32+
fscanf(read_data->file->pointer, "%lf", read_data->variable->value);
33+
} else {
34+
double xi = 0;
35+
for (int i = 0; i < read_data->vector->size; i++) {
36+
fscanf(read_data->file->pointer, "%lf", &xi);
37+
gsl_vector_set(read_data->vector->value, i, xi);
38+
}
39+
}
40+
41+
return FEENOX_OK;
42+
}

src/math/function.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,19 @@ double feenox_function_eval(function_t *this, const double *const_x) {
513513

514514
// check if we need to initialize
515515
if (this->initialized == 0) {
516+
// there is a pathological case where a BC or a property depends on T(x,y,z)
517+
// but T(x,y,z) itself is not ready before SOLVE_PROBLEM so we have to look
518+
// for the initial condition T_0(x,y,z)...
519+
if (this->algebraic_expression.items == NULL && this->mesh == NULL && this->vector_argument == NULL) {
520+
function_t *initial = feenox_get_function_ptr("T_0");
521+
if (initial != NULL) {
522+
return feenox_function_eval(initial, x);
523+
} else {
524+
feenox_push_error_message("function '%s' is not ready to be used and no initial condition '%s_0' found", this->name, this->name);
525+
return FEENOX_ERROR;
526+
}
527+
}
528+
516529
if (feenox_function_init(this) != FEENOX_OK) {
517530
feenox_runtime_error();
518531
}

src/parser/parser.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,13 @@ int feenox_parse_line(void) {
191191
} else if (strcasecmp(token, "FUNCTION") == 0) {
192192
feenox_call(feenox_parse_function());
193193
return FEENOX_OK;
194-
194+
195+
///kw+READ_DATA+desc Read data from a file (or standard output, or pipe, or queue, etc.).
196+
///kw+PRINT+usage READ_DATA
197+
} else if (strcasecmp(token, "READ_DATA") == 0) {
198+
feenox_call(feenox_parse_read_data());
199+
return FEENOX_OK;
200+
195201
///kw+PRINT+desc Write plain-text and/or formatted data to the standard output or into an output file.
196202
///kw+PRINT+usage PRINT
197203
} else if (strcasecmp(token, "PRINT") == 0) {
@@ -1568,6 +1574,34 @@ int feenox_parse_open_close(const char *what) {
15681574
return FEENOX_OK;
15691575
}
15701576

1577+
int feenox_parse_read_data(void) {
1578+
1579+
read_data_t *read_data = NULL;
1580+
feenox_check_alloc(read_data = calloc(1, sizeof(read_data_t)));
1581+
1582+
char *token = NULL;
1583+
while ((token = feenox_get_next_token(NULL)) != NULL) {
1584+
///kw+READ_DATA+usage [ FILE { <file_path> | <file_id> } ]
1585+
if (strcasecmp(token, "FILE") == 0 || strcasecmp(token, "FILE_PATH") == 0) {
1586+
feenox_call(feenox_parser_file(&read_data->file));
1587+
if (read_data->file->mode == NULL) {
1588+
feenox_check_alloc(read_data->file->mode = strdup("r"));
1589+
}
1590+
} else {
1591+
if ((read_data->variable = feenox_get_variable_ptr(token)) == NULL) {
1592+
if ((read_data->vector = feenox_get_vector_ptr(token)) == NULL) {
1593+
feenox_push_error_message("unknown symbol '%s'", token);
1594+
return FEENOX_ERROR;
1595+
}
1596+
}
1597+
1598+
}
1599+
}
1600+
1601+
feenox_call(feenox_add_instruction(feenox_instruction_read_data, read_data));
1602+
1603+
return FEENOX_OK;
1604+
}
15711605
int feenox_parse_print(void) {
15721606

15731607
// I don't expect anybody to want to use this PRINT instruction through the API

src/parser/parser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ extern int feenox_parse_sort_vector(void);
100100
extern int feenox_parse_file(char *mode);
101101
extern int feenox_parse_open_close(const char *what);
102102

103+
extern int feenox_parse_read_data(void);
104+
103105
extern int feenox_parse_print(void);
104106
extern int feenox_parse_printf(int all_ranks);
105107
extern int feenox_parse_print_function(void);

src/pdes/thermal/bc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ int feenox_problem_bc_parse_thermal(bc_data_t *bc_data, const char *lhs, char *r
6464

6565
// for non-linear problems it is important to have a good initial guess
6666
// if the user did not give us one in T_guess we average all the temperatures from the BCs
67+
// but we have to be sure that the BC expression does not involve a function coming from somewhere else
6768
if (bc_data->type_phys == BC_TYPE_THERMAL_TEMPERATURE || bc_data->type_phys == BC_TYPE_THERMAL_CONVECTION_TEMPERATURE ) {
6869
thermal.guessed_initial_guess += feenox_expression_eval(&bc_data->expr);
6970
thermal.n_bc_temperatures++;

tests/onetwothree.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
123 1 2 3

0 commit comments

Comments
 (0)