aboutsummaryrefslogtreecommitdiff
path: root/src/driver
diff options
context:
space:
mode:
Diffstat (limited to 'src/driver')
-rw-r--r--src/driver/BH_diagnostics.cc4
-rw-r--r--src/driver/Newton.cc242
-rw-r--r--src/driver/driver.hh9
-rw-r--r--src/driver/find_horizons.cc47
-rw-r--r--src/driver/horizon_sequence.cc34
-rw-r--r--src/driver/horizon_sequence.hh5
-rw-r--r--src/driver/initial_guess.cc17
-rw-r--r--src/driver/io.cc20
-rw-r--r--src/driver/makefile8
-rw-r--r--src/driver/setup.cc35
-rw-r--r--src/driver/test_horizon_sequence.cc8
11 files changed, 271 insertions, 158 deletions
diff --git a/src/driver/BH_diagnostics.cc b/src/driver/BH_diagnostics.cc
index ca411f8..5ec1418 100644
--- a/src/driver/BH_diagnostics.cc
+++ b/src/driver/BH_diagnostics.cc
@@ -143,7 +143,7 @@ case patch_system::patch_system__plus_xyz_octant_rotating:
integral_z = integral_one * ps.origin_z();
break;
default:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" compute_BH_diagnostics(): unknown ps.type()=(int)%d!\n"
" (this should never happen!)"
@@ -247,7 +247,7 @@ snprintf(file_name_buffer, N_file_name_buffer,
hn, IO_info.BH_diagnostics_file_name_extension);
FILE *fileptr = fopen(file_name_buffer, "w");
if (fileptr == NULL)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" setup_BH_diagnostics_output_file():\n"
" can't open BH-diagnostics output file\n"
diff --git a/src/driver/Newton.cc b/src/driver/Newton.cc
index 1af34a0..2cde6c5 100644
--- a/src/driver/Newton.cc
+++ b/src/driver/Newton.cc
@@ -41,8 +41,6 @@ using jtutil::error_exit;
#include "horizon_sequence.hh"
#include "driver.hh"
-#define DEBUG
-
//******************************************************************************
//
@@ -54,14 +52,13 @@ bool reduce_and_broadcast(cGH* GH,
int N_procs, int N_active_procs,
int my_proc, bool my_active_flag,
bool we_need_more_iterations,
- int hn, fp rms_norm, fp infinity_norm,
- int hn_buffer[],
- fp rms_norm_buffer[],
- fp infinity_norm_buffer[]);
-void print_Theta_norms(int N_active_procs,
- const int hn_buffer[],
- const fp rms_norm_buffer[],
- const fp infinity_norm_buffer[]);
+ int hn, int iteration, fp rms_norm, fp infinity_norm,
+ int hn_buffer[], int iteration_buffer[],
+ fp rms_norm_buffer[], fp infinity_norm_buffer[]);
+void print_Theta_norms
+ (int N_active_procs,
+ const int hn_buffer[], const int iteration_buffer[],
+ const fp rms_norm_buffer[], const fp infinity_norm_buffer[]);
void Newton_step(patch_system& ps,
fp max_allowable_Delta_h_over_h,
const struct verbose_info& verbose_info);
@@ -73,7 +70,8 @@ void Newton_step(patch_system& ps,
// This function tries to finds each horizon assigned to this processor,
// by solving Theta(h) = 0 via Newton's method. For each horizon found,
// it computes the BH diagnostics, optionally prints them (via CCTK_VInfo()),
-// and optionally writes them to a BH diagnostics output file.
+// and optionally writes them to a BH diagnostics output file. It also
+// optionally writes the horizon shape itself to a data file.
//
// This function must be called synchronously across all processors,
// and it operates synchronously, returning only when every processor
@@ -96,6 +94,7 @@ void Newton(cGH* GH,
const struct solver_info& solver_info,
const struct IO_info& IO_info,
const struct BH_diagnostics_info& BH_diagnostics_info,
+ const struct error_info& error_info,
const struct verbose_info& verbose_info)
{
const bool my_active_flag = hs.has_genuine_horizons();
@@ -103,16 +102,28 @@ const int N_horizons = hs.N_horizons();
// buffers for reduce_and_broadcast()
int* hn_buffer = NULL;
+int* iteration_buffer = NULL;
fp * rms_norm_buffer = NULL;
fp * infinity_norm_buffer = NULL;
if (hn_buffer == NULL)
then {
// allocate on first call
hn_buffer = new int[N_active_procs];
+ iteration_buffer = new int[N_active_procs];
rms_norm_buffer = new fp [N_active_procs];
infinity_norm_buffer = new fp [N_active_procs];
}
+// print out which horizons we're finding on this processor
+if (hs.has_genuine_horizons())
+ then CCTK_VInfo(CCTK_THORNSTRING,
+ "proc %d: searching for horizon%s %s",
+ my_proc,
+ (N_horizons > 1 ? "s" : ""), hs.sequence_string(","));
+ else CCTK_VInfo(CCTK_THORNSTRING,
+ "proc %d: dummy horizon(s) only",
+ my_proc);
+
//
// each pass through this loop finds a single horizon,
// or does corresponding dummy-horizon calls
@@ -158,11 +169,10 @@ if (hn_buffer == NULL)
//
for (int iteration = 1 ; ; ++iteration)
{
- #ifdef DEBUG
- CCTK_VInfo(CCTK_THORNSTRING,
- "Newton_solve(): iteration %d",
- iteration);
- #endif
+ if (verbose_info.print_algorithm_debug)
+ then CCTK_VInfo(CCTK_THORNSTRING,
+ "beginning iteration %d (horizon_is_genuine=%d)",
+ iteration, int(horizon_is_genuine));
//
@@ -173,36 +183,33 @@ if (hn_buffer == NULL)
&& solver_info.debugging_output_at_each_Newton_iteration)
then output_gridfn(*ps_ptr, gfns::gfn__h,
IO_info, IO_info.h_base_file_name,
- hn, verbose_info.print_algorithm_details,
+ hn, verbose_info.print_algorithm_highlights,
iteration);
- #ifdef DEBUG
- CCTK_VInfo(CCTK_THORNSTRING,
- " computing Theta: horizon_is_genuine=%d",
- int(horizon_is_genuine));
- #endif
jtutil::norm<fp> Theta_norms;
const bool Theta_is_ok
= expansion(ps_ptr,
cgi, gi,
+ error_info, (iteration == 1),
true, // yes, we want the Jacobian coeffs
verbose_info.print_algorithm_details,
&Theta_norms);
- #ifdef DEBUG
- CCTK_VInfo(CCTK_THORNSTRING,
- "Newton_solve(): Theta_is_ok=%d",
- Theta_is_ok);
- if (horizon_is_genuine && Theta_is_ok)
- then CCTK_VInfo(CCTK_THORNSTRING,
- " Theta rms-norm %.1e, infinity-norm %.1e",
- double(Theta_norms.rms_norm()),
- double(Theta_norms.infinity_norm()));
- #endif
+ if (verbose_info.print_algorithm_debug)
+ then {
+ CCTK_VInfo(CCTK_THORNSTRING,
+ " Newton_solve(): Theta_is_ok=%d",
+ Theta_is_ok);
+ if (horizon_is_genuine && Theta_is_ok)
+ then CCTK_VInfo(CCTK_THORNSTRING,
+ " Theta rms-norm %.1e, infinity-norm %.1e",
+ double(Theta_norms.rms_norm()),
+ double(Theta_norms.infinity_norm()));
+ }
if (horizon_is_genuine && Theta_is_ok
&& solver_info.debugging_output_at_each_Newton_iteration)
then output_gridfn(*ps_ptr, gfns::gfn__Theta,
IO_info, IO_info.Theta_base_file_name,
- hn, verbose_info.print_algorithm_details,
+ hn, verbose_info.print_algorithm_highlights,
iteration);
@@ -218,35 +225,13 @@ if (hn_buffer == NULL)
.Theta_norm_for_convergence);
if (horizon_is_genuine)
then AH_info_ptr->found_flag = found_this_horizon;
- if (found_this_horizon)
- then {
- compute_BH_diagnostics(*ps_ptr, BH_diagnostics_info,
- verbose_info,
- AH_info_ptr->BH_diagnostics);
- // FIXME: see header comment
- print_BH_diagnostics(AH_info_ptr->BH_diagnostics,
- N_horizons, hn,
- verbose_info);
- if (IO_info.output_BH_diagnostics)
- then {
- if (AH_info_ptr->BH_diagnostics_fileptr == NULL)
- then AH_info_ptr->BH_diagnostics_fileptr
- = setup_BH_diagnostics_output_file(IO_info,
- N_horizons,
- hn);
- output_BH_diagnostics_fn(AH_info_ptr->BH_diagnostics,
- IO_info,
- hn, AH_info_ptr
- ->BH_diagnostics_fileptr);
- }
- }
// does *this* horizon need more iterations?
// i.e. has this horizon's Newton iteration not yet converged?
const bool this_horizon_needs_more_iterations
= horizon_is_genuine && Theta_is_ok
&& !found_this_horizon
- && (iteration <= max_iterations);
+ && (iteration < max_iterations);
// do we (this processor) need to do more iterations
// on this or a following horizon?
@@ -257,37 +242,73 @@ if (hn_buffer == NULL)
if (verbose_info.print_algorithm_details)
then {
CCTK_VInfo(CCTK_THORNSTRING,
- "flags: found_this_horizon=%d",
+ " flags: found_this_horizon=%d",
int(found_this_horizon));
CCTK_VInfo(CCTK_THORNSTRING,
- " this_horizon_needs_more_iterations=%d",
+ " this_horizon_needs_more_iterations=%d",
int(this_horizon_needs_more_iterations));
CCTK_VInfo(CCTK_THORNSTRING,
- " we_need_more_iterations=%d",
+ " we_need_more_iterations=%d",
int(we_need_more_iterations));
}
// does any processor need more iterations
// on its current or a following horizon?
const bool any_proc_needs_more_iterations
- = reduce_and_broadcast
- (GH, N_procs, N_active_procs,
- my_proc, my_active_flag,
- we_need_more_iterations,
- hn, horizon_is_genuine ? Theta_norms.rms_norm() : 0.0,
- horizon_is_genuine ? Theta_norms.infinity_norm() : 0.0,
- hn_buffer, rms_norm_buffer, infinity_norm_buffer);
+ = reduce_and_broadcast(GH, N_procs, N_active_procs,
+ my_proc, my_active_flag,
+ we_need_more_iterations,
+ hn, iteration,
+ ((horizon_is_genuine && Theta_is_ok)
+ ? Theta_norms.rms_norm() : 0.0),
+ ((horizon_is_genuine && Theta_is_ok)
+ ? Theta_norms.infinity_norm() : 0.0),
+ hn_buffer, iteration_buffer,
+ rms_norm_buffer, infinity_norm_buffer);
if (verbose_info.print_algorithm_details)
then {
CCTK_VInfo(CCTK_THORNSTRING,
- " ==> any_proc_needs_more_iterations=%d",
+ " ==> any_proc_needs_more_iterations=%d",
int(any_proc_needs_more_iterations));
}
if (my_active_flag && verbose_info.print_algorithm_highlights)
then print_Theta_norms(N_active_procs,
- hn_buffer, rms_norm_buffer,
- infinity_norm_buffer);
+ hn_buffer, iteration_buffer,
+ rms_norm_buffer, infinity_norm_buffer);
+ if (found_this_horizon)
+ then {
+ compute_BH_diagnostics(*ps_ptr, BH_diagnostics_info,
+ verbose_info,
+ AH_info_ptr->BH_diagnostics);
+ // FIXME: see header comment
+ print_BH_diagnostics(AH_info_ptr->BH_diagnostics,
+ N_horizons, hn,
+ verbose_info);
+ if (IO_info.output_BH_diagnostics)
+ then {
+ if (AH_info_ptr->BH_diagnostics_fileptr == NULL)
+ then AH_info_ptr->BH_diagnostics_fileptr
+ = setup_BH_diagnostics_output_file(IO_info,
+ N_horizons,
+ hn);
+ output_BH_diagnostics_fn(AH_info_ptr->BH_diagnostics,
+ IO_info,
+ hn, AH_info_ptr
+ ->BH_diagnostics_fileptr);
+ }
+
+ if (IO_info.output_h)
+ then output_gridfn(*ps_ptr, gfns::gfn__h,
+ IO_info, IO_info.h_base_file_name,
+ hn, verbose_info
+ .print_algorithm_highlights);
+ if (IO_info.output_Theta)
+ then output_gridfn(*ps_ptr, gfns::gfn__Theta,
+ IO_info, IO_info.Theta_base_file_name,
+ hn, verbose_info
+ .print_algorithm_highlights);
+ }
//
@@ -303,10 +324,9 @@ if (hn_buffer == NULL)
}
if ((N_procs == 1) && !this_horizon_needs_more_iterations)
then {
- #ifdef DEBUG
- CCTK_VInfo(CCTK_THORNSTRING,
- " single processor: skipping to next horizon");
- #endif
+ if (verbose_info.print_algorithm_debug)
+ then CCTK_VInfo(CCTK_THORNSTRING,
+ "==> [single processor] Skipping to next horizon");
break; // *** LOOP EXIT ***
}
@@ -315,17 +335,17 @@ if (hn_buffer == NULL)
// compute the Jacobian matrix
// *** this is a synchronous operation across all processors ***
//
- #ifdef DEBUG
- CCTK_VInfo(CCTK_THORNSTRING,
- " computing Jacobian: genuine/dummy flag %d",
- int(this_horizon_needs_more_iterations));
- #endif
+ if (verbose_info.print_algorithm_debug)
+ then CCTK_VInfo(CCTK_THORNSTRING,
+ " computing Jacobian: genuine/dummy flag %d",
+ int(this_horizon_needs_more_iterations));
const bool Jacobian_is_ok
= expansion_Jacobian(this_horizon_needs_more_iterations ? ps_ptr
: NULL,
this_horizon_needs_more_iterations ? Jac_ptr
: NULL,
cgi, gi, Jacobian_info,
+ error_info, (iteration == 1),
verbose_info.print_algorithm_details);
@@ -335,10 +355,9 @@ if (hn_buffer == NULL)
//
if (! (this_horizon_needs_more_iterations && Jacobian_is_ok))
then {
- #ifdef DEBUG
- CCTK_VInfo(CCTK_THORNSTRING,
- " skipping to next horizon");
- #endif
+ if (verbose_info.print_algorithm_debug)
+ then CCTK_VInfo(CCTK_THORNSTRING,
+ " skipping to next horizon");
break; // *** LOOP EXIT ***
}
@@ -401,7 +420,8 @@ assert( false );
// This function does an inclusive-or--reduction of the "we need more
// iterations (either on this or on another genuine horizon" flags across
// all active processors. It also broadcasts which horizon we're working
-// on, and the current error norms, to processor #0.
+// on, the current iteration number, and the current error norms, to
+// processor #0.
//
// The reduction and broadcast are combined in this function to allow
// doing them all with a single reduction operation (and thus only a
@@ -415,10 +435,11 @@ assert( false );
// we_need_more_iterations = "we need more iterations (either on this
// or on another genuine horizon" flag to be
// inclusive-or--reduced
-// hn,{rms,infinity}_norm = horizon number and norms: if this is an active
-// processor these are broadcast to processor #0,
-// otherwise these are ignored
-// {hn,{rms,infinity}_norm}_buffer[N_active_procs]
+// hn,iteration,{rms,infinity}_norm = the values to be broadcast:
+// if this is an active processor these
+// are broadcast to processor #0,
+// otherwise these are ignored
+// {hn,iteration,{rms,infinity}_norm}_buffer[N_active_procs]
// = buffers for horizon numbers and norms: if this is processor #0
// these are set to the horizon numbers and norms for all active
// processors, otherwise these are set to undefined (garbage) values
@@ -432,10 +453,9 @@ bool reduce_and_broadcast(cGH* GH,
int N_procs, int N_active_procs,
int my_proc, bool my_active_flag,
bool we_need_more_iterations,
- int hn, fp rms_norm, fp infinity_norm,
- int hn_buffer[],
- fp rms_norm_buffer[],
- fp infinity_norm_buffer[])
+ int hn, int iteration, fp rms_norm, fp infinity_norm,
+ int hn_buffer[], int iteration_buffer[],
+ fp rms_norm_buffer[], fp infinity_norm_buffer[])
{
assert( my_proc >= 0 );
assert( my_proc < N_procs );
@@ -446,10 +466,12 @@ assert( my_proc < N_procs );
// doing a sum-reduction of the buffers.
//
// Alas, to do everything in a single operation, all the values have to
-// be of a single datatype in a single array, so we convert hn to
-// CCTK_REAL, and encode the "we need more iterations" in its sign.
+// be of a single datatype in a single array, so we convert hn and
+// iteration to CCTK_REAL, and encode the "we need more iterations" in
+// hn's sign.
//
-const int N_reduce_buffer = 3*N_active_procs;
+const int N_vars = 4;
+const int N_reduce_buffer = N_vars*N_active_procs;
static CCTK_REAL* reduce_buffer = NULL;
if (reduce_buffer == NULL)
then {
@@ -467,9 +489,10 @@ if (reduce_buffer == NULL)
if (my_active_flag)
then {
assert( my_proc < N_active_procs );
- reduce_buffer[3*my_proc + 0] = we_need_more_iterations ? hn : -hn;
- reduce_buffer[3*my_proc + 1] = rms_norm;
- reduce_buffer[3*my_proc + 2] = infinity_norm;
+ reduce_buffer[N_vars*my_proc + 0] = we_need_more_iterations ? hn : -hn;
+ reduce_buffer[N_vars*my_proc + 1] = iteration;
+ reduce_buffer[N_vars*my_proc + 2] = rms_norm;
+ reduce_buffer[N_vars*my_proc + 3] = infinity_norm;
}
//
@@ -479,7 +502,7 @@ if (my_active_flag)
// this name is appropriate for PUGHReduce, caveat user for other drivers :)
const int reduction_handle = CCTK_ReductionArrayHandle("sum");
if (reduction_handle < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"reduce_and_broadcast(): can't get sum-reduction handle!");
/*NOTREACHED*/
@@ -492,7 +515,7 @@ const int status
N_reduce_buffer,
CCTK_VARIABLE_REAL);
if (status < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"reduce_and_broadcast(): error status %d from reduction!",
status); /*NOTREACHED*/
@@ -502,12 +525,13 @@ if (status < 0)
bool any_proc_needs_more_iterations = false;
for (int proc = 0 ; proc < N_active_procs ; ++proc)
{
- const int i_proc = 3*proc;
+ const int i_proc = N_vars*proc;
const bool proc_needs_more_iterations = reduce_buffer[i_proc + 0] > 0.0;
any_proc_needs_more_iterations |= proc_needs_more_iterations;
hn_buffer[proc] = (int) fabs(reduce_buffer[i_proc + 0]);
- rms_norm_buffer[proc] = reduce_buffer[i_proc + 1];
- infinity_norm_buffer[proc] = reduce_buffer[i_proc + 2];
+ iteration_buffer[proc] = (int) reduce_buffer[i_proc + 1];
+ rms_norm_buffer[proc] = reduce_buffer[i_proc + 2];
+ infinity_norm_buffer[proc] = reduce_buffer[i_proc + 3];
}
return any_proc_needs_more_iterations;
@@ -523,20 +547,22 @@ return any_proc_needs_more_iterations;
// N_active_procs = The number of active processors.
// hn_buffer[N_active_procs] = Gives the horizon each active processor
// is currently working on.
+// iteration_buffer[N_active_procs] = Gives the iteration number of each
+// active processor on its current horizon.
// {rms,infinity}_norm_buffer[N_active_procs] = Gives the Theta norms for
// each active processor.
//
namespace {
-void print_Theta_norms(int N_active_procs,
- const int hn_buffer[],
- const fp rms_norm_buffer[],
- const fp infinity_norm_buffer[])
+void print_Theta_norms
+ (int N_active_procs,
+ const int hn_buffer[], const int iteration_buffer[],
+ const fp rms_norm_buffer[], const fp infinity_norm_buffer[])
{
for (int proc = 0 ; proc < N_active_procs ; ++proc)
{
CCTK_VInfo(CCTK_THORNSTRING,
- " proc %d/horizon %d: ||Theta|| rms=%.1e, infty=%.1e",
- proc, int(hn_buffer[proc]),
+ " proc %d/horizon %d/it %d |Theta| rms=%.1e inf=%.1e",
+ proc, hn_buffer[proc], iteration_buffer[proc],
double(rms_norm_buffer[proc]),
double(infinity_norm_buffer[proc]));
}
diff --git a/src/driver/driver.hh b/src/driver/driver.hh
index e5ad9aa..225130a 100644
--- a/src/driver/driver.hh
+++ b/src/driver/driver.hh
@@ -28,7 +28,8 @@ enum verbose_level
verbose_level__physics_highlights,
verbose_level__physics_details,
verbose_level__algorithm_highlights,
- verbose_level__algorithm_details // no comma
+ verbose_level__algorithm_details,
+ verbose_level__algorithm_debug // no comma
};
//
@@ -122,6 +123,9 @@ struct IO_info
bool output_initial_guess;
int how_often_to_output_h,
how_often_to_output_Theta;
+ // based on the above, do we want to output things now (this time step)?
+ bool output_h, output_Theta;
+
bool output_ghost_zones_for_h;
const char* ASCII_gnuplot_file_name_extension;
const char* HDF5_file_name_extension;
@@ -154,6 +158,7 @@ struct verbose_info
bool print_physics_details;
bool print_algorithm_highlights;
bool print_algorithm_details;
+ bool print_algorithm_debug;
};
//******************************************************************************
@@ -207,6 +212,7 @@ struct AH_info
struct state
{
enum method method;
+ struct error_info error_info;
struct verbose_info verbose_info;
int timer_handle;
int N_procs; // total number of processors
@@ -275,6 +281,7 @@ void Newton(cGH* GH,
const struct solver_info& solver_info,
const struct IO_info& IO_info,
const struct BH_diagnostics_info& BH_diagnostics_info,
+ const struct error_info& error_info,
const struct verbose_info& verbose_info);
// BH_diagnostics.cc
diff --git a/src/driver/find_horizons.cc b/src/driver/find_horizons.cc
index fd35afd..0324cf1 100644
--- a/src/driver/find_horizons.cc
+++ b/src/driver/find_horizons.cc
@@ -71,7 +71,7 @@ void do_evaluate_expansions(int my_proc, int N_horizons,
const struct cactus_grid_info& cgi,
const struct geometry_info& gi,
const struct IO_info& IO_info,
- bool output_h, bool output_Theta,
+ const struct error_info& error_info,
const struct verbose_info& verbose_info,
int timer_handle);
void do_test_expansion_Jacobians(int my_proc, int N_horizons,
@@ -81,6 +81,7 @@ void do_test_expansion_Jacobians(int my_proc, int N_horizons,
struct Jacobian_info& Jac_info,
bool test_all_Jacobian_compute_methods,
const struct IO_info& IO_info,
+ const struct error_info& error_info,
const struct verbose_info& verbose_info,
int timer_handle);
@@ -117,6 +118,7 @@ const bool active_flag = hs.has_genuine_horizons();
const struct geometry_info& gi = state.gi;
struct Jacobian_info& Jac_info = state.Jac_info;
struct IO_info& IO_info = state.IO_info;
+const struct error_info& error_info = state.error_info;
const struct verbose_info& verbose_info = state.verbose_info;
// what are the semantics of the Cactus gxx variables? (these may
@@ -125,17 +127,17 @@ if (CCTK_Equals(metric_type, "physical"))
then cgi.Cactus_conformal_metric = false;
else if (CCTK_Equals(metric_type, "static conformal"))
then cgi.Cactus_conformal_metric = (conformal_state > 0);
-else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+else CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"AHFinderDirect_find_horizons(): unknown metric_type=\"%s\"!",
metric_type); /*NOTREACHED*/
// get the Cactus time step and decide if we want to output h and/or Theta now
IO_info.time_iteration = cctk_iteration;
IO_info.time = cctk_time;
-const bool output_h
+IO_info.output_h
= (IO_info.how_often_to_output_h > 0)
&& ((IO_info.time_iteration % IO_info.how_often_to_output_h) == 0);
-const bool output_Theta
+IO_info.output_Theta
= (IO_info.how_often_to_output_Theta > 0)
&& ((IO_info.time_iteration % IO_info.how_often_to_output_Theta) == 0);
@@ -176,9 +178,9 @@ switch (state.method)
case method__evaluate_expansions:
do_evaluate_expansions(my_proc, state.N_horizons,
*state.my_hs, state.my_AH_info,
- cgi, gi,
- IO_info, output_h, output_Theta,
- state.verbose_info, state.timer_handle);
+ cgi, gi, IO_info,
+ error_info, verbose_info,
+ state.timer_handle);
break;
case method__test_expansion_Jacobians:
@@ -186,7 +188,8 @@ case method__test_expansion_Jacobians:
state.my_AH_info,
cgi, gi, Jac_info,
(test_all_Jacobian_compute_methods != 0),
- IO_info, verbose_info, state.timer_handle);
+ IO_info, error_info, verbose_info,
+ state.timer_handle);
break;
case method__find_horizons:
@@ -197,13 +200,13 @@ case method__find_horizons:
*state.my_hs, state.my_AH_info,
cgi, gi, Jac_info, state.solver_info,
IO_info, state.BH_diagnostics_info,
- verbose_info);
+ error_info, verbose_info);
if (state.timer_handle >= 0)
then CCTK_TimerStopI(state.timer_handle);
break;
default:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" find_horizons(): unknown method=(int)%d!\n"
" (this should never happen!)"
@@ -213,7 +216,8 @@ default:
if (state.timer_handle >= 0)
then {
- printf("timer stats for computation:\n");
+ CCTK_VInfo(CCTK_THORNSTRING,
+ "timer stats for computation:");
CCTK_TimerPrintDataI(state.timer_handle, -1);
}
}
@@ -279,7 +283,7 @@ const CCTK_REAL* data_ptr = static_cast<const fp*>(
);
if (check_for_NULL && (data_ptr == NULL))
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" Cactus_gridfn_data_ptr(): got unexpected NULL data pointer\n"
" for Cactus geometry gridfn!\n"
@@ -317,7 +321,7 @@ void do_evaluate_expansions(int my_proc, int N_horizons,
const struct cactus_grid_info& cgi,
const struct geometry_info& gi,
const struct IO_info& IO_info,
- bool output_h, bool output_Theta,
+ const struct error_info& error_info,
const struct verbose_info& verbose_info,
int timer_handle)
{
@@ -341,13 +345,14 @@ if (active_flag)
jtutil::norm<fp> Theta_norms;
const bool Theta_ok = expansion(&ps,
cgi, gi,
+ error_info, true,// initial eval
false, // no Jacobian coeffs
true, // yes, print msgs
&Theta_norms);
if (timer_handle >= 0)
then CCTK_TimerStopI(timer_handle);
- if (output_h)
+ if (IO_info.output_h)
then output_gridfn(ps, gfns::gfn__h,
IO_info, IO_info.h_base_file_name,
hn, verbose_info.print_algorithm_details);
@@ -357,7 +362,7 @@ if (active_flag)
CCTK_VInfo(CCTK_THORNSTRING,
" Theta(h) rms-norm %.2e, infinity-norm %.2e",
Theta_norms.rms_norm(), Theta_norms.infinity_norm());
- if (output_Theta)
+ if (IO_info.output_Theta)
then output_gridfn(ps, gfns::gfn__Theta,
IO_info, IO_info
.Theta_base_file_name,
@@ -369,8 +374,9 @@ if (active_flag)
else {
for (int i = 0 ; i < N_horizons ; ++i)
{
- expansion(NULL, // dummy computation
- cgi, gi);
+ expansion(NULL, // dummy computation
+ cgi, gi,
+ error_info, true); // initial evaluation
}
}
}
@@ -410,6 +416,7 @@ void do_test_expansion_Jacobians(int my_proc, int N_horizons,
struct Jacobian_info& Jac_info,
bool test_all_Jacobian_compute_methods,
const struct IO_info& IO_info,
+ const struct error_info& error_info,
const struct verbose_info& verbose_info,
int timer_handle)
{
@@ -427,10 +434,12 @@ patch_system* ps_ptr = active_flag ? AH_info_ptr->ps_ptr : NULL;
//
Jacobian* Jac_NP_ptr = active_flag ? AH_info_ptr->Jac_ptr : NULL;
expansion(ps_ptr,
- cgi, gi);
+ cgi, gi,
+ error_info, true); // initial evaluation
Jac_info.Jacobian_compute_method = Jacobian__numerical_perturbation;
expansion_Jacobian(ps_ptr, Jac_NP_ptr,
cgi, gi, Jac_info,
+ error_info, true, // initial evaluation
print_msg_flag);
Jacobian* Jac_SD_FDdr_ptr = NULL;
@@ -444,10 +453,12 @@ if (test_all_Jacobian_compute_methods)
: NULL;
expansion(ps_ptr,
cgi, gi,
+ error_info, true, // initial evaluation
true); // compute SD Jacobian coeffs
Jac_info.Jacobian_compute_method = Jacobian__symbolic_diff_with_FD_dr;
expansion_Jacobian(ps_ptr, Jac_SD_FDdr_ptr,
cgi, gi, Jac_info,
+ error_info, true, // initial evaluation
print_msg_flag);
}
diff --git a/src/driver/horizon_sequence.cc b/src/driver/horizon_sequence.cc
index ca47489..fa88423 100644
--- a/src/driver/horizon_sequence.cc
+++ b/src/driver/horizon_sequence.cc
@@ -4,12 +4,17 @@
//
// horizon_sequence::horizon_sequence
// horizon_sequence::~horizon_sequence
+// horizon_sequence::sequence_string
// horizon_sequence::append_hn
// horizon_sequence::next_posn
//
#include <stdio.h>
#include <assert.h>
+
+#include "../include/stdc.h"
+#include "../jtutil/util.hh"
+
#include "horizon_sequence.hh"
//******************************************************************************
@@ -38,6 +43,35 @@ delete[] my_hn_;
//******************************************************************************
//
+// This function returns a (pointer to a) C-style string showing all
+// the horizon numbers in the sequence, separated by the C-style string
+// sep , eg. "2,3,5".
+//
+// Note the result points into a private static buffer.
+//
+char* horizon_sequence::sequence_string(const char sep[]) const
+{
+const int N_hn_buffer = 10;
+char hn_buffer[N_hn_buffer];
+
+const int N_buffer = 100;
+static char buffer[N_buffer];
+
+buffer[0] = '\0';
+ for (int pos = 0 ; pos < my_N_horizons_ ; ++pos)
+ {
+ if (pos > 0)
+ then AHFinderDirect_Strlcat(buffer, sep, N_buffer);
+ snprintf(hn_buffer, N_hn_buffer, "%d", my_hn_[pos]);
+ AHFinderDirect_Strlcat(buffer, hn_buffer, N_buffer);
+ }
+
+return buffer;
+}
+
+//******************************************************************************
+
+//
// This function appends hn to the sequence. It returns the new value
// of my_N_horizons().
//
diff --git a/src/driver/horizon_sequence.hh b/src/driver/horizon_sequence.hh
index 398f687..ca363a1 100644
--- a/src/driver/horizon_sequence.hh
+++ b/src/driver/horizon_sequence.hh
@@ -28,6 +28,11 @@ public:
// are there any genuine horizons in the sequence (for this processor)?
bool has_genuine_horizons() const { return my_N_horizons_ > 0; }
+ // C-style string showing all horizon numbers,
+ // separated by the C-style string sep, eg. "2,3,5"
+ // ... result points into a private static buffer
+ char* sequence_string(const char sep[]) const;
+
// is the current horizon in the sequence dummy/genuine?
bool is_dummy () const { return posn_is_dummy (posn_); }
bool is_genuine() const { return posn_is_genuine(posn_); }
diff --git a/src/driver/initial_guess.cc b/src/driver/initial_guess.cc
index bc9ab89..7e00390 100644
--- a/src/driver/initial_guess.cc
+++ b/src/driver/initial_guess.cc
@@ -132,7 +132,7 @@ case initial_guess__coord_ellipsoid:
break;
default:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"unknown initial guess method=(int)%d!",
int(igi.method)); /*NOTREACHED*/
}
@@ -157,7 +157,7 @@ else if (STRING_EQUAL(initial_guess_method_string, "coordinate sphere"))
then return initial_guess__coord_sphere;
else if (STRING_EQUAL(initial_guess_method_string, "coordinate ellipsoid"))
then return initial_guess__coord_ellipsoid;
-else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+else CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" decode_initial_guess_method():\n"
" unknown initial_guess_method_string=\"%s\"!",
@@ -176,7 +176,7 @@ else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
// and the horizon is worked out on page 13.2 of my AHFinderDirect notes.
//
// Arguments:
-// [xyz]_posn = The position of the Kerr black hole.
+// [xyz]_posn = The global-coordinate position of the Kerr black hole.
// (m,a) = Describe the Kerr black hole. Note that my convention has
// a=J/m^2 dimensionless, while MTW take a=J/m=m*(my a).
// Kerr_Schild_flag = false to use Kerr coordinates,
@@ -215,9 +215,9 @@ if (verbose_info.print_algorithm_details)
" setting coordinate %s",
Kerr_Schild_flag ? "ellipsoid" : "sphere");
setup_coord_ellipsoid(ps,
- x_posn, y_posn, z_posn,
- xy_radius, xy_radius, z_radius,
- verbose_info.print_algorithm_details);
+ x_posn, y_posn, z_posn,
+ xy_radius, xy_radius, z_radius,
+ verbose_info.print_algorithm_details);
}
}
@@ -227,7 +227,7 @@ setup_coord_ellipsoid(ps,
// This function sets up an ellipsoid initial guess, using the formulas
// in "ellipsoid.maple" and the Maple-generated C code in "ellipsoid.c":
//
-// ellipsoid has center (A,B,C), radius (a,b,c)
+// ellipsoid has global-coordinates center (A,B,C), radius (a,b,c)
// angular coordinate system has center (U,V,W)
//
// direction cosines wrt angular coordinate center are (xcos,ycos,zcos)
@@ -292,7 +292,8 @@ if (print_msg_flag)
then r = r_plus;
else if ((r_plus < 0.0) && (r_minus > 0.0))
then r = r_minus;
- else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ else CCTK_VWarn(FATAL_ERROR,
+ __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" setup_coord_ellipsoid():\n"
" expected exactly one r>0 solution to quadratic, got 0 or 2!\n"
diff --git a/src/driver/io.cc b/src/driver/io.cc
index 2bddaa9..3db7edf 100644
--- a/src/driver/io.cc
+++ b/src/driver/io.cc
@@ -88,11 +88,11 @@ case horizon_file_format__ASCII_gnuplot:
break;
case horizon_file_format__HDF5:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"input_gridfn(): HDF5 data files not implemented yet!"); /*NOTREACHED*/
default:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" input_gridfn(): unknown IO_info.horizon_file_format=(int)%d!\n"
" (this should never happen!)"
@@ -126,7 +126,7 @@ case horizon_file_format__ASCII_gnuplot:
case gfns::gfn__h:
if (print_msg_flag)
then CCTK_VInfo(CCTK_THORNSTRING,
- " writing h to \"%s\"", file_name);
+ "writing h to \"%s\"", file_name);
ps.print_ghosted_gridfn_with_xyz
(unknown_gfn,
true, gfns::gfn__h,
@@ -137,19 +137,19 @@ case horizon_file_format__ASCII_gnuplot:
case gfns::gfn__Theta:
if (print_msg_flag)
then CCTK_VInfo(CCTK_THORNSTRING,
- " writing Theta to \"%s\"", file_name);
+ "writing Theta to \"%s\"", file_name);
ps.print_gridfn(unknown_gfn, file_name);
break;
case gfns::gfn__Delta_h:
if (print_msg_flag)
then CCTK_VInfo(CCTK_THORNSTRING,
- " writing Delta_h to \"%s\"", file_name);
+ "writing Delta_h to \"%s\"", file_name);
ps.print_gridfn(unknown_gfn, file_name);
break;
default:
if (print_msg_flag)
then CCTK_VInfo(CCTK_THORNSTRING,
- " writing gfn=%d to \"%s\"",
+ "writing gfn=%d to \"%s\"",
unknown_gfn, file_name);
ps.print_gridfn(unknown_gfn, file_name);
break;
@@ -157,11 +157,11 @@ case horizon_file_format__ASCII_gnuplot:
break;
case horizon_file_format__HDF5:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"output_gridfn(): HDF5 data files not implemented yet!"); /*NOTREACHED*/
default:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" output_gridfn(): unknown IO_info.horizon_file_format=(int)%d!\n"
" (this should never happen!)"
@@ -206,7 +206,7 @@ if (print_msg_flag)
FILE *fileptr = fopen(file_name, "w");
if (fileptr == NULL)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"output_Jacobians(): can't open output file \"%s\"!",
file_name); /*NOTREACHED*/
@@ -334,7 +334,7 @@ case horizon_file_format__HDF5:
file_name_extension = IO_info.HDF5_file_name_extension;
break;
default:
- CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"\n"
" io_file_name(): unknown IO_info.horizon_file_format=(int)%d!\n"
" (this should never happen!)"
diff --git a/src/driver/makefile b/src/driver/makefile
index bbc3443..852a6ed 100644
--- a/src/driver/makefile
+++ b/src/driver/makefile
@@ -1,5 +1,5 @@
# Makefile for driver code
-# $Header: /usr/local/svn/cvs-repositories/numrelcvs/AEIThorns/AHFinderDirect/src/driver/makefile,v 1.3 2003-02-15 18:43:08 jthorn Exp $
+# $Header: /usr/local/svn/cvs-repositories/numrelcvs/AEIThorns/AHFinderDirect/src/driver/makefile,v 1.4 2003-02-16 22:21:48 jthorn Exp $
#
# Targets:
@@ -21,8 +21,10 @@ test : test_horizon_sequence
.PHONY : test_horizon_sequence
test_horizon_sequence :
- $(CXX) $(CXXFLAGS) -o $@ test_horizon_sequence.cc horizon_sequence.cc
+ $(CXX) $(CXXFLAGS) -o $@ \
+ test_horizon_sequence.cc horizon_sequence.cc \
+ ../jtutil/miscstr.c
.PHONY : clean
clean :
- -rm *core test_horizon_sequence
+ -rm test_horizon_sequence
diff --git a/src/driver/setup.cc b/src/driver/setup.cc
index df6e76e..d0b823e 100644
--- a/src/driver/setup.cc
+++ b/src/driver/setup.cc
@@ -105,6 +105,19 @@ CCTK_VInfo(CCTK_THORNSTRING,
//
state.method = decode_method(method);
+state.error_info.warn_level__point_outside__initial
+ = warn_level__point_outside__initial;
+state.error_info.warn_level__point_outside__subsequent
+ = warn_level__point_outside__subsequent;
+state.error_info.warn_level__skipping_finite_check
+ = warn_level__skipping_finite_check;
+state.error_info.warn_level__nonfinite_geometry
+ = warn_level__nonfinite_geometry;
+state.error_info.warn_level__gij_not_positive_definite__initial
+ = warn_level__gij_not_positive_definite__initial;
+state.error_info.warn_level__gij_not_positive_definite__subsequent
+ = warn_level__gij_not_positive_definite__subsequent;
+
struct verbose_info& verbose_info = state.verbose_info;
verbose_info.verbose_level = decode_verbose_level(verbose_level);
verbose_info.print_physics_highlights
@@ -115,6 +128,8 @@ verbose_info.print_algorithm_highlights
= (state.verbose_info.verbose_level >= verbose_level__algorithm_highlights);
verbose_info.print_algorithm_details
= (state.verbose_info.verbose_level >= verbose_level__algorithm_details);
+verbose_info.print_algorithm_debug
+ = (state.verbose_info.verbose_level >= verbose_level__algorithm_debug);
state.timer_handle = (print_timing_stats != 0) ? CCTK_TimerCreateI() : -1;
@@ -140,7 +155,7 @@ cgi.Cactus_conformal_metric = false; // dummy value, may change later
cgi.coord_system_handle = CCTK_CoordSystemHandle(coordinate_system_name);
if (cgi.coord_system_handle < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"AHFinderDirect_setup(): can't find Cactus coordinate system \"%s\"!",
coordinate_system_name); /*NOTREACHED*/
cgi.g_dd_11_varindex = CCTK_VarIndex("ADMBase::gxx");
@@ -195,12 +210,12 @@ gi.geometry_method = decode_geometry_method(geometry_method);
// parameters for geometry_method = interpolation methods
gi.operator_handle = CCTK_InterpHandle(geometry_interpolator_name);
if (gi.operator_handle < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"AHFinderDirect_setup(): couldn't find interpolator \"%s\"!",
geometry_interpolator_name); /*NOTREACHED*/
gi.param_table_handle = Util_TableCreateFromString(geometry_interpolator_pars);
if (gi.param_table_handle < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"AHFinderDirect_setup(): bad geometry-interpolator parameter(s) \"%s\"!",
geometry_interpolator_pars); /*NOTREACHED*/
@@ -249,6 +264,8 @@ IO_info.horizon_file_format = decode_horizon_file_format(horizon_file_format);
IO_info.output_initial_guess = (output_initial_guess != 0);
IO_info.how_often_to_output_h = how_often_to_output_h;
IO_info.how_often_to_output_Theta = how_often_to_output_Theta;
+IO_info.output_h = false; // dummy value
+IO_info.output_Theta = false; // dummy value
IO_info.output_ghost_zones_for_h = (output_ghost_zones_for_h != 0);
IO_info.ASCII_gnuplot_file_name_extension = ASCII_gnuplot_file_name_extension;
IO_info.HDF5_file_name_extension = HDF5_file_name_extension;
@@ -308,13 +325,13 @@ if (verbose_info.print_algorithm_highlights)
then CCTK_VInfo(CCTK_THORNSTRING, " setting up interpatch interpolator");
const int interp_handle = CCTK_InterpHandle(interpatch_interpolator_name);
if (interp_handle < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"AHFinderDirect_setup(): couldn't find interpolator \"%s\"!",
interpatch_interpolator_name); /*NOTREACHED*/
const int interp_param_table_handle
= Util_TableCreateFromString(interpatch_interpolator_pars);
if (interp_param_table_handle < 0)
- then CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ then CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"AHFinderDirect_setup(): bad interpatch-interpolator parameter(s) \"%s\"!",
interpatch_interpolator_pars); /*NOTREACHED*/
@@ -441,7 +458,7 @@ else if (STRING_EQUAL(method_string, "test expansion Jacobians"))
then return method__test_expansion_Jacobians;
else if (STRING_EQUAL(method_string, "find horizons"))
then return method__find_horizons;
-else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+else CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"decode_method(): unknown method_string=\"%s\"!",
method_string); /*NOTREACHED*/
}
@@ -465,7 +482,9 @@ else if (STRING_EQUAL(verbose_level_string, "algorithm highlights"))
then return verbose_level__algorithm_highlights;
else if (STRING_EQUAL(verbose_level_string, "algorithm details"))
then return verbose_level__algorithm_details;
-else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+else if (STRING_EQUAL(verbose_level_string, "algorithm debug"))
+ then return verbose_level__algorithm_debug;
+else CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"decode_verbose_level(): unknown verbose_level_string=\"%s\"!",
verbose_level_string); /*NOTREACHED*/
}
@@ -485,7 +504,7 @@ if (STRING_EQUAL(horizon_file_format_string, "ASCII (gnuplot)"))
then return horizon_file_format__ASCII_gnuplot;
else if (STRING_EQUAL(horizon_file_format_string, "HDF5"))
then return horizon_file_format__HDF5;
-else CCTK_VWarn(-1, __LINE__, __FILE__, CCTK_THORNSTRING,
+else CCTK_VWarn(FATAL_ERROR, __LINE__, __FILE__, CCTK_THORNSTRING,
"decode_horizon_file_format(): unknown horizon_file_format_string=\"%s\"!",
horizon_file_format_string); /*NOTREACHED*/
}
diff --git a/src/driver/test_horizon_sequence.cc b/src/driver/test_horizon_sequence.cc
index 04e0978..d59a0f4 100644
--- a/src/driver/test_horizon_sequence.cc
+++ b/src/driver/test_horizon_sequence.cc
@@ -2,7 +2,10 @@
// $Header$
#include <stdio.h>
+#include <string.h>
#include <assert.h>
+
+#include "../include/stdc.h"
#include "horizon_sequence.hh"
// prototypes for functions local to this file
@@ -34,6 +37,7 @@ horizon_sequence hs0(0);
assert( hs0.N_horizons() == 0 );
assert( hs0.my_N_horizons() == 0 );
assert( ! hs0.has_genuine_horizons() );
+assert( STRING_EQUAL(hs0.sequence_string(","), "") );
assert( hs0.is_dummy() );
assert( ! hs0.is_genuine() );
assert( ! hs0.is_next_genuine() );
@@ -69,6 +73,7 @@ assert( hs1.append_hn(42) == 1 );
assert( hs1.N_horizons() == 1 );
assert( hs1.my_N_horizons() == 1 );
assert( hs1.has_genuine_horizons() );
+assert( STRING_EQUAL(hs1.sequence_string(","), "42") );
assert( hs1.is_genuine() );
assert( ! hs1.is_next_genuine() );
assert( hs1.dummy_number() == 0 );
@@ -117,6 +122,7 @@ assert( hs2.append_hn(69) == 2 );
assert( hs2.N_horizons() == 2 );
assert( hs2.my_N_horizons() == 2 );
assert( hs2.has_genuine_horizons() );
+assert( STRING_EQUAL(hs2.sequence_string(","), "42,69") );
assert( hs2.is_genuine() );
assert( hs2.is_next_genuine() );
assert( hs2.dummy_number() == 0 );
@@ -182,6 +188,8 @@ void test345()
assert( hs.is_next_genuine() );
assert( hs.dummy_number() == 0 );
+ assert( STRING_EQUAL(hs.sequence_string(","), "42,69,105") );
+
for (int i = 1 ; i <= 4 ; ++i)
{
printf(" try %d...\n", i);