diff --git a/src/cats/actions/action_population_grid_output.c b/src/cats/actions/action_population_grid_output.c
index 97c931fef5beaca85745fae598e16b0138afaf11..e961712148c5460ecee60789c04eccedc124ae59 100644
--- a/src/cats/actions/action_population_grid_output.c
+++ b/src/cats/actions/action_population_grid_output.c
@@ -40,7 +40,7 @@ enum action_status action_save_adults(struct cats_grid *grid, struct cats_config
         assert(grid != NULL);
         if (conf->command_line_options.lambda_test) {
                 if (grid->param.parametrization == PARAM_HYBRID) {
-                        printf("POP,%d,%d,%f,%LF,%Lf,%d\n", conf->time.year_current, get_adult_population(grid, 0, 0),
+                        log_message(LOG_RAW, "POP,%d,%d,%f,%LF,%Lf,%d\n", conf->time.year_current, get_adult_population(grid, 0, 0),
                                get_suitability(grid, 0, 0), grid->param.OT,
                                grid->param.scale_factor, get_adult_carrying_capacity(grid, 0, 0));
                 }
diff --git a/src/cats/cats.c b/src/cats/cats.c
index 543cf9f77adc98781845eeb106a1a2bf99367a56..0370b24252d9eac651aef7b01ea3c7e6880db90c 100644
--- a/src/cats/cats.c
+++ b/src/cats/cats.c
@@ -130,7 +130,7 @@ void load_modules(struct cats_configuration *conf)
 {
         for (int32_t i = 0; i < conf->modules.found_count; i++) {
                 int32_t id = load_module(conf, &conf->modules.module[i]);
-                printf("%s: %d/%d-> %d (%d)\n", conf->modules.module[i].name, i, conf->modules.count, id,
+                log_message(LOG_RAW, "%s: %d/%d-> %d (%d)\n", conf->modules.module[i].name, i, conf->modules.count, id,
                        conf->modules.module[i].flags);
         }
 
diff --git a/src/cats/command_line/command_line_info.c b/src/cats/command_line/command_line_info.c
index 8f93bdc40e79c7536d933042c492c5a570f45906..cfa654c66aadd8ecbe17286278be1b0f1eeff476 100644
--- a/src/cats/command_line/command_line_info.c
+++ b/src/cats/command_line/command_line_info.c
@@ -145,16 +145,16 @@ void print_usage(const char *name, const char *error_msg)
 /// @brief prints CATS version info (git version, compiler, build and library information)
 void print_version_info(void)
 {
-        printf("CATS version %s\n\n", VERSION);
-        printf("using libraries:\n");
-        printf("\tGSL  version: %s\n", GSL_VERSION);
-        printf("\tGDAL version: %d.%d.%d\n", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR, GDAL_VERSION_REV);
-        printf("\n");
-        printf("compilation info:\n");
-        printf("\tdate:     %s\n",__DATE__);
-        printf("\ttime:     %s\n",__TIME__);
-        printf("\tcompiler: %s\n", COMPILER);
-        printf("\n");
+        log_message(LOG_RAW, "CATS version %s\n\n", VERSION);
+        log_message(LOG_RAW, "using libraries:\n");
+        log_message(LOG_RAW, "\tGSL  version: %s\n", GSL_VERSION);
+        log_message(LOG_RAW, "\tGDAL version: %d.%d.%d\n", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR, GDAL_VERSION_REV);
+        log_message(LOG_RAW, "\n");
+        log_message(LOG_RAW, "compilation info:\n");
+        log_message(LOG_RAW, "\tdate:     %s\n",__DATE__);
+        log_message(LOG_RAW, "\ttime:     %s\n",__TIME__);
+        log_message(LOG_RAW, "\tcompiler: %s\n", COMPILER);
+        log_message(LOG_RAW, "\n");
 }
 
 
@@ -173,7 +173,7 @@ void print_runtime_information(int argc, char **argv)
         char buffer[100];
         time_string(buffer, 100);
 
-        printf("run time information:\n");
+        log_message(LOG_RAW, "run time information:\n");
 
         char *node_name;
 #ifdef CATS_ON_WINDOWS
@@ -187,24 +187,24 @@ void print_runtime_information(int argc, char **argv)
 #ifdef CATS_ON_WINDOWS
         char cwd_buffer[MAX_PATH];
         GetCurrentDirectory(MAX_PATH, cwd_buffer);
-        printf("\tcwd: %s\n", cwd_buffer);
+        log_message(LOG_RAW, "\tcwd: %s\n", cwd_buffer);
 #else
         char *cwd = get_current_dir_name();
-        printf("  cwd:            %s\n", cwd);
+        log_message(LOG_RAW, "  cwd:            %s\n", cwd);
         free(cwd);
 #endif
-        printf("  date:           %s\n", buffer);
-        printf("  command:        %s\n", argv[0]);
-        printf("  arguments (%d):  ", argc - 1);
+        log_message(LOG_RAW, "  date:           %s\n", buffer);
+        log_message(LOG_RAW, "  command:        %s\n", argv[0]);
+        log_message(LOG_RAW, "  arguments (%d):  ", argc - 1);
 
         for (int i = 1; i < argc; i++) {
-                printf("%s ", argv[i]);
+                log_message(LOG_RAW, "%s ", argv[i]);
         }
 
-        printf("\n");
+        log_message(LOG_RAW, "\n");
         // HOSTNAME
-        printf("  host:           %s\n", node_name);
-        printf("\n");
+        log_message(LOG_RAW, "  host:           %s\n", node_name);
+        log_message(LOG_RAW, "\n");
 }
 
 
diff --git a/src/cats/configuration/print_configuration.c b/src/cats/configuration/print_configuration.c
index 545cf85806233a3bd4d018c1d551139b31a7ee06..62655e43a5c964e21406cf4c7e14700d83a7c7b0 100644
--- a/src/cats/configuration/print_configuration.c
+++ b/src/cats/configuration/print_configuration.c
@@ -71,7 +71,7 @@ void print_environments(struct cats_configuration *conf, int32_t indent) // FIXM
         print_string(indent, "Environment registry", "");
         for (int32_t i = 0; i < conf->environment_registry.count; i++) {
                 print_environment(&conf->environment_registry.environment[i], indent + 1);
-                printf("\n");
+                log_message(LOG_RAW, "\n");
         }
 }
 
@@ -79,7 +79,7 @@ void print_environments(struct cats_configuration *conf, int32_t indent) // FIXM
 void print_config_summary(struct cats_configuration *conf)
 {
         if (get_log_level() > LOG_INFO) return;
-        printf("%s\n", TEXT_DIVIDER);
+        log_message(LOG_RAW, "%s\n", TEXT_DIVIDER);
 
         // GENERAL
 
@@ -167,7 +167,7 @@ void print_config_summary(struct cats_configuration *conf)
                 print_string(2, "save lambda grid (density)", bool_to_string(param->save_lambda_grid_density));
                 print_rate(2, "hapaxanthy", param->hapaxanthy);
                 print_rate(2, "demographic slope", param->demographic_slope);
-                printf("\n");
+                log_message(LOG_RAW, "\n");
 
                 // DISPERSAL
                 if (param->custom_dispersal == false) {
@@ -179,7 +179,7 @@ void print_config_summary(struct cats_configuration *conf)
                                 print_rate(2, "LRD probability", dispersal->long_range_prob);
                                 print_integer(2, "LRD radius ", dispersal->long_range_radius);
                                 print_integer(2, "LRD target count", dispersal->long_range_target_count);
-                                printf("\n");
+                                log_message(LOG_RAW, "\n");
                         }
 
 
@@ -194,16 +194,16 @@ void print_config_summary(struct cats_configuration *conf)
                                 print_rate(3, "prob min", dispersal->prob_min[j]);
                                 print_rate(3, "prob max", dispersal->prob_max[j]);
 
-                                printf("\n");
+                                log_message(LOG_RAW, "\n");
                         }
                 }
         }
 
-        printf("%s\n", TEXT_DIVIDER);
+        log_message(LOG_RAW, "%s\n", TEXT_DIVIDER);
         print_environments(conf, 0);
-        printf("%s\n", TEXT_DIVIDER);
+        log_message(LOG_RAW, "%s\n", TEXT_DIVIDER);
         print_environment_sets(conf);
-        printf("%s\n", TEXT_DIVIDER);
+        log_message(LOG_RAW, "%s\n", TEXT_DIVIDER);
 }
 
 
