ZJVGO4A2JCKZGLPXJWBBUO7TJZCT7AI5RGPS24LQD35T3W5C7FGAC Cactus Code Thorn PuncturesAuthor(s) : Erik Schnetter <schnetter@gmail.com>Maintainer(s): Erik Schnetter <schnetter@gmail.com>Licence : LGPL--------------------------------------------------------------------------1. PurposeProvide multi-black-hole initial conditions based on the "puncture" idea:Steven Brandt, Bernd Brügmann, "A simple construction of initial datafor multiple black holes", Phys. Rev. Lett. 78:3606-3609, 1997, DOI:10.1103/PhysRevLett.78.3606, arXiv:gr-qc/9703066.
# Configuration definitions for thorn PuncturesREQUIRES Arith
# Interface definition for thorn PuncturesIMPLEMENTS: PuncturesINHERITS: ADMBaseUSES INCLUDE HEADER: loop.hxxUSES INCLUDE HEADER: mat.hxxUSES INCLUDE HEADER: sum.hxxUSES INCLUDE HEADER: vec.hxxUSES INCLUDE HEADER: vect.hxxvoid FUNCTION CallScheduleGroup(CCTK_POINTER IN cctkGH,CCTK_STRING IN groupname)REQUIRES FUNCTION CallScheduleGroupvoid FUNCTION SolvePoisson(CCTK_INT IN gi_sol,CCTK_INT IN gi_rhs,CCTK_INT IN gi_res,CCTK_REAL IN reltol,CCTK_REAL IN abstol,CCTK_REAL OUT res_initial,CCTK_REAL OUT res_final)REQUIRES FUNCTION SolvePoissonCCTK_REAL urhs TYPE=gf TAGS='index={0 0 0} checkpoint="no"' "Right hand side"CCTK_REAL usol TYPE=gf TAGS='index={0 0 0} checkpoint="no"' "Conformal factor u"CCTK_REAL ures TYPE=gf TAGS='index={0 0 0} checkpoint="no"' "Residual"
# run.me:# run.cores: 4# run.memory: 1.0e9# run.time: 60.0ActiveThorns = "ADMBaseCarpetXFormalineIOUtilPunctures"Cactus::cctk_show_schedule = noCactus::presync_mode = "mixed-error"CarpetX::verbose = noCarpetX::poison_undefined_values = yesCactus::cctk_itlast = 0CarpetX::xmin = -1.0CarpetX::ymin = -1.0CarpetX::zmin = -1.0CarpetX::xmax = +1.0CarpetX::ymax = +1.0CarpetX::zmax = +1.0CarpetX::ncells_x = 8CarpetX::ncells_y = 8CarpetX::ncells_z = 8CarpetX::periodic_x = noCarpetX::periodic_y = noCarpetX::periodic_z = noCarpetX::periodic = no# CarpetX::reflection_x = yes# CarpetX::reflection_y = yes# CarpetX::reflection_z = yes# CarpetX::reflection_upper_x = yes# CarpetX::reflection_upper_y = yes# CarpetX::reflection_upper_z = yesCarpetX::ghost_size = 1ADMBase::initial_data = "Punctures"ADMBase::initial_lapse = "Punctures"ADMBase::initial_shift = "Punctures"ADMBase::initial_dtlapse = "Punctures"ADMBase::initial_dtshift = "Punctures"Punctures::npunctures = 1IO::out_dir = $parfileIO::out_every = 1IO::out_mode = "np"IO::out_proc_every = 1CarpetX::out_silo_vars = "all"
# run.me:# run.cores: 4# run.memory: 1.0e9# run.time: 60.0ActiveThorns = "ADMBaseCarpetXFormalineIOUtilPunctures"Cactus::cctk_show_schedule = noCactus::presync_mode = "mixed-error"CarpetX::verbose = noCarpetX::poison_undefined_values = yesCactus::cctk_itlast = 0CarpetX::xmin = -1.0CarpetX::ymin = -1.0CarpetX::zmin = -1.0CarpetX::xmax = +1.0CarpetX::ymax = +1.0CarpetX::zmax = +1.0CarpetX::ncells_x = 8CarpetX::ncells_y = 8CarpetX::ncells_z = 8CarpetX::periodic_x = noCarpetX::periodic_y = noCarpetX::periodic_z = noCarpetX::periodic = no# CarpetX::reflection_x = yes# CarpetX::reflection_y = yes# CarpetX::reflection_z = yes# CarpetX::reflection_upper_x = yes# CarpetX::reflection_upper_y = yes# CarpetX::reflection_upper_z = yesCarpetX::ghost_size = 1ADMBase::initial_data = "Punctures"ADMBase::initial_lapse = "Punctures"ADMBase::initial_shift = "Punctures"ADMBase::initial_dtlapse = "Punctures"ADMBase::initial_dtshift = "Punctures"Punctures::npunctures = 2Punctures::mass[0] = 0.5Punctures::posz[0] = +0.5Punctures::mass[1] = 0.5Punctures::posz[1] = -0.5IO::out_dir = $parfileIO::out_every = 1IO::out_mode = "np"IO::out_proc_every = 1CarpetX::out_silo_vars = "all"
# run.me:# run.cores: 4# run.memory: 1.0e9# run.time: 60.0ActiveThorns = "ADMBaseCarpetXFormalineIOUtilPunctures"Cactus::cctk_show_schedule = noCactus::presync_mode = "mixed-error"CarpetX::verbose = noCarpetX::poison_undefined_values = yesCactus::cctk_itlast = 0CarpetX::xmin = -1.0CarpetX::ymin = -1.0CarpetX::zmin = -1.0CarpetX::xmax = +1.0CarpetX::ymax = +1.0CarpetX::zmax = +1.0CarpetX::ncells_x = 8CarpetX::ncells_y = 8CarpetX::ncells_z = 8CarpetX::periodic_x = noCarpetX::periodic_y = noCarpetX::periodic_z = noCarpetX::periodic = no# CarpetX::reflection_x = yes# CarpetX::reflection_y = yes# CarpetX::reflection_z = yes# CarpetX::reflection_upper_x = yes# CarpetX::reflection_upper_y = yes# CarpetX::reflection_upper_z = yesCarpetX::ghost_size = 1ADMBase::initial_data = "Punctures"ADMBase::initial_lapse = "Punctures"ADMBase::initial_shift = "Punctures"ADMBase::initial_dtlapse = "Punctures"ADMBase::initial_dtshift = "Punctures"IO::out_dir = $parfileIO::out_every = 1IO::out_mode = "np"IO::out_proc_every = 1CarpetX::out_silo_vars = "all"
# run.me:# run.cores: 4# run.memory: 1.0e9# run.time: 60.0ActiveThorns = "ADMBaseCarpetXFormalineIOUtilPunctures"Cactus::cctk_show_schedule = noCactus::presync_mode = "mixed-error"CarpetX::verbose = noCarpetX::poison_undefined_values = yesCactus::cctk_itlast = 0CarpetX::xmin = -10.0CarpetX::ymin = -10.0CarpetX::zmin = -10.0CarpetX::xmax = +10.0CarpetX::ymax = +10.0CarpetX::zmax = +10.0CarpetX::ncells_x = 64CarpetX::ncells_y = 64CarpetX::ncells_z = 64CarpetX::periodic_x = noCarpetX::periodic_y = noCarpetX::periodic_z = noCarpetX::periodic = no# CarpetX::reflection_x = yes# CarpetX::reflection_y = yes# CarpetX::reflection_z = yes# CarpetX::reflection_upper_x = yes# CarpetX::reflection_upper_y = yes# CarpetX::reflection_upper_z = yesCarpetX::ghost_size = 1ADMBase::initial_data = "Punctures"ADMBase::initial_lapse = "Punctures"ADMBase::initial_shift = "Punctures"ADMBase::initial_dtlapse = "Punctures"ADMBase::initial_dtshift = "Punctures"# QC-0 setupPunctures::npunctures = 2Punctures::mass[0] = 0.453Punctures::posx[0] = +1.168642873Punctures::momy[0] = +0.3331917498Punctures::mass[1] = 0.453Punctures::posx[1] = -1.168642873Punctures::momy[1] = -0.3331917498IO::out_dir = $parfileIO::out_every = 1IO::out_mode = "np"IO::out_proc_every = 1CarpetX::out_silo_vars = "all"
# run.me:# run.cores: 40# run.memory: 1.0e9# run.time: 600.0ActiveThorns = "ADMBaseCarpetXErrorEstimatorFormalineIOUtilPunctures"Cactus::cctk_show_schedule = noCactus::presync_mode = "mixed-error"CarpetX::verbose = noCarpetX::poison_undefined_values = yesCactus::cctk_itlast = 0CarpetX::xmin = -16.0CarpetX::ymin = -16.0CarpetX::zmin = -16.0CarpetX::xmax = +16.0CarpetX::ymax = +16.0CarpetX::zmax = +16.0CarpetX::ncells_x = 64CarpetX::ncells_y = 64CarpetX::ncells_z = 64CarpetX::periodic_x = noCarpetX::periodic_y = noCarpetX::periodic_z = noCarpetX::periodic = no# CarpetX::reflection_x = yes# CarpetX::reflection_y = yes# CarpetX::reflection_z = yes# CarpetX::reflection_upper_x = yes# CarpetX::reflection_upper_y = yes# CarpetX::reflection_upper_z = yesCarpetX::ghost_size = 1CarpetX::max_num_levels = 5CarpetX::regrid_every = 0CarpetX::regrid_error_threshold = 8.0ErrorEstimator::region_shape = "cube"ErrorEstimator::scale_by_resolution = yesADMBase::initial_data = "Punctures"ADMBase::initial_lapse = "Punctures"ADMBase::initial_shift = "Punctures"ADMBase::initial_dtlapse = "Punctures"ADMBase::initial_dtshift = "Punctures"# QC-0 setupPunctures::npunctures = 2Punctures::mass[0] = 0.453Punctures::posx[0] = +1.168642873Punctures::momy[0] = +0.3331917498Punctures::mass[1] = 0.453Punctures::posx[1] = -1.168642873Punctures::momy[1] = -0.3331917498IO::out_dir = $parfileIO::out_every = 1IO::out_mode = "np"IO::out_proc_every = 1CarpetX::out_silo_vars = "all"
# Parameter definitions for thorn PuncturesSHARES: ADMBaseEXTENDS KEYWORD initial_data "Initial metric and extrinsic curvature datasets"{"Punctures" :: "Puncture black holes"}EXTENDS KEYWORD initial_lapse "Initial lapse value"{"Punctures" :: "Lapse suitable for puncture black holes"}EXTENDS KEYWORD initial_shift "Initial shift value"{"Punctures" :: "Shift suitable for puncture black holes"}EXTENDS KEYWORD initial_dtlapse "Initial dtlapse value"{"Punctures" :: "Lapse time derivative suitable for puncture black holes"}EXTENDS KEYWORD initial_dtshift "Initial dtshift value"{"Punctures" :: "Shift time derivative suitable for puncture black holes"}PRIVATE:CCTK_INT npunctures "Number of punctures"{0:11 :: ""} 0CCTK_REAL mass[11] "Puncture mass"{0.0:* :: ""} 1.0CCTK_REAL posx[11] "Puncture position"{*:* :: ""} 0.0CCTK_REAL posy[11] "Puncture position"{*:* :: ""} 0.0CCTK_REAL posz[11] "Puncture position"{*:* :: ""} 0.0CCTK_REAL momx[11] "Puncture momentum"{*:* :: ""} 0.0CCTK_REAL momy[11] "Puncture momentum"{*:* :: ""} 0.0CCTK_REAL momz[11] "Puncture momentum"{*:* :: ""} 0.0CCTK_REAL amomx[11] "Puncture angular momentum"{*:* :: ""} 0.0CCTK_REAL amomy[11] "Puncture angular momentum"{*:* :: ""} 0.0CCTK_REAL amomz[11] "Puncture angular momentum"{*:* :: ""} 0.0CCTK_REAL rmin "Minimum radius (to avoid singularities)"{0.0:* :: ""} 1.0e-8CCTK_REAL abstol "Absolute tolerance for non-linear solver"{0.0:* :: ""} 1.0e-6
# Schedule definitions for thorn PuncturesSCHEDULE Punctures_init AT initial{LANG: CWRITES: usol(everywhere)} "Set up initial guess"SCHEDULE Punctures_solve AT initial AFTER Punctures_init{LANG: COPTIONS: levelREADS: usol(everywhere)WRITES: usol(everywhere)WRITES: urhs(everywhere)WRITES: ures(interior)} "Solve Hamiltonian constraint"SCHEDULE GROUP Punctures_solve1{} "Perform one linear solve"SCHEDULE Punctures_rhs IN Punctures_solve1{LANG: CREADS: usol(everywhere)WRITES: urhs(everywhere)} "Set up right hand side"SCHEDULE GROUP Punctures_solve2{} "Perform one linear solve"SCHEDULE Punctures_boundary IN Punctures_solve2{LANG: CREADS: usol(everywhere)WRITES: usol(everywhere)} "Apply boundary conditions to puncture solution"SCHEDULE Punctures_ADMBase AT initial AFTER Punctures_solve{LANG: CREADS: usol(everywhere)WRITES: ADMBase::metric(everywhere)WRITES: ADMBase::curv(everywhere)WRITES: ADMBase::lapse(everywhere)WRITES: ADMBase::shift(everywhere)WRITES: ADMBase::dtlapse(everywhere)WRITES: ADMBase::dtshift(everywhere)} "Set ADMBase variables"
# Main make.code.defn file for thorn Punctures# Source files in this directorySRCS = punctures.cxx# Subdirectories containing source filesSUBDIRS =
#include <loop.hxx>#include <mat.hxx>#include <sum.hxx>#include <vec.hxx>#include <vect.hxx>#include <cctk.h>#include <cctk_Arguments_Checked.h>#include <cctk_Parameters.h>#include <cassert>#include <cmath>namespace Punctures {using namespace Arith;using namespace Loop;using namespace std;////////////////////////////////////////////////////////////////////////////////template <typename T> T pown(T x, int n) {if (n < 0) {x = 1 / x;n = -n;}T r = 1;while (n > 0) {if (n % 2)r *= x;x *= x;n /= 2;}return r;}const mat<CCTK_REAL, 3, DN, DN> g([](int a, int b) { return a == b; });const auto epsilon = [](int a, int b,int c) -> CCTK_REAL CCTK_ATTRIBUTE_ALWAYS_INLINE {if (a == 0 && b == 1 && c == 2)return 1;if (a == 0 && b == 2 && c == 1)return -1;if (a == 1 && b == 0 && c == 2)return -1;if (a == 1 && b == 2 && c == 0)return 1;if (a == 2 && b == 0 && c == 1)return 1;if (a == 2 && b == 1 && c == 0)return -1;return 0;};////////////////////////////////////////////////////////////////////////////////template <typename T>CCTK_ATTRIBUTE_ALWAYS_INLINE void fcalc(const PointDesc &p, const T &u,T &alpha, mat<T, 3, DN, DN> &K, T &rhs,T &psi) {DECLARE_CCTK_PARAMETERS;T alpha1 = 0;K = mat<T, 3, DN, DN>();for (int i = 0; i < npunctures; ++i) {const vec<T, 3, UP> x{posx[i], posy[i], posz[i]};const vec<T, 3, UP> P{momx[i], momy[i], momz[i]};const vec<T, 3, UP> S{amomx[i], amomy[i], amomz[i]};const T r = sqrt(sum<3>([&](int a) { return pow(p.X[a] - x(a), 2); }));const vec<T, 3, UP> n([&](int a) { return r < rmin ? 0 : x(a) / r; });alpha1 += mass[i] / (2 * fmax(rmin, r));K += mat<T, 3, DN, DN>([&](int a, int b) {return 3 / (2 * pow(fmax(rmin, r), 2)) *(P(a) * n(b) + P(b) * n(a) -(g(a, b) - n(a) * n(b)) *sum<3>([&](int c) { return P(c) * n(c); })) +3 / pow(fmax(rmin, r), 3) * sum<3>([&](int c, int d) {return epsilon(a, c, d) * S(c) * n(d) * n(b) +epsilon(b, c, d) * S(c) * n(d) * n(a);});});}alpha = 1 / alpha1;if (isinf1(alpha)) {// Infinitely far away, or there are no black holesrhs = 0;psi = 1;return;}if (alpha == 0) {assert(0); // handled by rmin// At a punctureK = mat<T, 3, DN, DN>();rhs = 0;psi = INFINITY;return;}const T beta = 1 / T(8) * pow(alpha, 7) *sum<3>([&](int a, int b) { return K(a, b) * K(a, b); });rhs = -beta * pow(1 + alpha * u, -7);psi = 1 / alpha + u;}template <typename T> T frhs(const PointDesc &p, const T &u) {T alpha;mat<T, 3, DN, DN> K;T rhs;T psi;fcalc(p, u, alpha, K, rhs, psi);return rhs;}// u = 1 + C / r + ...template <typename T> T fbnd(const PointDesc &p) { return 1; }template <typename T> T fpsi(const PointDesc &p, const T &u) {T alpha;mat<T, 3, DN, DN> K;T rhs;T psi;fcalc(p, u, alpha, K, rhs, psi);return psi;}template <typename T> mat<T, 3, DN, DN> fK(const PointDesc &p, const T &u) {T alpha;mat<T, 3, DN, DN> K;T rhs;T psi;fcalc(p, u, alpha, K, rhs, psi);return K;}////////////////////////////////////////////////////////////////////////////////extern "C" void Punctures_init(CCTK_ARGUMENTS) {DECLARE_CCTK_ARGUMENTS_Punctures_init;DECLARE_CCTK_PARAMETERS;const GF3D<CCTK_REAL, 0, 0, 0> usol_(cctkGH, usol);// Initialize all points (including ghosts)loop_all<0, 0, 0>(cctkGH, [&](const PointDesc &p) { usol_(p.I) = 1.0; });// Note: The boundary conditions are applied on the outermost layer// of the interior points, not on the boundary points.// Set boundary conditionsloop_all<0, 0, 0>(cctkGH, [&](const PointDesc &p) {if (cctk_lbnd[0] + p.i <= 1 || cctk_lbnd[0] + p.i >= cctk_gsh[0] - 1 ||cctk_lbnd[1] + p.j <= 1 || cctk_lbnd[1] + p.j >= cctk_gsh[1] - 1 ||cctk_lbnd[2] + p.k <= 1 || cctk_lbnd[2] + p.k >= cctk_gsh[2] - 1)usol_(p.I) = fbnd<CCTK_REAL>(p);});}extern "C" void Punctures_solve(CCTK_ARGUMENTS) {DECLARE_CCTK_ARGUMENTS_Punctures_solve;DECLARE_CCTK_PARAMETERS;const int max_iters = 100;for (int iter = 1;; ++iter) {CCTK_VINFO("Nonlinear iteration #%d", iter);// Set up RHSCallScheduleGroup(cctkGH, "Punctures_solve1");const int gi_sol = CCTK_GroupIndex("Punctures::usol");assert(gi_sol >= 0);const int gi_rhs = CCTK_GroupIndex("Punctures::urhs");assert(gi_rhs >= 0);const int gi_res = CCTK_GroupIndex("Punctures::ures");assert(gi_res >= 0);// linear solver accuracyconst CCTK_REAL reltol = 0.0;const CCTK_REAL abstol = 1.0e-10;CCTK_REAL res_initial, res_final;SolvePoisson(gi_sol, gi_rhs, gi_res, reltol, abstol, &res_initial,&res_final);CCTK_VINFO("Linear residual before solve: %g", double(res_initial));CCTK_VINFO("Linear residual after solve: %g", double(res_final));// Correct boundariesCallScheduleGroup(cctkGH, "Punctures_solve2");if (res_initial <= abstol) {CCTK_VINFO("Nonlinear iterations finished after %d iterations; accuracy ""goal reached",iter);break;}if (iter == max_iters) {CCTK_VWARN(CCTK_WARN_ALERT,"Nonlinear iterations finished after %d iterations; accuracy ""goal NOT reached",iter);break;}}}extern "C" void Punctures_rhs(CCTK_ARGUMENTS) {DECLARE_CCTK_ARGUMENTS_Punctures_rhs;DECLARE_CCTK_PARAMETERS;const GF3D<const CCTK_REAL, 0, 0, 0> usol_(cctkGH, usol);const GF3D<CCTK_REAL, 0, 0, 0> urhs_(cctkGH, urhs);// Set RHSloop_all<0, 0, 0>(cctkGH, [&](const PointDesc &p) { urhs_(p.I) = frhs(p, usol_(p.I)); });}extern "C" void Punctures_boundary(CCTK_ARGUMENTS) {DECLARE_CCTK_ARGUMENTS_Punctures_boundary;DECLARE_CCTK_PARAMETERS;const GF3D<CCTK_REAL, 0, 0, 0> usol_(cctkGH, usol);// Set boundary conditionsloop_all<0, 0, 0>(cctkGH, [&](const PointDesc &p) {if (cctk_lbnd[0] + p.i <= 1 || cctk_lbnd[0] + p.i >= cctk_gsh[0] - 1 ||cctk_lbnd[1] + p.j <= 1 || cctk_lbnd[1] + p.j >= cctk_gsh[1] - 1 ||cctk_lbnd[2] + p.k <= 1 || cctk_lbnd[2] + p.k >= cctk_gsh[2] - 1)usol_(p.I) = fbnd<CCTK_REAL>(p);});}extern "C" void Punctures_ADMBase(CCTK_ARGUMENTS) {DECLARE_CCTK_ARGUMENTS_Punctures_ADMBase;DECLARE_CCTK_PARAMETERS;const GF3D<const CCTK_REAL, 0, 0, 0> usol_(cctkGH, usol);const GF3D<CCTK_REAL, 0, 0, 0> gxx_(cctkGH, gxx);const GF3D<CCTK_REAL, 0, 0, 0> gxy_(cctkGH, gxy);const GF3D<CCTK_REAL, 0, 0, 0> gxz_(cctkGH, gxz);const GF3D<CCTK_REAL, 0, 0, 0> gyy_(cctkGH, gyy);const GF3D<CCTK_REAL, 0, 0, 0> gyz_(cctkGH, gyz);const GF3D<CCTK_REAL, 0, 0, 0> gzz_(cctkGH, gzz);const GF3D<CCTK_REAL, 0, 0, 0> Kxx_(cctkGH, kxx);const GF3D<CCTK_REAL, 0, 0, 0> Kxy_(cctkGH, kxy);const GF3D<CCTK_REAL, 0, 0, 0> Kxz_(cctkGH, kxz);const GF3D<CCTK_REAL, 0, 0, 0> Kyy_(cctkGH, kyy);const GF3D<CCTK_REAL, 0, 0, 0> Kyz_(cctkGH, kyz);const GF3D<CCTK_REAL, 0, 0, 0> Kzz_(cctkGH, kzz);const GF3D<CCTK_REAL, 0, 0, 0> alp_(cctkGH, alp);const GF3D<CCTK_REAL, 0, 0, 0> betax_(cctkGH, betax);const GF3D<CCTK_REAL, 0, 0, 0> betay_(cctkGH, betay);const GF3D<CCTK_REAL, 0, 0, 0> betaz_(cctkGH, betaz);const GF3D<CCTK_REAL, 0, 0, 0> dtalp_(cctkGH, dtalp);const GF3D<CCTK_REAL, 0, 0, 0> dtbetax_(cctkGH, dtbetax);const GF3D<CCTK_REAL, 0, 0, 0> dtbetay_(cctkGH, dtbetay);const GF3D<CCTK_REAL, 0, 0, 0> dtbetaz_(cctkGH, dtbetaz);loop_all<0, 0, 0>(cctkGH, [&](const PointDesc &p) {const CCTK_REAL psi = fpsi(p, usol_(p.I));const mat<CCTK_REAL, 3, DN, DN> K = fK(p, usol_(p.I));const mat<CCTK_REAL, 3, DN, DN> gph = pow(psi, 4) * g;const mat<CCTK_REAL, 3, DN, DN> Kph = pow(psi, -2) * K;gxx_(p.I) = gph(0, 0);gxy_(p.I) = gph(0, 1);gxz_(p.I) = gph(0, 2);gyy_(p.I) = gph(1, 1);gyz_(p.I) = gph(1, 2);gzz_(p.I) = gph(2, 2);Kxx_(p.I) = Kph(0, 0);Kxy_(p.I) = Kph(0, 1);Kxz_(p.I) = Kph(0, 2);Kyy_(p.I) = Kph(1, 1);Kyz_(p.I) = Kph(1, 2);Kzz_(p.I) = Kph(2, 2);alp_(p.I) = 1; // TODObetax_(p.I) = 0;betay_(p.I) = 0;betaz_(p.I) = 0;dtalp_(p.I) = 0;dtbetax_(p.I) = 0;dtbetay_(p.I) = 0;dtbetaz_(p.I) = 0;});}} // namespace Punctures