aboutsummaryrefslogtreecommitdiff
path: root/Carpet/LoopControl/src/lc_auto.c
diff options
context:
space:
mode:
Diffstat (limited to 'Carpet/LoopControl/src/lc_auto.c')
-rw-r--r--Carpet/LoopControl/src/lc_auto.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/Carpet/LoopControl/src/lc_auto.c b/Carpet/LoopControl/src/lc_auto.c
new file mode 100644
index 000000000..73d9a43fc
--- /dev/null
+++ b/Carpet/LoopControl/src/lc_auto.c
@@ -0,0 +1,143 @@
+#include <assert.h>
+#include <math.h>
+
+#include <gsl/gsl_rng.h>
+
+#include <cctk.h>
+#include <cctk_Parameters.h>
+
+#include "lc_siman.h"
+
+#include "lc_auto.h"
+
+
+
+static lc_statset_t const * restrict statset;
+
+
+
+static inline
+int
+step (int const oldval, int const maxval,
+ gsl_rng const * restrict const rng, double const step_size)
+{
+ int const offset = (int) ((2 * gsl_rng_uniform_pos (rng) - 1) * step_size);
+ return (oldval + offset + maxval) % maxval;
+}
+
+
+
+static
+void
+take_step (const gsl_rng *rng, void *xp_, double step_size)
+{
+ DECLARE_CCTK_PARAMETERS;
+ lc_auto_position_t * restrict const xp = xp_;
+ if (gsl_rng_uniform (rng) < siman_probability_change_topology) {
+ xp->topology = gsl_rng_uniform_int (rng, statset->ntopologies);
+ }
+ for (int d=0; d<3; ++d) {
+ xp->tiling[d] = step (xp->tiling[d], statset->ntilings[d], rng, step_size);
+ }
+}
+
+static
+double
+distance (void *xp_, void *yp_)
+{
+ lc_auto_position_t const * restrict const xp = xp_;
+ lc_auto_position_t const * restrict const yp = yp_;
+ double dist = 10 * (xp->topology != yp->topology);
+ for (int d=0; d<3; ++d) {
+ dist += fabs (xp->tiling[d] - yp->tiling[d]);
+ }
+ return dist / 2; /* 2 = sqrt(4) */
+}
+
+static
+void
+print_position (void *xp_)
+{
+ lc_auto_position_t const * restrict const xp = xp_;
+ printf (" #%2d/[%3d,%3d,%3d]",
+ xp->topology,
+ xp->tiling[0], xp->tiling[1], xp->tiling[2]);
+}
+
+
+
+void
+lc_auto_init (lc_statset_t * restrict const ls,
+ int * restrict const topology,
+ int tiling[3])
+{
+ DECLARE_CCTK_PARAMETERS;
+ assert (! cycle_j_tilings); /* don't mix strategies */
+
+ if (! ls->auto_state) {
+ /* First call for this user parameter set of this loop */
+
+ ls->auto_state = malloc (sizeof * ls->auto_state);
+
+ /* Initialise simulated annealing parameters */
+ ls->auto_state->siman_params.iters_fixed_T = siman_iters_fixed_T;
+ ls->auto_state->siman_params.step_size = siman_step_size;
+ ls->auto_state->siman_params.k = siman_k;
+ ls->auto_state->siman_params.t_initial = siman_T_initial;
+ ls->auto_state->siman_params.mu_t = siman_mu_T;
+ ls->auto_state->siman_params.t_min = siman_T_min;
+
+ /* Create random number generator */
+ gsl_rng_env_setup();
+ ls->auto_state->rng = gsl_rng_alloc (gsl_rng_default);
+
+ /* Set initial position */
+ ls->auto_state->position.topology = * topology;
+ for (int d=0; d<3; ++d) {
+ ls->auto_state->position.tiling[d] = tiling[d];
+ }
+
+ /* Initialise simulated annealing state */
+ statset = ls;
+ ls->auto_state->siman_state =
+ lc_siman_solve (NULL,
+ ls->auto_state->rng,
+ NULL, 0.0,
+ take_step, distance, print_position,
+ sizeof (lc_auto_position_t),
+ ls->auto_state->siman_params);
+
+ } else {
+ /* Not the first call */
+
+ if (ls->auto_state->siman_state) {
+ /* The solver is still active: ask for the next state */
+ statset = ls;
+ ls->auto_state->siman_state =
+ lc_siman_solve (ls->auto_state->siman_state,
+ ls->auto_state->rng,
+ & ls->auto_state->position, ls->auto_state->time,
+ take_step, distance, print_position,
+ sizeof (lc_auto_position_t),
+ ls->auto_state->siman_params);
+ }
+
+ /* Set thread topology and tiling specification */
+ * topology = ls->auto_state->position.topology;
+ for (int d=0; d<3; ++d) {
+ tiling[d] = ls->auto_state->position.tiling[d];
+ }
+
+ } /* if not the first call */
+}
+
+
+
+void
+lc_auto_finish (lc_statset_t * restrict const ls,
+ lc_stattime_t const * restrict const lt)
+{
+ ls->auto_state->time =
+ lt->time_calc_sum /
+ (lt->time_count * ls->npoints[0] * ls->npoints[1] * ls->npoints[2]);
+}