diff --git a/src/cats/debug/debug_vital_rates.c b/src/cats/debug/debug_vital_rates.c
index 2d9f9db466aec0711d811ea83af5a501287d92d9..2f45cf9db954a28da26e8c213549cfaed4e6b58a 100644
--- a/src/cats/debug/debug_vital_rates.c
+++ b/src/cats/debug/debug_vital_rates.c
@@ -103,7 +103,7 @@ void debug_vital_rates(struct cats_configuration *conf)
         struct cats_species_param *param = &grid->param;
         set_param_values(param, 0.5, 0.25, 0.5);
         struct cats_vital_rate *cc = &param->carrying_capacity;
-        printf("K %Lf\n", param->carrying_capacity.func->func(cc, param, 0.5, 0, 0));
+        log_message(LOG_RAW, "K %Lf\n", param->carrying_capacity.func->func(cc, param, 0.5, 0, 0));
 
         enum cats_density_dependence density_dep[] = {NO_DENSITY_DEP, DENSITY_DEP_NEGATIVE};
         int32_t dens_count = sizeof(density_dep) / sizeof(density_dep[0]);
@@ -143,7 +143,7 @@ void debug_vital_rates(struct cats_configuration *conf)
                                         f = fopen(filename, "w");
                                         ENSURE_FILE_OPENED(f, filename)
                                         free(filename);
-                                        printf("%s - density %d - ZT %Lf - OT %Lf - scale %Lf\n",
+                                        log_message(LOG_RAW, "%s - density %d - ZT %Lf - OT %Lf - scale %Lf\n",
                                                vr.func->short_name,
                                                dens_idx,
                                                param->ZT,
diff --git a/src/cats/environment/environment_set.c b/src/cats/environment/environment_set.c
index 9f461268014ffc5f5bed2e904cd7c1edc77eb1c3..2d08f3d39fa912ec736fb442f814200720e3b176 100644
--- a/src/cats/environment/environment_set.c
+++ b/src/cats/environment/environment_set.c
@@ -85,21 +85,21 @@ void print_environment_set(struct cats_environment *set, int32_t indent)
                         break;
         }
 
-        printf("\n");
+        log_message(LOG_RAW, "\n");
 }
 
 
 void print_environment_sets(struct cats_configuration *conf)
 {
-        printf("Environment sets\n");
+        log_message(LOG_RAW, "Environment sets\n");
         print_integer(1, "Number of sets", conf->environment.count);
-        printf("\n");
+        log_message(LOG_RAW, "\n");
         for (int32_t i = 0; i < conf->environment.count; i++) {
                 print_environment_set(&conf->environment.environment_sets[i], 1);
 
         }
-        printf("\n");
-        printf("\n");
+        log_message(LOG_RAW, "\n");
+        log_message(LOG_RAW, "\n");
 }
 
 
