aboutsummaryrefslogtreecommitdiff
path: root/init.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-08-27 13:35:52 +0200
committerAnton Khirnov <anton@khirnov.net>2021-08-27 13:37:30 +0200
commit1f443d3fdb93e71a70244b7521ae0f4c40601351 (patch)
treeef98c12efbdd879f6e0dc4f0c439b621824195ee /init.c
parent83bc788ae55b49d633ead8fa7ad5136f919826ce (diff)
Add public API for evaluating the residual at an arbitrary location.
Diffstat (limited to 'init.c')
-rw-r--r--init.c87
1 files changed, 82 insertions, 5 deletions
diff --git a/init.c b/init.c
index c5c633c..dac0731 100644
--- a/init.c
+++ b/init.c
@@ -796,7 +796,7 @@ static int eval_var_kernel(void *arg, unsigned int job_idx, unsigned int thread_
static int eval_var(const TDContext *td, unsigned int var_idx,
size_t nb_coords, const double *r, const double *theta,
- const unsigned int diff_order[2],
+ const unsigned int diff_order[2], double add,
double *out)
{
TDPriv *s = td->priv;
@@ -830,7 +830,7 @@ static int eval_var(const TDContext *td, unsigned int var_idx,
thread_data.basis[0] = s->basis[var_idx][0];
thread_data.basis[1] = s->basis[var_idx][1];
thread_data.coeffs = td->coeffs[var_idx];
- thread_data.init_val = (var_idx == 0 && diff_order[0] == 0 && diff_order[1] == 0) ? 1.0 : 0.0;
+ thread_data.init_val = add;
tp_execute(s->tp, nb_coords, eval_var_kernel, &thread_data);
@@ -846,7 +846,8 @@ int td_eval_psi(const TDContext *td,
const unsigned int diff_order[2],
double *out)
{
- return eval_var(td, 0, nb_coords, r, theta, diff_order, out);
+ const double add = (diff_order[0] == 0 && diff_order[1] == 0) ? 1.0 : 0.0;
+ return eval_var(td, 0, nb_coords, r, theta, diff_order, add, out);
}
int td_eval_krr(const TDContext *td,
@@ -854,14 +855,14 @@ int td_eval_krr(const TDContext *td,
const unsigned int diff_order[2],
double *out)
{
- return eval_var(td, 1, nb_coords, r, theta, diff_order, out);
+ return eval_var(td, 1, nb_coords, r, theta, diff_order, 0.0, out);
}
int td_eval_kpp(const TDContext *td,
size_t nb_coords, const double *r, const double *theta,
const unsigned int diff_order[2],
double *out)
{
- return eval_var(td, 2, nb_coords, r, theta, diff_order, out);
+ return eval_var(td, 2, nb_coords, r, theta, diff_order, 0.0, out);
}
int td_eval_krt(const TDContext *td,
@@ -955,3 +956,79 @@ fail:
return 0;
}
+
+int td_eval_residual(const TDContext *td,
+ size_t nb_coords_r, const double *r,
+ size_t nb_coords_theta, const double *theta,
+ double *out[3])
+{
+ const unsigned int nb_coords[2] = { nb_coords_r, nb_coords_theta };
+ const double *coords[2] = { r, theta};
+ const size_t grid_size = nb_coords_r * nb_coords_theta;
+
+ TDConstraintEvalContext *ce = NULL;
+ double *r_2d = NULL, *theta_2d = NULL;
+ double *vars[TD_CONSTRAINT_VAR_NB][PSSOLVE_DIFF_ORDER_NB] = {{ NULL }};
+ int ret;
+
+ ret = posix_memalign((void**)&r_2d, 32, grid_size * sizeof(*r_2d));
+ ret |= posix_memalign((void**)&theta_2d, 32, grid_size * sizeof(*theta_2d));
+ if (ret) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ for (size_t j = 0; j < nb_coords_theta; j++) {
+ for (size_t i = 0; i < nb_coords_r; i++) {
+ const size_t idx = j * nb_coords_r + i;
+ r_2d[idx] = r[i];
+ theta_2d[idx] = theta[j];
+ }
+ }
+
+ for (int var = 0; var < TD_CONSTRAINT_VAR_NB; var++) {
+ for (int diff_order = 0; diff_order < PSSOLVE_DIFF_ORDER_NB; diff_order++) {
+ const unsigned int diff_orders[2] = {
+ tdi_pssolve_diff_order(diff_order, 0),
+ tdi_pssolve_diff_order(diff_order, 1),
+ };
+
+ ret = posix_memalign((void**)&vars[var][diff_order],
+ 32, grid_size * sizeof(*vars[var][diff_order]));
+ if (ret) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = eval_var(td, var, grid_size, r_2d, theta_2d, diff_orders,
+ 0.0, vars[var][diff_order]);
+ if (ret)
+ goto fail;
+ }
+ }
+
+ ret = constraint_eval_alloc(td, nb_coords, coords,
+ td->amplitude, &ce);
+ if (ret < 0)
+ goto fail;
+
+ ret = tdi_constraint_eval(ce, TD_CONSTRAINT_EQ_HAM, vars, out[0]);
+ ret |= tdi_constraint_eval(ce, TD_CONSTRAINT_EQ_MOM_0, vars, out[1]);
+ ret |= tdi_constraint_eval(ce, TD_CONSTRAINT_EQ_MOM_1, vars, out[2]);
+ if (ret)
+ goto fail;
+
+ ret = 0;
+
+fail:
+ free(r_2d);
+ free(theta_2d);
+ tdi_constraint_eval_free(&ce);
+ for (int diff_order = 0; diff_order < PSSOLVE_DIFF_ORDER_NB; diff_order++) {
+ free(vars[0][diff_order]);
+ free(vars[1][diff_order]);
+ free(vars[2][diff_order]);
+ }
+
+ return ret;
+}