diff --git a/src/cats/lambda/eigen.c b/src/cats/lambda/eigen.c
index dc42baf7eaeb003e0cec7e8e1c7b233009429bbd..6733929a4c53d90bb77f5b514a49d3f5bab53699 100644
--- a/src/cats/lambda/eigen.c
+++ b/src/cats/lambda/eigen.c
@@ -38,24 +38,24 @@ void print_eigen_system(gsl_complex eigen_value, gsl_vector_complex_view *eigen_
 {
         log_message(LOG_IMPORTANT, "Eigenvalue: %g + %gi", GSL_REAL(eigen_value), GSL_IMAG(eigen_value));
         log_message(LOG_IMPORTANT, "Eigenvector");
-        printf("\n");
+        log_message(LOG_RAW, "\n");
         const int32_t seed_persistence = get_vital_age_from_param(param, VA_SEED_PERSISTENCE);
 
         for (int32_t j = 0; j < N; ++j) {
                 char *name = NULL;
                 gsl_complex vector_entry = gsl_vector_complex_get(&eigen_vector->vector, j);
                 if (j < seed_persistence) {
-                        printf("EV::S%d::%g::%gi\n", j + 1, GSL_REAL(vector_entry), GSL_IMAG(vector_entry));
+                        log_message(LOG_RAW, "EV::S%d::%g::%gi\n", j + 1, GSL_REAL(vector_entry), GSL_IMAG(vector_entry));
                 } else if (j < N - 1) {
-                        printf("EV::J%d::%g::%gi\n", j - seed_persistence + 1, GSL_REAL(vector_entry),
+                        log_message(LOG_RAW, "EV::J%d::%g::%gi\n", j - seed_persistence + 1, GSL_REAL(vector_entry),
                                GSL_IMAG(vector_entry));
                 } else {
-                        printf("EV::A::%g::%gi\n", GSL_REAL(vector_entry), GSL_IMAG(vector_entry));
+                        log_message(LOG_RAW, "EV::A::%g::%gi\n", GSL_REAL(vector_entry), GSL_IMAG(vector_entry));
                 }
 
                 free(name);
         }
-        printf("\n");
+        log_message(LOG_RAW, "\n");
 
 }
 
@@ -99,7 +99,7 @@ gsl_complex get_largest_eigen_value(double *matrix, int32_t N, bool silent, stru
 
                 for (int32_t i = 0; i < N; i++) {
                         gsl_complex evec = gsl_vector_complex_get(eigen_values, i);
-                        printf("EV %d: %+0.17e %+0.17e i\n", i, GSL_REAL(evec), GSL_IMAG(evec));
+                        log_message(LOG_RAW, "EV %d: %+0.17e %+0.17e i\n", i, GSL_REAL(evec), GSL_IMAG(evec));
                 }
         }
 
diff --git a/src/cats/lambda/lambda.c b/src/cats/lambda/lambda.c
index 72f865e9b0323e152534e1b2336fdc7a624d3104..696b94a7bf94ac3498149e6d2b0cb0045f6c8871 100644
--- a/src/cats/lambda/lambda.c
+++ b/src/cats/lambda/lambda.c
@@ -69,21 +69,21 @@ cats_dt_rates calculate_lambda(struct cats_configuration *conf, struct lambda_pa
         bool e_val_ok = are_eigen_value_and_vector_real(largest_eigen_value, eigen_vector, N) && GSL_REAL(largest_eigen_value) > 0;
         //printf("%d\n",  conf->command_line_options.debug_flags & DEBUG_LAMBDA);
         if (!e_val_ok && (silent == false || conf->command_line_options.debug_flags & DEBUG_LAMBDA)) {
-                printf("============================\n");
+                log_message(LOG_RAW, "============================\n");
                 log_message(LOG_ERROR, "Eigenvalue or eigenvector not real and positive");
                 print_eigen_system(largest_eigen_value, &eigen_vector, N, &conf->param[species_id]);
-                printf("Original matrix\n");
+                log_message(LOG_RAW, "Original matrix\n");
                 print_matrix(matrix_copy, N, N);
-                printf("Schur form T:\n");
+                log_message(LOG_RAW, "Schur form T:\n");
                 print_matrix(matrix, N, N);
                 debug_lambda_1_found(conf, species_id, largest_eigen_value, matrix_copy, N, l_param);
-                printf("============================\n");
+                log_message(LOG_RAW, "============================\n");
         }
 
         if (silent == false && l_param->calculate_scale == true) {
 
                 if (fabs(GSL_REAL(largest_eigen_value) - 1.0) < LAMBDA_EPS) {
-                        printf("Final matrix\n");
+                        log_message(LOG_RAW, "Final matrix\n");
                         print_matrix(matrix_copy, N, N);
                         debug_lambda_1_found(conf, species_id, largest_eigen_value, matrix_copy, N, l_param);
                 }
@@ -133,7 +133,7 @@ void debug_lambda_1_found(struct cats_configuration *conf, int32_t species_id, g
         const int32_t stages_seeds = seed_persistence;
 
         const int32_t stages_juveniles = mat_max;
-        printf("\n");
+        log_message(LOG_RAW, "\n");
         log_message(LOG_IMPORTANT, "found lambda within %f of 1.0: %f",
                     LAMBDA_EPS,
                     GSL_REAL(largest_eigen_value));
diff --git a/src/cats/lambda/leslie_matrix.c b/src/cats/lambda/leslie_matrix.c
index 5566ece615a77908ae914200056d1193b2ba6a73..fe5c4ea67d905146671edd16f34c2f2b45ca1585 100644
--- a/src/cats/lambda/leslie_matrix.c
+++ b/src/cats/lambda/leslie_matrix.c
@@ -131,10 +131,10 @@ create_leslie_matrix(struct cats_configuration *conf, struct lambda_parameters *
 
         if (print_rate) {
                 for (int32_t i = 0; i < mat_max + 1; i++) {
-                        printf("m%d = %f\n", i,
+                        log_message(LOG_RAW, "m%d = %f\n", i,
                                (double) age_specific_maturation_rate(i, juvenile_survival, mat_min, mat_max));
                 }
-                printf("d = %f\n", d);
+                log_message(LOG_RAW, "d = %f\n", d);
         }
 
         // special case:
@@ -187,10 +187,10 @@ create_leslie_matrix(struct cats_configuration *conf, struct lambda_parameters *
                 if (row * N + s < N * N) {
 
                 } else {
-                        printf("N = %d\n", N);
-                        printf("s = %d\n", s);
-                        printf("row = %d\n", row);
-                        exit(1);
+                        log_message(LOG_RAW, "N = %d\n", N);
+                        log_message(LOG_RAW, "s = %d\n", s);
+                        log_message(LOG_RAW, "row = %d\n", row);
+                        exit(EXIT_FAILURE);
                 }
                 matrix[row * N + s] = (double) (germination_rate * (1.0 - m0) * juvenile_survival);
         }
diff --git a/src/cats/lambda/matrix_helpers.c b/src/cats/lambda/matrix_helpers.c
index 5b0fb71d803b2c11d6b1f57736d512e47a4a6741..f57f53885cece0793e2c4d48702d2ed02c80defb 100644
--- a/src/cats/lambda/matrix_helpers.c
+++ b/src/cats/lambda/matrix_helpers.c
@@ -34,19 +34,19 @@ void print_matrix(double *matrix, int32_t rows, int32_t cols)
         assert(matrix != NULL);
         assert(rows > 0);
         assert(cols > 0);
-        printf("[\n");
+        log_message(LOG_RAW, "[\n");
         for (int32_t row = 0; row < rows; row++) {
-                printf("  ");
+                log_message(LOG_RAW, "  ");
                 for (int32_t col = 0; col < cols; col++) {
-                        printf("%+0.17e", matrix[row * cols + col]);
-                        if (col < cols -1) {printf(", ");}
-                        if (row < rows  -1 &&  col == cols -1) printf(";");
+                        log_message(LOG_RAW, "%+0.17e", matrix[row * cols + col]);
+                        if (col < cols -1) {log_message(LOG_RAW, ", ");}
+                        if (row < rows  -1 &&  col == cols -1) log_message(LOG_RAW, ";");
                 }
 
-                printf("\n");
+                log_message(LOG_RAW, "\n");
         }
 
-        printf("]\n");
+        log_message(LOG_RAW, "]\n");
 }
 
 
diff --git a/src/cats/modules/load_module.c b/src/cats/modules/load_module.c
index a56e9b12a95d7d2b576d1dbdfd4b3e9f4c41617c..65bc4cb7090b25ce7edeb1c7b6746e37b49235ac 100644
--- a/src/cats/modules/load_module.c
+++ b/src/cats/modules/load_module.c
@@ -63,7 +63,7 @@ void print_modules(struct cats_configuration *conf)
         for (int i = 0; i < conf->modules.count; i++) {
                 print_module(&conf->modules.module[i], i);
                 print_module_species_data(&conf->param->module_data[i]);
-                printf("\n\n");
+                log_message(LOG_RAW, "\n\n");
         }
 }
 
diff --git a/src/cats/mpi/mpi_debug.c b/src/cats/mpi/mpi_debug.c
index 15a7e78e5c4630af3bf4204cb7a1576642d45c93..13583674632daa46ddcbed47ef1567c459df91b0 100644
--- a/src/cats/mpi/mpi_debug.c
+++ b/src/cats/mpi/mpi_debug.c
@@ -71,7 +71,7 @@ void mpi_save_locally_dispersed_seeds(struct cats_configuration *conf, struct ca
         int rows_after = 0;
         get_rows_around(conf, &rows_before, &rows_after, &radius, grid->id);
         offset.rows = conf->geometry.row_offset - rows_before;
-        printf("rank %d, rows %d cols %d, rows before %d, rows after %d, row offset %d\n\n", conf->mpi.world_rank,
+        log_message(LOG_RAW, "rank %d, rows %d cols %d, rows before %d, rows after %d, row offset %d\n\n", conf->mpi.world_rank,
                grid->dimension.rows,
                grid->dimension.cols, rows_before, rows_after, conf->geometry.row_offset);
         struct cats_dimension dimension;
diff --git a/src/cats/plants/juvenile_survival_calculation.c b/src/cats/plants/juvenile_survival_calculation.c
index 648ca5dc03a1690fa284b9ffea0403e52e51eaaa..1ab4a29f7521927ccd7cc66c2bf2b89689d7787e 100644
--- a/src/cats/plants/juvenile_survival_calculation.c
+++ b/src/cats/plants/juvenile_survival_calculation.c
@@ -30,7 +30,7 @@ void juvenile_start_status_old(int32_t age, cats_dt_rates start, cats_dt_rates n
                                cats_dt_rates juveniles, cats_dt_rates start_pop)
 {
 
-        printf("Start of year %02d: %08.4Lf: %08.4Lf (%06.4Lf) new adults, %08.4Lf remaining discarded \n",
+        log_message(LOG_RAW, "Start of year %02d: %08.4Lf: %08.4Lf (%06.4Lf) new adults, %08.4Lf remaining discarded \n",
                age, start, new_adults, m, juveniles);
 
 }
@@ -38,14 +38,14 @@ void juvenile_start_status_old(int32_t age, cats_dt_rates start, cats_dt_rates n
 
 void juvenile_dead_old(int32_t age, cats_dt_rates juveniles, cats_dt_rates start_pop)
 {
-        printf("ABC:nodes.append(['J%d', 'D', %Lf])\n", age - 1, juveniles / start_pop);
+        log_message(LOG_RAW, "ABC:nodes.append(['J%d', 'D', %Lf])\n", age - 1, juveniles / start_pop);
 }
 
 
 void juvenile_start_status(int32_t age, cats_dt_rates start, cats_dt_rates new_adults, cats_dt_rates m,
                            cats_dt_rates surviving, cats_dt_rates survival_rate)
 {
-        printf("Start of year %02d: %08.4Lf: %08.4Lf (%06.4Lf) new adults, %08.4Lf (%06.4Lf) surviving \n",
+        log_message(LOG_RAW, "Start of year %02d: %08.4Lf: %08.4Lf (%06.4Lf) new adults, %08.4Lf (%06.4Lf) surviving \n",
                age, start, new_adults, m, surviving,
                survival_rate);
 }
@@ -54,9 +54,9 @@ void juvenile_start_status(int32_t age, cats_dt_rates start, cats_dt_rates new_a
 void print_juvenile_dead(cats_dt_rates dead, cats_dt_rates start_pop, int32_t age)
 {
         if (age == 0) {
-                printf("ABC:nodes.append(['G', 'D', %Lf])\n", dead / start_pop);
+                log_message(LOG_RAW, "ABC:nodes.append(['G', 'D', %Lf])\n", dead / start_pop);
         } else {
-                printf("ABC:nodes.append(['J%d', 'D', %Lf])\n", age, dead / start_pop);
+                log_message(LOG_RAW, "ABC:nodes.append(['J%d', 'D', %Lf])\n", age, dead / start_pop);
         }
 }
 
@@ -64,10 +64,10 @@ void print_juvenile_dead(cats_dt_rates dead, cats_dt_rates start_pop, int32_t ag
 void print_juvenile_adults(cats_dt_rates new_adults, cats_dt_rates start_pop, int32_t age)
 {
         if (age == 0) {
-                printf("ABC:nodes.append(['G', 'A', %Lf])\n", new_adults / start_pop);
+                log_message(LOG_RAW, "ABC:nodes.append(['G', 'A', %Lf])\n", new_adults / start_pop);
         } else {
 
-                printf("ABC:nodes.append(['J%d', 'A', %Lf])\n", age, new_adults / start_pop);
+                log_message(LOG_RAW, "ABC:nodes.append(['J%d', 'A', %Lf])\n", age, new_adults / start_pop);
         }
 }
 
@@ -75,9 +75,9 @@ void print_juvenile_adults(cats_dt_rates new_adults, cats_dt_rates start_pop, in
 void print_juvenile_trans(cats_dt_rates juveniles, cats_dt_rates start_pop, int32_t age)
 {
         if (age == 0) {
-                printf("ABC:nodes.append(['G', 'J1', %Lf])\n", juveniles / start_pop);
+                log_message(LOG_RAW, "ABC:nodes.append(['G', 'J1', %Lf])\n", juveniles / start_pop);
         } else {
-                printf("ABC:nodes.append(['J%d', 'J%d', %Lf])\n", age, age + 1,
+                log_message(LOG_RAW, "ABC:nodes.append(['J%d', 'J%d', %Lf])\n", age, age + 1,
                        juveniles / start_pop);
         }
 }
@@ -91,7 +91,7 @@ calculate_total_survival(cats_dt_rates survival_rate, int32_t age_min, int32_t a
         cats_dt_rates adults = 0.0;
         if (print) {
 
-                printf("Testing juvenile survival rate of %Lf\n", survival_rate);
+                log_message(LOG_RAW, "Testing juvenile survival rate of %Lf\n", survival_rate);
         }
         for (int32_t age = 0; age < age_max + 1; age++) {
 
@@ -145,19 +145,19 @@ cats_dt_rates calculate_survival_rate(cats_dt_rates total_survival, int32_t age_
         cats_dt_rates high = 1.0;
         cats_dt_rates s = total_survival / 2;
         if (verbose) {
-                printf("finding year-to-year survival for total survival rate %Lf from germination to adult with age min and %d age max %d\n",
+                log_message(LOG_RAW, "finding year-to-year survival for total survival rate %Lf from germination to adult with age min and %d age max %d\n",
                        total_survival, age_min, age_max);
         }
         int32_t count = 0;
         while (true) {
                 count++;
                 cats_dt_rates ts = calculate_total_survival(s, age_min, age_max, false);
-                if (verbose) { printf("year survival %Lf -> total survival %Lf\n", s, ts); }
+                if (verbose) { log_message(LOG_RAW, "year survival %Lf -> total survival %Lf\n", s, ts); }
                 //printf("ts %Lf\n", fabsl(ts - total_survival)/1e-5);
 
                 if (fabsl(ts - total_survival) < JUV_SURV_DELTA) {
                         //printf("year survival %0.5Lf -> total survival %0.5Lf\n", s, ts);
-                        if (verbose) { printf("done\n"); }
+                        if (verbose) { log_message(LOG_RAW, "done\n"); }
                         break;
                 }
 
@@ -183,7 +183,7 @@ cats_dt_rates calculate_survival_rate(cats_dt_rates total_survival, int32_t age_
 
         }
         if (verbose) {
-                printf("%Lf\n", s);
+                log_message(LOG_RAW, "%Lf\n", s);
         }
         //printf("done\n");
 
diff --git a/src/cats/plants/seeds.c b/src/cats/plants/seeds.c
index a1a98c85787793dc3501ac3dcfdb3003ab82a89f..2c4b0ecec7ac65b0ef6d720fc36ce65fba95e976 100644
--- a/src/cats/plants/seeds.c
+++ b/src/cats/plants/seeds.c
@@ -182,7 +182,7 @@ germinate_seeds0(struct cats_grid *grid, const cats_dt_coord row, const cats_dt_
 {
         // how many seeds of the first year germinate?
         if (grid->dispersed_seeds[row][col] > 0) {
-                printf("%f\n", grid->dispersed_seeds[row][col]);
+                log_message(LOG_RAW, "%f\n", grid->dispersed_seeds[row][col]);
                 abort();
         }
         cats_dt_population germinated = poisson(ts->rng, grid->dispersed_seeds[row][col] * germination_rate);
@@ -223,7 +223,7 @@ void clean_seeds_0_mpi_area(struct cats_grid *grid, struct cats_configuration *c
         int rows_after = 0;
         int radius;
         get_rows_around(conf, &rows_before, &rows_after, &radius, grid->id);
-        printf("%d %d %d\n", rows_before, rows_after, radius);
+        log_message(LOG_RAW, "%d %d %d\n", rows_before, rows_after, radius);
         for (cats_dt_coord row = 0; row < grid->dimension.rows + rows_before + rows_after; row++) {
                 for (cats_dt_coord col = 0; col < grid->dimension.cols; col++) {
                         grid->seeds_0_all[row][col] = 0.0f;
diff --git a/src/cats/populations/plant_juveniles.c b/src/cats/populations/plant_juveniles.c
index 7b025f34df6542498c0088a29106d4c07b19d4d5..9ad22ff1847d23e3f2a64e5e1e2581a60b342a2a 100644
--- a/src/cats/populations/plant_juveniles.c
+++ b/src/cats/populations/plant_juveniles.c
@@ -117,10 +117,10 @@ scale_down_juveniles2(struct cats_grid *grid, cats_dt_coord row, cats_dt_coord c
         weighted_juvenile_sum = get_weighted_juvenile_sum(grid, row, col);
         if (weighted_juvenile_sum > juvenile_cc) {
                 log_message(LOG_ERROR, "%s: weighted juvenile sum > juvenile CC", __func__);
-                printf("sum: %"PRId64", cc %"PRId64"\n", weighted_juvenile_sum, juvenile_cc);
-                printf("factor %Lf\n", factor);
+                log_message(LOG_RAW, "sum: %"PRId64", cc %"PRId64"\n", weighted_juvenile_sum, juvenile_cc);
+                log_message(LOG_RAW, "factor %Lf\n", factor);
                 for (int32_t i = 0; i < mat_max + 1 - 1; i++) {
-                        printf("juvenile stage %d: %d - multiplier %Lf\n", i, grid->juveniles[row][col][i],
+                        log_message(LOG_RAW, "juvenile stage %d: %d - multiplier %Lf\n", i, grid->juveniles[row][col][i],
                                juvenile_cc_multiplier(&grid->param, i));
                 }
                 fflush(stdout);
diff --git a/src/cats/populations/population.c b/src/cats/populations/population.c
index 06e595bb614fdd4b575cdc727466b69f32bcb4e8..026f8c25550ce034542a8ee8a82ae7ffe07f5e8c 100644
--- a/src/cats/populations/population.c
+++ b/src/cats/populations/population.c
@@ -214,7 +214,7 @@ increase_population_by(struct cats_grid *grid, cats_dt_coord row, cats_dt_coord
         // existing juveniles still fit into the cell? also no problem.
         cats_dt_population_sum max_allowed_juveniles = round_population_sum_safe((cats_dt_rates) K * JUVENILE_CC_MULTI) - N;
         if (max_allowed_juveniles <0 ) {
-                printf("%d %Lf %d %ld %ld\n", K, (cats_dt_rates) K * JUVENILE_CC_MULTI, N,  round_population_sum_safe((cats_dt_rates) K * JUVENILE_CC_MULTI), max_allowed_juveniles);
+                log_message(LOG_RAW, "%d %Lf %d %ld %ld\n", K, (cats_dt_rates) K * JUVENILE_CC_MULTI, N,  round_population_sum_safe((cats_dt_rates) K * JUVENILE_CC_MULTI), max_allowed_juveniles);
         }
         assert(max_allowed_juveniles >= 0);
 
diff --git a/src/cats/vital_rates/setup_rates.c b/src/cats/vital_rates/setup_rates.c
index b90f61d84b0ee99035dd1a2e3dc0ccd4b3db4f83..9bdace81841818765b64b25bd4a417263bb5ee6e 100644
--- a/src/cats/vital_rates/setup_rates.c
+++ b/src/cats/vital_rates/setup_rates.c
@@ -309,7 +309,7 @@ print_vital_rate(const struct cats_vital_rate *vital_rate, const struct cats_spe
                         break;
         }
         print_rate(4, "adult population density suitability threshold", vital_rate->density_ts);
-        printf("\n");
+        log_message(LOG_RAW, "\n");
 
 }
 
diff --git a/src/cats/vital_rates/vital_rates_helper.c b/src/cats/vital_rates/vital_rates_helper.c
index e86cf57e305f38539667034c6a616c4c5029fb1c..d166a1217894691d2988b300570e3902b6bdd8a3 100644
--- a/src/cats/vital_rates/vital_rates_helper.c
+++ b/src/cats/vital_rates/vital_rates_helper.c
@@ -30,7 +30,7 @@ void print_vital_rates(struct cats_configuration *conf)
 {
         for (int sp_idx = 0; sp_idx < conf->param_count; sp_idx++) {
                 const struct cats_species_param *param = &conf->param[sp_idx];
-                printf("Vital rates for %s\n", conf->param->species_name);
+                log_message(LOG_RAW, "Vital rates for %s\n", conf->param->species_name);
                 print_vital_rate(&param->carrying_capacity, param);
 
                 if (param->custom_vital_rates == false) {
diff --git a/src/cats_ini/cats_ini_helpers.c b/src/cats_ini/cats_ini_helpers.c
index 250cfa3c479a039429156f46f73c8b8e977ac8bc..6fc5b3841eb97c0d1537ebe2399a67eb823af7a2 100644
--- a/src/cats_ini/cats_ini_helpers.c
+++ b/src/cats_ini/cats_ini_helpers.c
@@ -55,9 +55,9 @@ void print_accesses(struct cats_ini *ini)
         for (int32_t sec = 0; sec < SECTIONS; sec++) {
                 const int32_t KEYS = ini->n_keys[sec];
                 for (int key = 0; key < KEYS; key++) {
-                        printf("%s::%s has value '%s' and was accessed", ini->sections[sec], ini->keys[sec][key],
+                        log_message(LOG_RAW, "%s::%s has value '%s' and was accessed", ini->sections[sec], ini->keys[sec][key],
                                ini->values[sec][key]);
-                        printf("% d times\n", ini->values_accessed[sec][key]);
+                        log_message(LOG_RAW, "% d times\n", ini->values_accessed[sec][key]);
                 }
         }
 }
diff --git a/src/cats_ini/cats_ini_write_values.c b/src/cats_ini/cats_ini_write_values.c
index c49b488dcecc8da2106c9f0d8ada03a32cf241ad..d2a7957403b894e5e9e1649fb51c56ad7e167240 100644
--- a/src/cats_ini/cats_ini_write_values.c
+++ b/src/cats_ini/cats_ini_write_values.c
@@ -54,7 +54,7 @@ int add_section(struct cats_ini *ini, char *section_name)
         ini->values_accessed[N] = NULL;
         ini->values[N] = NULL;
 
-        DBG(printf("SECTION: %s\n", ini->sections[N]);)
+        DBG(log_message(LOG_RAW, "SECTION: %s\n", ini->sections[N]);)
 
         ini->n_sections++;
         return N;
@@ -139,7 +139,7 @@ int32_t add_key_val(struct cats_ini *ini, int32_t section_idx, char *key, char *
         ini->keys[section_idx][KEY] = key;
         ini->values[section_idx][KEY] = value;
         ini->n_keys[section_idx] += 1;
-        DBG(printf("\tKEY: %s VALUE: %s\n", key, val))
+        DBG(log_message(LOG_RAW, "\tKEY: %s VALUE: %s\n", key, val))
         return KEY;
 }
 
@@ -154,7 +154,7 @@ void maybe_add_key_val(char *line, struct cats_ini *ini)
         int32_t N_secs = ini->n_sections;
         int32_t SECTION = N_secs - 1;
         if (N_secs == 0) {
-                DBG(printf("IGNORED: line outside of section \"%s\"\n", line);)
+                DBG(log_message(LOG_RAW, "IGNORED: line outside of section \"%s\"\n", line);)
                 return;
         }
 
@@ -182,7 +182,7 @@ void maybe_add_key_val(char *line, struct cats_ini *ini)
 
         fflush(stdout);
         if (line == NULL || (found && strlen(found) == 0)) {
-                DBG(printf("\tIGNORED: empty or invalid line \"%s\"\n", found);)
+                DBG(log_message(LOG_RAW, "\tIGNORED: empty or invalid line \"%s\"\n", found);)
                 return;
         }
         if (found == NULL) return;
diff --git a/src/cats_strings/cats_strings.c b/src/cats_strings/cats_strings.c
index 8bd461aa69640a9cfd45f4feee6750c61f720f3a..ecb970c35b676c9a2a09284692dae553b3adaeb5 100644
--- a/src/cats_strings/cats_strings.c
+++ b/src/cats_strings/cats_strings.c
@@ -50,9 +50,9 @@ void string_array_add(struct string_array *array, const char *string)
 
         size_t new_size = (array->count + 1) * sizeof(char *);
 
-        DBG_STRING(printf("%s: address:        %p\n", __func__, array);)
-        DBG_STRING(printf("%s: count:          %d\n", __func__, array->count);)
-        DBG_STRING(printf("%s: trying to add:  %s\n", __func__, string);)
+        DBG_STRING(log_message(LOG_RAW, "%s: address:        %p\n", __func__, array);)
+        DBG_STRING(log_message(LOG_RAW, "%s: count:          %d\n", __func__, array->count);)
+        DBG_STRING(log_message(LOG_RAW, "%s: trying to add:  %s\n", __func__, string);)
 
         array->string = realloc_or_die(array->string, new_size);
         array->typehint = realloc_or_die(array->typehint, sizeof(enum JSON_HINT) * (array->count + 1));
@@ -60,11 +60,11 @@ void string_array_add(struct string_array *array, const char *string)
         array->typehint[array->count] = JSON_QUOTED;
         array->count = array->count + 1;
 
-        DBG_STRING(printf("%s: string addr:    %p\n", __func__, array->string);)
-        DBG_STRING(printf("%s: count:          %d\n", __func__, array->count);)
-        DBG_STRING(printf("%s: newest pointer: %p\n", __func__, array->string[array->count - 1]);)
-        DBG_STRING(printf("%s: newest string:  %s\n", __func__, array->string[array->count - 1]);)
-        DBG_STRING(printf("\n");)
+        DBG_STRING(log_message(LOG_RAW, "%s: string addr:    %p\n", __func__, array->string);)
+        DBG_STRING(log_message(LOG_RAW, "%s: count:          %d\n", __func__, array->count);)
+        DBG_STRING(log_message(LOG_RAW, "%s: newest pointer: %p\n", __func__, array->string[array->count - 1]);)
+        DBG_STRING(log_message(LOG_RAW, "%s: newest string:  %s\n", __func__, array->string[array->count - 1]);)
+        DBG_STRING(log_message(LOG_RAW, "\n");)
 }
 
 
@@ -163,12 +163,12 @@ void free_string_array(struct string_array **array)
         if (array == NULL) return;
 
         struct string_array *this = *array;
-        DBG_STRING(printf("%s: address:        %p\n", __func__, this);)
-        DBG_STRING(printf("%s: string:         %p\n", __func__, this->string);)
-        DBG_STRING(printf("%s: count:          %d\n", __func__, this->count);)
+        DBG_STRING(log_message(LOG_RAW, "%s: address:        %p\n", __func__, this);)
+        DBG_STRING(log_message(LOG_RAW, "%s: string:         %p\n", __func__, this->string);)
+        DBG_STRING(log_message(LOG_RAW, "%s: count:          %d\n", __func__, this->count);)
 
         for (int32_t i = 0; i < this->count; i++) {
-                DBG_STRING(printf("%s: string %d:      %s\n", __func__, i, this->string[i]);)
+                DBG_STRING(log_message(LOG_RAW, "%s: string %d:      %s\n", __func__, i, this->string[i]);)
                 free(this->string[i]);
         }
         free(this->typehint);
@@ -235,7 +235,7 @@ struct string_array *get_all_tokens(char *line, const char *sep)
                 string_array_add(result, token_copy);
                 free(token_copy);
                 //string_array_add(result, token);
-                DBG_STRING(printf("-found token: \"%s\"\n", token);)
+                DBG_STRING(log_message(LOG_RAW, "-found token: \"%s\"\n", token);)
                 seen++;
         }
 
@@ -375,11 +375,11 @@ char *string_array_paste(const struct string_array *array, const char *sep)
 
 void print_string_array(const struct string_array *array)
 {
-        printf("string array with %d entries:\n", array->count);
+        log_message(LOG_RAW, "string array with %d entries:\n", array->count);
         for (int32_t i = 0; i < array->count; i++) {
-                printf("\t% 2d: '%s'\n", i, array->string[i]);
+                log_message(LOG_RAW, "\t% 2d: '%s'\n", i, array->string[i]);
         }
-        printf("\n");
+        log_message(LOG_RAW, "\n");
 }
 
 
diff --git a/src/cats_strings/pretty_print.c b/src/cats_strings/pretty_print.c
index d9768e842f7bbc8e2349e6aafc9cc5f0dc60b7f1..42219bd605abea013dfd476993c5f8d11af83701 100644
--- a/src/cats_strings/pretty_print.c
+++ b/src/cats_strings/pretty_print.c
@@ -24,24 +24,25 @@
 #include "cats_global.h"
 #include <inttypes.h>
 #include "cats_strings.h"
+#include "logging/logging.h"
 
 
 void print_string(int indent, const char *name, const char *value)
 {
         indent *= 2;
-        if (indent > 0) printf("%*s", indent, "");
-        printf("%-*s%*s\n", PAD_NAME - indent, name, PAD_VALUE, value);
+        if (indent > 0) log_message(LOG_RAW, "%*s", indent, "");
+        log_message(LOG_RAW, "%-*s%*s\n", PAD_NAME - indent, name, PAD_VALUE, value);
 }
 
 
 void print_subcategory(int indent, const char *category_name, int64_t category_number, char *name)
 {
         indent *= 2;
-        if (indent > 0) printf("%*s", indent, "");
+        if (indent > 0) log_message(LOG_RAW, "%*s", indent, "");
         if (name) {
-                printf("[%s %" PRIu64 ": %s]\n", category_name, category_number, name);
+                log_message(LOG_RAW, "[%s %" PRIu64 ": %s]\n", category_name, category_number, name);
         } else {
-                printf("[%s %" PRIu64 "]\n", category_name, category_number);
+                log_message(LOG_RAW, "[%s %" PRIu64 "]\n", category_name, category_number);
         }
 }
 
@@ -55,13 +56,13 @@ const char *bool_to_string(const bool b)
 
 void print_category(int indent, const char *category, const char *name)
 {
-        printf("\n");
+        log_message(LOG_RAW, "\n");
         indent *= 2;
-        if (indent > 0) printf("%*s", indent, "");
+        if (indent > 0) log_message(LOG_RAW, "%*s", indent, "");
         if (name) {
-                printf("[%s - %s]\n", category, name);
+                log_message(LOG_RAW, "[%s - %s]\n", category, name);
         } else {
-                printf("[%s]\n", category);
+                log_message(LOG_RAW, "[%s]\n", category);
         }
 }
 
@@ -69,15 +70,15 @@ void print_category(int indent, const char *category, const char *name)
 void print_integer(int indent, const char *name, int64_t value)
 {
         indent *= 2;
-        if (indent > 0) printf("%*s", indent, "");
-        printf("%-*s%*"PRIu64"\n", PAD_NAME - indent, name, PAD_VALUE, value);
+        if (indent > 0) log_message(LOG_RAW, "%*s", indent, "");
+        log_message(LOG_RAW, "%-*s%*"PRIu64"\n", PAD_NAME - indent, name, PAD_VALUE, value);
 }
 
 
 void print_rate(int indent, const char *name, long double value)
 {
         indent *= 2;
-        if (indent > 0) printf("%*s", indent, "");
-        printf("%-*s%*Lf\n", PAD_NAME - indent, name, PAD_VALUE, value);
+        if (indent > 0) log_message(LOG_RAW, "%*s", indent, "");
+        log_message(LOG_RAW, "%-*s%*Lf\n", PAD_NAME - indent, name, PAD_VALUE, value);
 }
 
diff --git a/src/logging/logging.c b/src/logging/logging.c
index bfd77584f85631d704fe620bb238be355d1a27b0..1da0adecca6e0110ecd2917c6d977e162ee1330f 100644
--- a/src/logging/logging.c
+++ b/src/logging/logging.c
@@ -50,6 +50,7 @@ const char *get_log_level_name(enum cats_log_level level)
                         return " DBG";
                 case LOG_INFO:
                         return "INFO";
+                case LOG_RAW:
                 case LOG_EMPTY:
                         return "";
                 case LOG_MARK:
@@ -74,7 +75,7 @@ const char *get_log_level_name(enum cats_log_level level)
 const char *get_log_level_color(enum cats_log_level level)
 {
         switch (level) {
-
+                case LOG_RAW:
                 case LOG_DEBUG:
                         return C_RESET;
                 case LOG_INFO:
@@ -194,9 +195,15 @@ void log_msg(const char *msg, enum cats_log_level loglevel)
 {
         if (loglevel < internal_current_log_level) return;
 
+        if (loglevel == LOG_RAW) {
+                if (! logging_quiet) fprintf(stdout, "%s", msg);
+                if (cats_log_file != NULL) fprintf(cats_log_file, "%s", msg);
+                return;
+        }
+
         if (loglevel == LOG_EMPTY) {
                 if (! logging_quiet) fprintf(stdout, "\n");
-                if (cats_log_file != NULL) fprintf(stdout, "\n");
+                if (cats_log_file != NULL) fprintf(cats_log_file, "\n");
                 return;
         }
 
diff --git a/src/logging/logging.h b/src/logging/logging.h
index 4ded5f2637a0a71cfffb5a4e1cfb84fb2c2a3650..e1fcf4d730108454c125309123a07bf2011425b6 100644
--- a/src/logging/logging.h
+++ b/src/logging/logging.h
@@ -52,6 +52,7 @@ enum cats_log_level {
         LOG_WARNING,
         LOG_ERROR,
         LOG_MPI,
+        LOG_RAW,
         LOG_UNIMPLEMENTED,
         LOG_UNKNOWN
 };
diff --git a/src/modules/cats_test_module/second_file.c b/src/modules/cats_test_module/second_file.c
index eec29b72b498e5ac595d17ed946bb11625b3e58b..91c969b5c62170ded17e1e943493827149f7702c 100644
--- a/src/modules/cats_test_module/second_file.c
+++ b/src/modules/cats_test_module/second_file.c
@@ -29,6 +29,6 @@
 
 void greeting2(void)
 {
-        printf("HELLO from %d\n", CATS_MODULE_ID);
+        log_message(LOG_RAW, "HELLO from %d\n", CATS_MODULE_ID);
 }