diff options
-rw-r--r-- | README | 13 | ||||
-rw-r--r-- | doc/documentation.tex | 144 | ||||
-rw-r--r-- | interface.ccl | 6 | ||||
-rw-r--r-- | param.ccl | 73 | ||||
-rw-r--r-- | schedule.ccl | 7 | ||||
-rw-r--r-- | src/CoordTransf.c | 159 | ||||
-rw-r--r-- | src/Equations.c | 186 | ||||
-rw-r--r-- | src/FuncAndJacobian.c | 744 | ||||
-rw-r--r-- | src/Newton.c | 435 | ||||
-rw-r--r-- | src/TP_utilities.c | 951 | ||||
-rw-r--r-- | src/TP_utilities.h | 91 | ||||
-rw-r--r-- | src/TwoPunctures.c | 128 | ||||
-rw-r--r-- | src/TwoPunctures.h | 95 | ||||
-rw-r--r-- | src/make.code.defn | 8 | ||||
-rw-r--r-- | test/twopunctures.par | 53 |
15 files changed, 3093 insertions, 0 deletions
@@ -0,0 +1,13 @@ +CVS info : $Header$ + +Cactus Code Thorn TwoPunctures +Thorn Author(s) : Marcus Ansorg <marcus.ansorg@aei.mpg.de> + : Erik Schnetter <schnetter@aei.mpg.de> +Thorn Maintainer(s) : Marcus Ansorg <marcus.ansorg@aei.mpg.de> + : Erik Schnetter <schnetter@aei.mpg.de> +-------------------------------------------------------------------------- + +Purpose of the thorn: + +Create initial for two puncture black holes using a single domain +spectral method. diff --git a/doc/documentation.tex b/doc/documentation.tex new file mode 100644 index 0000000..60ff50f --- /dev/null +++ b/doc/documentation.tex @@ -0,0 +1,144 @@ +% *======================================================================* +% Cactus Thorn template for ThornGuide documentation +% Author: Ian Kelley +% Date: Sun Jun 02, 2002 +% $Header$ +% +% Thorn documentation in the latex file doc/documentation.tex +% will be included in ThornGuides built with the Cactus make system. +% The scripts employed by the make system automatically include +% pages about variables, parameters and scheduling parsed from the +% relevant thorn CCL files. +% +% This template contains guidelines which help to assure that your +% documentation will be correctly added to ThornGuides. More +% information is available in the Cactus UsersGuide. +% +% Guidelines: +% - Do not change anything before the line +% % START CACTUS THORNGUIDE", +% except for filling in the title, author, date, etc. fields. +% - Each of these fields should only be on ONE line. +% - Author names should be separated with a \\ or a comma. +% - You can define your own macros, but they must appear after +% the START CACTUS THORNGUIDE line, and must not redefine standard +% latex commands. +% - To avoid name clashes with other thorns, 'labels', 'citations', +% 'references', and 'image' names should conform to the following +% convention: +% ARRANGEMENT_THORN_LABEL +% For example, an image wave.eps in the arrangement CactusWave and +% thorn WaveToyC should be renamed to CactusWave_WaveToyC_wave.eps +% - Graphics should only be included using the graphicx package. +% More specifically, with the "\includegraphics" command. Do +% not specify any graphic file extensions in your .tex file. This +% will allow us to create a PDF version of the ThornGuide +% via pdflatex. +% - References should be included with the latex "\bibitem" command. +% - Use \begin{abstract}...\end{abstract} instead of \abstract{...} +% - Do not use \appendix, instead include any appendices you need as +% standard sections. +% - For the benefit of our Perl scripts, and for future extensions, +% please use simple latex. +% +% *======================================================================* +% +% Example of including a graphic image: +% \begin{figure}[ht] +% \begin{center} +% \includegraphics[width=6cm]{MyArrangement_MyThorn_MyFigure} +% \end{center} +% \caption{Illustration of this and that} +% \label{MyArrangement_MyThorn_MyLabel} +% \end{figure} +% +% Example of using a label: +% \label{MyArrangement_MyThorn_MyLabel} +% +% Example of a citation: +% \cite{MyArrangement_MyThorn_Author99} +% +% Example of including a reference +% \bibitem{MyArrangement_MyThorn_Author99} +% {J. Author, {\em The Title of the Book, Journal, or periodical}, 1 (1999), +% 1--16. {\tt http://www.nowhere.com/}} +% +% *======================================================================* + +% If you are using CVS use this line to give version information +% $Header$ + +\documentclass{article} + +% Use the Cactus ThornGuide style file +% (Automatically used from Cactus distribution, if you have a +% thorn without the Cactus Flesh download this from the Cactus +% homepage at www.cactuscode.org) +\usepackage{../../../../doc/latex/cactus} + +\begin{document} + +% The author of the documentation +\author{Marcus Ansorg \textless marcus.ansorg@aei.mpg.de\textgreater \\ Erik Schnetter \textless schnetter@aei.mpg.de\textgreater} + +% The title of the document (not necessarily the name of the Thorn) +\title{} + +% the date your document was last changed, if your document is in CVS, +% please use: +% \date{$ $Date$ $} +\date{May 18 2004} + +\maketitle + +% Do not delete next line +% START CACTUS THORNGUIDE + +% Add all definitions used in this documentation here +% \def\mydef etc + +% Add an abstract for this thorn's documentation +\begin{abstract} + +\end{abstract} + +% The following sections are suggestive only. +% Remove them or add your own. + +\section{Introduction} + +\section{Physical System} + +\section{Numerical Implementation} + +\section{Using This Thorn} + +\subsection{Obtaining This Thorn} + +\subsection{Basic Usage} + +\subsection{Special Behaviour} + +\subsection{Interaction With Other Thorns} + +\subsection{Examples} + +\subsection{Support and Feedback} + +\section{History} + +\subsection{Thorn Source Code} + +\subsection{Thorn Documentation} + +\subsection{Acknowledgements} + + +\begin{thebibliography}{9} + +\end{thebibliography} + +% Do not delete next line +% END CACTUS THORNGUIDE + +\end{document} diff --git a/interface.ccl b/interface.ccl new file mode 100644 index 0000000..427ac85 --- /dev/null +++ b/interface.ccl @@ -0,0 +1,6 @@ +# Interface definition for thorn TwoPunctures +# $Header$ + +IMPLEMENTS: TwoPunctures + +INHERITS: ADMBase StaticConformal grid diff --git a/param.ccl b/param.ccl new file mode 100644 index 0000000..0d006df --- /dev/null +++ b/param.ccl @@ -0,0 +1,73 @@ +# Parameter definitions for thorn TwoPunctures +# $Header$ + +SHARES: ADMBase + +USES KEYWORD metric_type + +EXTENDS KEYWORD initial_data +{ + "twopunctures" :: "two puncture black holes" +} + + + +SHARES: StaticConformal + +USES KEYWORD conformal_storage + + + +PRIVATE: + +INT npoints_A "Number of coefficients in the compactified radial direction" +{ + 4:* :: "" +} 30 + +INT npoints_B "Number of coefficients in the angular direction" +{ + 4:* :: "" +} 30 + +INT npoints_phi "Number of coefficients in the phi direction" +{ + 4:*:2 :: "" +} 16 + + + +REAL par_b "x coordinate of the m+ puncture" +{ + (0.0:*) :: "" +} 1.0 + +REAL par_m_plus "mass of the m+ puncture" +{ + (0.0:* :: "" +} 1.0 + +REAL par_m_minus "mass of the m- puncture" +{ + (0.0:* :: "" +} 1.0 + +REAL par_P_plus[3] "momentum of the m+ puncture" +{ + (*:*) :: "" +} 0.0 + +REAL par_P_minus[3] "momentum of the m- puncture" +{ + (*:*) :: "" +} 0.0 + +REAL par_S_plus[3] "spin of the m+ puncture" +{ + (*:*) :: "" +} 0.0 + +REAL par_S_minus[3] "spin of the m- puncture" +{ + (*:*) :: "" +} 0.0 diff --git a/schedule.ccl b/schedule.ccl new file mode 100644 index 0000000..f625a55 --- /dev/null +++ b/schedule.ccl @@ -0,0 +1,7 @@ +# Schedule definitions for thorn TwoPunctures +# $Header$ + +SCHEDULE TwoPunctures IN ADMBase_InitialData +{ + LANG: C +} "Create puncture black hole initial data" diff --git a/src/CoordTransf.c b/src/CoordTransf.c new file mode 100644 index 0000000..5b2f31a --- /dev/null +++ b/src/CoordTransf.c @@ -0,0 +1,159 @@ +// TwoPunctures: File "CoordTransf.c" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ctype.h> +#include <time.h> +#include "cctk_Parameters.h" +#include "TP_utilities.h" +#include "TwoPunctures.h" + +//--------------------------------------------------------------- +void +AB_To_XR (int nvar, double A, double B, double *X, double *R, + derivs U) +// On Entrance: U.d0[]=U[]; U.d1[] =U[]_A; U.d2[] =U[]_B; U.d3[] =U[]_3; +// U.d11[]=U[]_AA; U.d12[]=U[]_AB; U.d13[]=U[]_A3; +// U.d22[]=U[]_BB; U.d23[]=U[]_B3; U.d33[]=U[]_33; +// At Exit: U.d0[]=U[]; U.d1[] =U[]_X; U.d2[] =U[]_R; U.d3[] =U[]_3; +// U.d11[]=U[]_XX; U.d12[]=U[]_XR; U.d13[]=U[]_X3; +// U.d22[]=U[]_RR; U.d23[]=U[]_R3; U.d33[]=U[]_33; +{ + DECLARE_CCTK_PARAMETERS; + double At = 0.5 * (A + 1), A_X, A_XX, B_R, B_RR; + int ivar; + + *X = 2 * atanh (At); + *R = Pih + 2 * atan (B); + + A_X = 1 - At * At; + A_XX = -At * A_X; + B_R = 0.5 * (1 + B * B); + B_RR = B * B_R; + + for (ivar = 0; ivar < nvar; ivar++) + { + U.d11[ivar] = A_X * A_X * U.d11[ivar] + A_XX * U.d1[ivar]; + U.d12[ivar] = A_X * B_R * U.d12[ivar]; + U.d13[ivar] = A_X * U.d13[ivar]; + U.d22[ivar] = B_R * B_R * U.d22[ivar] + B_RR * U.d2[ivar]; + U.d23[ivar] = B_R * U.d23[ivar]; + U.d1[ivar] = A_X * U.d1[ivar]; + U.d2[ivar] = B_R * U.d2[ivar]; + } +} + +//--------------------------------------------------------------- +void +C_To_c (int nvar, double X, double R, double *x, double *r, + derivs U) +// On Entrance: U.d0[]=U[]; U.d1[] =U[]_X; U.d2[] =U[]_R; U.d3[] =U[]_3; +// U.d11[]=U[]_XX; U.d12[]=U[]_XR; U.d13[]=U[]_X3; +// U.d22[]=U[]_RR; U.d23[]=U[]_R3; U.d33[]=U[]_33; +// At Exit: U.d0[]=U[]; U.d1[] =U[]_x; U.d2[] =U[]_r; U.d3[] =U[]_3; +// U.d11[]=U[]_xx; U.d12[]=U[]_xr; U.d13[]=U[]_x3; +// U.d22[]=U[]_rr; U.d23[]=U[]_r3; U.d33[]=U[]_33; +{ + DECLARE_CCTK_PARAMETERS; + double C_c2, U_cb, U_CB; + dcomplex C, C_c, C_cc, c, c_C, c_CC, U_c, U_cc, U_C, U_CC, One = + Complex (1., 0.); + int ivar; + + C.r = X; + C.i = R; + + c = RCmul (par_b, Ccosh (C)); // c=b*cosh(C) + c_C = RCmul (par_b, Csinh (C)); + c_CC = c; + + C_c = Cdiv (One, c_C); + C_cc = RCmul (-1., Cmul (Cmul (C_c, C_c), Cmul (C_c, c_CC))); + C_c2 = C_c.r * C_c.r + C_c.i * C_c.i; + + for (ivar = 0; ivar < nvar; ivar++) + { + // U_C = 0.5*(U_X3-i*U_R3) + // U_c = U_C*C_c = 0.5*(U_x3-i*U_r3) + U_C.r = 0.5 * U.d13[ivar]; + U_C.i = -0.5 * U.d23[ivar]; + U_c = Cmul (U_C, C_c); + U.d13[ivar] = 2. * U_c.r; + U.d23[ivar] = -2. * U_c.i; + + // U_C = 0.5*(U_X-i*U_R) + // U_c = U_C*C_c = 0.5*(U_x-i*U_r) + U_C.r = 0.5 * U.d1[ivar]; + U_C.i = -0.5 * U.d2[ivar]; + U_c = Cmul (U_C, C_c); + U.d1[ivar] = 2. * U_c.r; + U.d2[ivar] = -2. * U_c.i; + + // U_CC = 0.25*(U_XX-U_RR-2*i*U_XR) + // U_CB = d^2(U)/(dC*d\bar{C}) = 0.25*(U_XX+U_RR) + U_CC.r = 0.25 * (U.d11[ivar] - U.d22[ivar]); + U_CC.i = -0.5 * U.d12[ivar]; + U_CB = 0.25 * (U.d11[ivar] + U.d22[ivar]); + + // U_cc = C_cc*U_C+(C_c)^2*U_CC + U_cb = U_CB * C_c2; + U_cc = Cadd (Cmul (C_cc, U_C), Cmul (Cmul (C_c, C_c), U_CC)); + + // U_xx = 2*(U_cb+Re[U_cc]) + // U_rr = 2*(U_cb-Re[U_cc]) + // U_rx = -2*Im[U_cc] + U.d11[ivar] = 2 * (U_cb + U_cc.r); + U.d22[ivar] = 2 * (U_cb - U_cc.r); + U.d12[ivar] = -2 * U_cc.i; + } + + *x = c.r; + *r = c.i; +} + +//--------------------------------------------------------------- +void +rx3_To_xyz (int nvar, double x, double r, double phi, + double *y, double *z, derivs U) +// On Entrance: U.d0[]=U[]; U.d1[] =U[]_x; U.d2[] =U[]_r; U.d3[] =U[]_3; +// U.d11[]=U[]_xx; U.d12[]=U[]_xr; U.d13[]=U[]_x3; +// U.d22[]=U[]_rr; U.d23[]=U[]_r3; U.d33[]=U[]_33; +// At Exit: U.d0[]=U[]; U.d1[] =U[]_x; U.d2[] =U[]_y; U.dz[] =U[]_z; +// U.d11[]=U[]_xx; U.d12[]=U[]_xy; U.d1z[]=U[]_xz; +// U.d22[]=U[]_yy; U.d2z[]=U[]_yz; U.dzz[]=U[]_zz; +{ + int jvar; + double + sin_phi = sin (phi), + cos_phi = cos (phi), + sin2_phi = sin_phi * sin_phi, + cos2_phi = cos_phi * cos_phi, + sin_2phi = 2 * sin_phi * cos_phi, + cos_2phi = cos2_phi - sin2_phi, r_inv = 1 / r, r_inv2 = r_inv * r_inv; + + *y = r * cos_phi; + *z = r * sin_phi; + + for (jvar = 0; jvar < nvar; jvar++) + { + double U_x = U.d1[jvar], U_r = U.d2[jvar], U_3 = U.d3[jvar], + U_xx = U.d11[jvar], U_xr = U.d12[jvar], U_x3 = U.d13[jvar], + U_rr = U.d22[jvar], U_r3 = U.d23[jvar], U_33 = U.d33[jvar]; + U.d1[jvar] = U_x; // U_x + U.d2[jvar] = U_r * cos_phi - U_3 * r_inv * sin_phi; // U_y + U.d3[jvar] = U_r * sin_phi + U_3 * r_inv * cos_phi; // U_z + U.d11[jvar] = U_xx; // U_xx + U.d12[jvar] = U_xr * cos_phi - U_x3 * r_inv * sin_phi; // U_xy + U.d13[jvar] = U_xr * sin_phi + U_x3 * r_inv * cos_phi; // U_xz + U.d22[jvar] = U_rr * cos2_phi + r_inv2 * sin2_phi * (U_33 + r * U_r) // U_yy + + sin_2phi * r_inv2 * (U_3 - r * U_r3); + U.d23[jvar] = 0.5 * sin_2phi * (U_rr - r_inv * U_r - r_inv2 * U_33) // U_yz + - cos_2phi * r_inv2 * (U_3 - r * U_r3); + U.d33[jvar] = U_rr * sin2_phi + r_inv2 * cos2_phi * (U_33 + r * U_r) // U_zz + - sin_2phi * r_inv2 * (U_3 - r * U_r3); + } +} + +//--------------------------------------------------------------- diff --git a/src/Equations.c b/src/Equations.c new file mode 100644 index 0000000..b461d4e --- /dev/null +++ b/src/Equations.c @@ -0,0 +1,186 @@ +// TwoPunctures: File "Equations.c" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ctype.h> +#include "cctk_Parameters.h" +#include "TP_utilities.h" +#include "TwoPunctures.h" + +// U.d0[ivar] = U[ivar]; (ivar = 0..nvar-1) +// U.d1[ivar] = U[ivar]_x; +// U.d2[ivar] = U[ivar]_y; +// U.d3[ivar] = U[ivar]_z; +// U.d11[ivar] = U[ivar]_xx; +// U.d12[ivar] = U[ivar]_xy; +// U.d13[ivar] = U[ivar]_xz; +// U.d22[ivar] = U[ivar]_yy; +// U.d23[ivar] = U[ivar]_yz; +// U.d33[ivar] = U[ivar]_zz; + +double +BY_KKofxyz (double x, double y, double z) +{ + DECLARE_CCTK_PARAMETERS; + int i, j; + double r_plus, r2_plus, r3_plus, r_minus, r2_minus, r3_minus, np_Pp, nm_Pm, + Aij, AijAij, n_plus[3], n_minus[3], np_Sp[3], nm_Sm[3]; + + r2_plus = (x - par_b) * (x - par_b) + y * y + z * z; + r2_minus = (x + par_b) * (x + par_b) + y * y + z * z; + r_plus = sqrt (r2_plus); + r_minus = sqrt (r2_minus); + r3_plus = r_plus * r2_plus; + r3_minus = r_minus * r2_minus; + + n_plus[0] = (x - par_b) / r_plus; + n_minus[0] = (x + par_b) / r_minus; + n_plus[1] = y / r_plus; + n_minus[1] = y / r_minus; + n_plus[2] = z / r_plus; + n_minus[2] = z / r_minus; + + // dot product: np_Pp = (n_+).(P_+); nm_Pm = (n_-).(P_-) + np_Pp = 0; + nm_Pm = 0; + for (i = 0; i < 3; i++) + { + np_Pp += n_plus[i] * par_P_plus[i]; + nm_Pm += n_minus[i] * par_P_minus[i]; + } + // cross product: np_Sp[i] = [(n_+) x (S_+)]_i; nm_Sm[i] = [(n_-) x (S_-)]_i + np_Sp[0] = n_plus[1] * par_S_plus[2] - n_plus[2] * par_S_plus[1]; + np_Sp[1] = n_plus[2] * par_S_plus[0] - n_plus[0] * par_S_plus[2]; + np_Sp[2] = n_plus[0] * par_S_plus[1] - n_plus[1] * par_S_plus[0]; + nm_Sm[0] = n_minus[1] * par_S_minus[2] - n_minus[2] * par_S_minus[1]; + nm_Sm[1] = n_minus[2] * par_S_minus[0] - n_minus[0] * par_S_minus[2]; + nm_Sm[2] = n_minus[0] * par_S_minus[1] - n_minus[1] * par_S_minus[0]; + AijAij = 0; + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { // Bowen-York-Curvature : + Aij = + +1.5 * (par_P_plus[i] * n_plus[j] + par_P_plus[j] * n_plus[i] + + np_Pp * n_plus[i] * n_plus[j]) / r2_plus + + 1.5 * (par_P_minus[i] * n_minus[j] + par_P_minus[j] * n_minus[i] + + nm_Pm * n_minus[i] * n_minus[j]) / r2_minus + - 3.0 * (np_Sp[i] * n_plus[j] + np_Sp[j] * n_plus[j]) / r3_plus + - 3.0 * (nm_Sm[i] * n_minus[j] + nm_Sm[i] * n_minus[j]) / r3_minus; + if (i == j) + Aij -= +1.5 * (np_Pp / r2_plus + nm_Pm / r2_minus); + AijAij += Aij * Aij; + } + } + + return AijAij; +} + +void +BY_Aijofxyz (double x, double y, double z, double Aij[3][3]) +{ + // Aij is a one-dimensional array with 9 elements + DECLARE_CCTK_PARAMETERS; + int i, j; + double r_plus, r2_plus, r3_plus, r_minus, r2_minus, r3_minus, np_Pp, nm_Pm, + n_plus[3], n_minus[3], np_Sp[3], nm_Sm[3]; + + r2_plus = (x - par_b) * (x - par_b) + y * y + z * z; + r2_minus = (x + par_b) * (x + par_b) + y * y + z * z; + r_plus = sqrt (r2_plus); + r_minus = sqrt (r2_minus); + r3_plus = r_plus * r2_plus; + r3_minus = r_minus * r2_minus; + + n_plus[0] = (x - par_b) / r_plus; + n_minus[0] = (x + par_b) / r_minus; + n_plus[1] = y / r_plus; + n_minus[1] = y / r_minus; + n_plus[2] = z / r_plus; + n_minus[2] = z / r_minus; + + // dot product: np_Pp = (n_+).(P_+); nm_Pm = (n_-).(P_-) + np_Pp = 0; + nm_Pm = 0; + for (i = 0; i < 3; i++) + { + np_Pp += n_plus[i] * par_P_plus[i]; + nm_Pm += n_minus[i] * par_P_minus[i]; + } + // cross product: np_Sp[i] = [(n_+) x (S_+)]_i; nm_Sm[i] = [(n_-) x (S_-)]_i + np_Sp[0] = n_plus[1] * par_S_plus[2] - n_plus[2] * par_S_plus[1]; + np_Sp[1] = n_plus[2] * par_S_plus[0] - n_plus[0] * par_S_plus[2]; + np_Sp[2] = n_plus[0] * par_S_plus[1] - n_plus[1] * par_S_plus[0]; + nm_Sm[0] = n_minus[1] * par_S_minus[2] - n_minus[2] * par_S_minus[1]; + nm_Sm[1] = n_minus[2] * par_S_minus[0] - n_minus[0] * par_S_minus[2]; + nm_Sm[2] = n_minus[0] * par_S_minus[1] - n_minus[1] * par_S_minus[0]; + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { // Bowen-York-Curvature : + Aij[i][j] = + +1.5 * (par_P_plus[i] * n_plus[j] + par_P_plus[j] * n_plus[i] + + np_Pp * n_plus[i] * n_plus[j]) / r2_plus + + 1.5 * (par_P_minus[i] * n_minus[j] + par_P_minus[j] * n_minus[i] + + nm_Pm * n_minus[i] * n_minus[j]) / r2_minus + - 3.0 * (np_Sp[i] * n_plus[j] + np_Sp[j] * n_plus[j]) / r3_plus + - 3.0 * (nm_Sm[i] * n_minus[j] + nm_Sm[i] * n_minus[j]) / r3_minus; + if (i == j) + Aij[i][j] -= +1.5 * (np_Pp / r2_plus + nm_Pm / r2_minus); + } + } +} + +//--------------------------------------------------------------- +//******* Nonlinear Equations ********** +//--------------------------------------------------------------- +void +NonLinEquations (double A, double B, double X, double R, + double x, double r, double phi, + double y, double z, derivs U, double *values) +{ + DECLARE_CCTK_PARAMETERS; + double r_plus, r_minus, psi, psi2, psi4, psi7; + double mu; + + r_plus = sqrt ((x - par_b) * (x - par_b) + y * y + z * z); + r_minus = sqrt ((x + par_b) * (x + par_b) + y * y + z * z); + + psi = + 1. + 0.5 * par_m_plus / r_plus + 0.5 * par_m_minus / r_minus + U.d0[0]; + psi2 = psi * psi; + psi4 = psi2 * psi2; + psi7 = psi * psi2 * psi4; + + values[0] = + U.d11[0] + U.d22[0] + U.d33[0] + 0.125 * BY_KKofxyz (x, y, z) / psi7; + +} + +//--------------------------------------------------------------- +//******* Linear Equations ********** +//--------------------------------------------------------------- +void +LinEquations (double A, double B, double X, double R, + double x, double r, double phi, + double y, double z, derivs dU, derivs U, double *values) +{ + DECLARE_CCTK_PARAMETERS; + double r_plus, r_minus, psi, psi2, psi4, psi8; + + r_plus = sqrt ((x - par_b) * (x - par_b) + y * y + z * z); + r_minus = sqrt ((x + par_b) * (x + par_b) + y * y + z * z); + + psi = + 1. + 0.5 * par_m_plus / r_plus + 0.5 * par_m_minus / r_minus + U.d0[0]; + psi2 = psi * psi; + psi4 = psi2 * psi2; + psi8 = psi4 * psi4; + + values[0] = dU.d11[0] + dU.d22[0] + dU.d33[0] + - 0.875 * BY_KKofxyz (x, y, z) / psi8 * dU.d0[0]; +} + +//--------------------------------------------------------------- diff --git a/src/FuncAndJacobian.c b/src/FuncAndJacobian.c new file mode 100644 index 0000000..568ac13 --- /dev/null +++ b/src/FuncAndJacobian.c @@ -0,0 +1,744 @@ +// TwoPunctures: File "FuncAndJacobian.c" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ctype.h> +#include <time.h> +#include "cctk_Parameters.h" +#include "TP_utilities.h" +#include "TwoPunctures.h" + +#define FAC sin(al)*sin(be)*sin(al)*sin(be)*sin(al)*sin(be) +//#define FAC sin(al)*sin(be)*sin(al)*sin(be) +//#define FAC 1 + +// ------------------------------------------------------------------------------- +int +Index (int ivar, int i, int j, int k, int nvar, int n1, int n2, int n3) +{ + int i1 = i, j1 = j, k1 = k; + + if (i1 < 0) + i1 = -(i1 + 1); + if (i1 >= n1) + i1 = 2 * n1 - (i1 + 1); + + if (j1 < 0) + j1 = -(j1 + 1); + if (j1 >= n2) + j1 = 2 * n2 - (j1 + 1); + + if (k1 < 0) + k1 = k1 + n3; + if (k1 >= n3) + k1 = k1 - n3; + + return ivar + nvar * (i1 + n1 * (j1 + n2 * k1)); +} + +// ------------------------------------------------------------------------------- +void +allocate_derivs (derivs * v, int n) +{ + int m = n - 1; + (*v).d0 = dvector (0, m); + (*v).d1 = dvector (0, m); + (*v).d2 = dvector (0, m); + (*v).d3 = dvector (0, m); + (*v).d11 = dvector (0, m); + (*v).d12 = dvector (0, m); + (*v).d13 = dvector (0, m); + (*v).d22 = dvector (0, m); + (*v).d23 = dvector (0, m); + (*v).d33 = dvector (0, m); +} + +// ------------------------------------------------------------------------------- +void +free_derivs (derivs * v, int n) +{ + int m = n - 1; + free_dvector ((*v).d0, 0, m); + free_dvector ((*v).d1, 0, m); + free_dvector ((*v).d2, 0, m); + free_dvector ((*v).d3, 0, m); + free_dvector ((*v).d11, 0, m); + free_dvector ((*v).d12, 0, m); + free_dvector ((*v).d13, 0, m); + free_dvector ((*v).d22, 0, m); + free_dvector ((*v).d23, 0, m); + free_dvector ((*v).d33, 0, m); +} + +// ------------------------------------------------------------------------------- +void +Derivatives_AB3 (int nvar, int n1, int n2, int n3, derivs v) +{ + int i, j, k, ivar, N, *indx; + double *p, *dp, *d2p, *q, *dq, *r, *dr; + + N = maximum3 (n1, n2, n3); + p = dvector (0, N); + dp = dvector (0, N); + d2p = dvector (0, N); + q = dvector (0, N); + dq = dvector (0, N); + r = dvector (0, N); + dr = dvector (0, N); + indx = ivector (0, N); + + for (ivar = 0; ivar < nvar; ivar++) + { + for (k = 0; k < n3; k++) + { // Calculation of Derivatives w.r.t. A-Dir. + for (j = 0; j < n2; j++) + { // (Chebyshev_Zeros) + for (i = 0; i < n1; i++) + { + indx[i] = Index (ivar, i, j, k, nvar, n1, n2, n3); + p[i] = v.d0[indx[i]]; + } + chebft_Zeros (p, n1, 0); + chder (p, dp, n1); + chder (dp, d2p, n1); + chebft_Zeros (dp, n1, 1); + chebft_Zeros (d2p, n1, 1); + for (i = 0; i < n1; i++) + { + v.d1[indx[i]] = dp[i]; + v.d11[indx[i]] = d2p[i]; + } + } + } + for (k = 0; k < n3; k++) + { // Calculation of Derivatives w.r.t. A-Dir. + for (i = 0; i < n1; i++) + { // (Chebyshev_Zeros) + for (j = 0; j < n2; j++) + { + indx[j] = Index (ivar, i, j, k, nvar, n1, n2, n3); + p[j] = v.d0[indx[j]]; + q[j] = v.d1[indx[j]]; + } + chebft_Zeros (p, n2, 0); + chebft_Zeros (q, n2, 0); + chder (p, dp, n2); + chder (dp, d2p, n2); + chder (q, dq, n2); + chebft_Zeros (dp, n2, 1); + chebft_Zeros (d2p, n2, 1); + chebft_Zeros (dq, n2, 1); + for (j = 0; j < n2; j++) + { + v.d2[indx[j]] = dp[j]; + v.d22[indx[j]] = d2p[j]; + v.d12[indx[j]] = dq[j]; + } + } + } + for (i = 0; i < n1; i++) + { // Calculation of Derivatives w.r.t. phi-Dir. (Fourier) + for (j = 0; j < n2; j++) + { + for (k = 0; k < n3; k++) + { + indx[k] = Index (ivar, i, j, k, nvar, n1, n2, n3); + p[k] = v.d0[indx[k]]; + q[k] = v.d1[indx[k]]; + r[k] = v.d2[indx[k]]; + } + fourft (p, n3, 0); + fourder (p, dp, n3); + fourder2 (p, d2p, n3); + fourft (dp, n3, 1); + fourft (d2p, n3, 1); + fourft (q, n3, 0); + fourder (q, dq, n3); + fourft (dq, n3, 1); + fourft (r, n3, 0); + fourder (r, dr, n3); + fourft (dr, n3, 1); + for (k = 0; k < n3; k++) + { + v.d3[indx[k]] = dp[k]; + v.d33[indx[k]] = d2p[k]; + v.d13[indx[k]] = dq[k]; + v.d23[indx[k]] = dr[k]; + } + } + } + } + free_dvector (p, 0, N); + free_dvector (dp, 0, N); + free_dvector (d2p, 0, N); + free_dvector (q, 0, N); + free_dvector (dq, 0, N); + free_dvector (r, 0, N); + free_dvector (dr, 0, N); + free_ivector (indx, 0, N); +} + +// ------------------------------------------------------------------------------- +void +F_of_v (int nvar, int n1, int n2, int n3, derivs v, double *F, + derivs u) +{ // Calculates the left hand sides of the non-linear equations F_m(v_n)=0 + // and the function u (u.d0[]) as well as its derivatives + // (u.d1[], u.d2[], u.d3[], u.d11[], u.d12[], u.d13[], u.d22[], u.d23[], u.d33[]) + // at interior points and at the boundaries "+/-" + int i, j, k, ivar, indx; + double al, be, A, B, X, R, x, r, phi, y, z, Am1, *values; + derivs U; + + values = dvector (0, nvar - 1); + allocate_derivs (&U, nvar); + + Derivatives_AB3 (nvar, n1, n2, n3, v); + + for (i = 0; i < n1; i++) + { + for (j = 0; j < n2; j++) + { + for (k = 0; k < n3; k++) + { + + al = Pih * (2 * i + 1) / n1; + A = -cos (al); + be = Pih * (2 * j + 1) / n2; + B = -cos (be); + phi = 2. * Pi * k / n3; + + Am1 = A - 1; + for (ivar = 0; ivar < nvar; ivar++) + { + indx = Index (ivar, i, j, k, nvar, n1, n2, n3); + U.d0[ivar] = Am1 * v.d0[indx]; // U + U.d1[ivar] = v.d0[indx] + Am1 * v.d1[indx]; // U_A + U.d2[ivar] = Am1 * v.d2[indx]; // U_B + U.d3[ivar] = Am1 * v.d3[indx]; // U_3 + U.d11[ivar] = 2 * v.d1[indx] + Am1 * v.d11[indx]; // U_AA + U.d12[ivar] = v.d2[indx] + Am1 * v.d12[indx]; // U_AB + U.d13[ivar] = v.d3[indx] + Am1 * v.d13[indx]; // U_AB + U.d22[ivar] = Am1 * v.d22[indx]; // U_BB + U.d23[ivar] = Am1 * v.d23[indx]; // U_B3 + U.d33[ivar] = Am1 * v.d33[indx]; // U_33 + } + // Calculation of (X,R) and + // (U_X, U_R, U_3, U_XX, U_XR, U_X3, U_RR, U_R3, U_33) + AB_To_XR (nvar, A, B, &X, &R, U); + // Calculation of (x,r) and + // (U, U_x, U_r, U_3, U_xx, U_xr, U_x3, U_rr, U_r3, U_33) + C_To_c (nvar, X, R, &x, &r, U); + // Calculation of (y,z) and + // (U, U_x, U_y, U_z, U_xx, U_xy, U_xz, U_yy, U_yz, U_zz) + rx3_To_xyz (nvar, x, r, phi, &y, &z, U); + NonLinEquations (A, B, X, R, x, r, phi, y, z, U, values); + for (ivar = 0; ivar < nvar; ivar++) + { + indx = Index (ivar, i, j, k, nvar, n1, n2, n3); + F[indx] = values[ivar] * FAC; + u.d0[indx] = U.d0[ivar]; // U + u.d1[indx] = U.d1[ivar]; // U_x + u.d2[indx] = U.d2[ivar]; // U_y + u.d3[indx] = U.d3[ivar]; // U_z + u.d11[indx] = U.d11[ivar]; // U_xx + u.d12[indx] = U.d12[ivar]; // U_xy + u.d13[indx] = U.d13[ivar]; // U_xz + u.d22[indx] = U.d22[ivar]; // U_yy + u.d23[indx] = U.d23[ivar]; // U_yz + u.d33[indx] = U.d33[ivar]; // U_zz + } + } + } + } + free_dvector (values, 0, nvar - 1); + free_derivs (&U, nvar); +} + +// ------------------------------------------------------------------------------- +void +J_times_dv (int nvar, int n1, int n2, int n3, derivs dv, + double *Jdv, derivs u) +{ // Calculates the left hand sides of the non-linear equations F_m(v_n)=0 + // and the function u (u.d0[]) as well as its derivatives + // (u.d1[], u.d2[], u.d3[], u.d11[], u.d12[], u.d13[], u.d22[], u.d23[], u.d33[]) + // at interior points and at the boundaries "+/-" + DECLARE_CCTK_PARAMETERS; + int i, j, k, ivar, indx; + double al, be, A, B, X, R, x, r, phi, y, z, Am1, *values; + derivs dU, U; + + + values = dvector (0, nvar - 1); + allocate_derivs (&dU, nvar); + allocate_derivs (&U, nvar); + + Derivatives_AB3 (nvar, n1, n2, n3, dv); + + for (i = 0; i < n1; i++) + { + for (j = 0; j < n2; j++) + { + for (k = 0; k < n3; k++) + { + + al = Pih * (2 * i + 1) / n1; + A = -cos (al); + be = Pih * (2 * j + 1) / n2; + B = -cos (be); + phi = 2. * Pi * k / n3; + + Am1 = A - 1; + for (ivar = 0; ivar < nvar; ivar++) + { + indx = Index (ivar, i, j, k, nvar, n1, n2, n3); + dU.d0[ivar] = Am1 * dv.d0[indx]; // dU + dU.d1[ivar] = dv.d0[indx] + Am1 * dv.d1[indx]; // dU_A + dU.d2[ivar] = Am1 * dv.d2[indx]; // dU_B + dU.d3[ivar] = Am1 * dv.d3[indx]; // dU_3 + dU.d11[ivar] = 2 * dv.d1[indx] + Am1 * dv.d11[indx]; // dU_AA + dU.d12[ivar] = dv.d2[indx] + Am1 * dv.d12[indx]; // dU_AB + dU.d13[ivar] = dv.d3[indx] + Am1 * dv.d13[indx]; // dU_AB + dU.d22[ivar] = Am1 * dv.d22[indx]; // dU_BB + dU.d23[ivar] = Am1 * dv.d23[indx]; // dU_B3 + dU.d33[ivar] = Am1 * dv.d33[indx]; // dU_33 + U.d0[ivar] = u.d0[indx]; // U + U.d1[ivar] = u.d1[indx]; // U_x + U.d2[ivar] = u.d2[indx]; // U_y + U.d3[ivar] = u.d3[indx]; // U_z + U.d11[ivar] = u.d11[indx]; // U_xx + U.d12[ivar] = u.d12[indx]; // U_xy + U.d13[ivar] = u.d13[indx]; // U_xz + U.d22[ivar] = u.d22[indx]; // U_yy + U.d23[ivar] = u.d23[indx]; // U_yz + U.d33[ivar] = u.d33[indx]; // U_zz + } + // Calculation of (X,R) and + // (dU_X, dU_R, dU_3, dU_XX, dU_XR, dU_X3, dU_RR, dU_R3, dU_33) + AB_To_XR (nvar, A, B, &X, &R, dU); + // Calculation of (x,r) and + // (dU, dU_x, dU_r, dU_3, dU_xx, dU_xr, dU_x3, dU_rr, dU_r3, dU_33) + C_To_c (nvar, X, R, &x, &r, dU); + // Calculation of (y,z) and + // (dU, dU_x, dU_y, dU_z, dU_xx, dU_xy, dU_xz, dU_yy, dU_yz, dU_zz) + rx3_To_xyz (nvar, x, r, phi, &y, &z, dU); + LinEquations (A, B, X, R, x, r, phi, y, z, dU, U, values); + for (ivar = 0; ivar < nvar; ivar++) + { + indx = Index (ivar, i, j, k, nvar, n1, n2, n3); + Jdv[indx] = values[ivar] * FAC; + } + } + } + } + free_dvector (values, 0, nvar - 1); + free_derivs (&dU, nvar); + free_derivs (&U, nvar); +} + +// ------------------------------------------------------------------------------- +void +JFD_times_dv (int i, int j, int k, int nvar, int n1, int n2, + int n3, derivs dv, derivs u, double *values) +{ // Calculates rows of the vector 'J(FD)*dv'. + // First row to be calculated: row = Index(0, i, j, k; nvar, n1, n2, n3) + // Last row to be calculated: row = Index(nvar-1, i, j, k; nvar, n1, n2, n3) + // These rows are stored in the vector JFDdv[0] ... JFDdv[nvar-1]. + DECLARE_CCTK_PARAMETERS; + int ivar, indx; + double al, be, A, B, X, R, x, r, phi, y, z, Am1; + double sin_al, sin_al_i1, sin_al_i2, sin_al_i3, cos_al; + double sin_be, sin_be_i1, sin_be_i2, sin_be_i3, cos_be; + double dV0, dV1, dV2, dV3, dV11, dV12, dV13, dV22, dV23, dV33, + ha, ga, ga2, hb, gb, gb2, hp, gp, gp2, gagb, gagp, gbgp; + derivs dU, U; + + allocate_derivs (&dU, nvar); + allocate_derivs (&U, nvar); + + if (k < 0) + k = k + n3; + if (k >= n3) + k = k - n3; + + ha = Pi / n1; // ha: Stepsize with respect to (al) + al = ha * (i + 0.5); + A = -cos (al); + ga = 1 / ha; + ga2 = ga * ga; + + hb = Pi / n2; // hb: Stepsize with respect to (be) + be = hb * (j + 0.5); + B = -cos (be); + gb = 1 / hb; + gb2 = gb * gb; + gagb = ga * gb; + + hp = 2 * Pi / n3; // hp: Stepsize with respect to (phi) + phi = hp * j; + gp = 1 / hp; + gp2 = gp * gp; + gagp = ga * gp; + gbgp = gb * gp; + + + sin_al = sin (al); + sin_be = sin (be); + sin_al_i1 = 1 / sin_al; + sin_be_i1 = 1 / sin_be; + sin_al_i2 = sin_al_i1 * sin_al_i1; + sin_be_i2 = sin_be_i1 * sin_be_i1; + sin_al_i3 = sin_al_i1 * sin_al_i2; + sin_be_i3 = sin_be_i1 * sin_be_i2; + cos_al = -A; + cos_be = -B; + + Am1 = A - 1; + for (ivar = 0; ivar < nvar; ivar++) + { + int iccc = Index (ivar, i, j, k, nvar, n1, n2, n3), + ipcc = Index (ivar, i + 1, j, k, nvar, n1, n2, n3), + imcc = Index (ivar, i - 1, j, k, nvar, n1, n2, n3), + icpc = Index (ivar, i, j + 1, k, nvar, n1, n2, n3), + icmc = Index (ivar, i, j - 1, k, nvar, n1, n2, n3), + iccp = Index (ivar, i, j, k + 1, nvar, n1, n2, n3), + iccm = Index (ivar, i, j, k - 1, nvar, n1, n2, n3), + icpp = Index (ivar, i, j + 1, k + 1, nvar, n1, n2, n3), + icmp = Index (ivar, i, j - 1, k + 1, nvar, n1, n2, n3), + icpm = Index (ivar, i, j + 1, k - 1, nvar, n1, n2, n3), + icmm = Index (ivar, i, j - 1, k - 1, nvar, n1, n2, n3), + ipcp = Index (ivar, i + 1, j, k + 1, nvar, n1, n2, n3), + imcp = Index (ivar, i - 1, j, k + 1, nvar, n1, n2, n3), + ipcm = Index (ivar, i + 1, j, k - 1, nvar, n1, n2, n3), + imcm = Index (ivar, i - 1, j, k - 1, nvar, n1, n2, n3), + ippc = Index (ivar, i + 1, j + 1, k, nvar, n1, n2, n3), + impc = Index (ivar, i - 1, j + 1, k, nvar, n1, n2, n3), + ipmc = Index (ivar, i + 1, j - 1, k, nvar, n1, n2, n3), + immc = Index (ivar, i - 1, j - 1, k, nvar, n1, n2, n3); + // Derivatives of (dv) w.r.t. (al,be,phi): + dV0 = dv.d0[iccc]; + dV1 = 0.5 * ga * (dv.d0[ipcc] - dv.d0[imcc]); + dV2 = 0.5 * gb * (dv.d0[icpc] - dv.d0[icmc]); + dV3 = 0.5 * gp * (dv.d0[iccp] - dv.d0[iccm]); + dV11 = ga2 * (dv.d0[ipcc] + dv.d0[imcc] - 2 * dv.d0[iccc]); + dV22 = gb2 * (dv.d0[icpc] + dv.d0[icmc] - 2 * dv.d0[iccc]); + dV33 = gp2 * (dv.d0[iccp] + dv.d0[iccm] - 2 * dv.d0[iccc]); + dV12 = + 0.25 * gagb * (dv.d0[ippc] - dv.d0[ipmc] + dv.d0[immc] - dv.d0[impc]); + dV13 = + 0.25 * gagp * (dv.d0[ipcp] - dv.d0[imcp] + dv.d0[imcm] - dv.d0[ipcm]); + dV23 = + 0.25 * gbgp * (dv.d0[icpp] - dv.d0[icpm] + dv.d0[icmm] - dv.d0[icmp]); + // Derivatives of (dv) w.r.t. (A,B,phi): + dV11 = sin_al_i3 * (sin_al * dV11 - cos_al * dV1); + dV12 = sin_al_i1 * sin_be_i1 * dV12; + dV13 = sin_al_i1 * dV13; + dV22 = sin_be_i3 * (sin_be * dV22 - cos_be * dV2); + dV23 = sin_be_i1 * dV23; + dV1 = sin_al_i1 * dV1; + dV2 = sin_be_i1 * dV2; + // Derivatives of (dU) w.r.t. (A,B,phi): + dU.d0[ivar] = Am1 * dV0; + dU.d1[ivar] = dV0 + Am1 * dV1; + dU.d2[ivar] = Am1 * dV2; + dU.d3[ivar] = Am1 * dV3; + dU.d11[ivar] = 2 * dV1 + Am1 * dV11; + dU.d12[ivar] = dV2 + Am1 * dV12; + dU.d13[ivar] = dV3 + Am1 * dV13; + dU.d22[ivar] = Am1 * dV22; + dU.d23[ivar] = Am1 * dV23; + dU.d33[ivar] = Am1 * dV33; + + indx = Index (ivar, i, j, k, nvar, n1, n2, n3); + U.d0[ivar] = u.d0[indx]; // U + U.d1[ivar] = u.d1[indx]; // U_x + U.d2[ivar] = u.d2[indx]; // U_y + U.d3[ivar] = u.d3[indx]; // U_z + U.d11[ivar] = u.d11[indx]; // U_xx + U.d12[ivar] = u.d12[indx]; // U_xy + U.d13[ivar] = u.d13[indx]; // U_xz + U.d22[ivar] = u.d22[indx]; // U_yy + U.d23[ivar] = u.d23[indx]; // U_yz + U.d33[ivar] = u.d33[indx]; // U_zz + } + // Calculation of (X,R) and + // (dU_X, dU_R, dU_3, dU_XX, dU_XR, dU_X3, dU_RR, dU_R3, dU_33) + AB_To_XR (nvar, A, B, &X, &R, dU); + // Calculation of (x,r) and + // (dU, dU_x, dU_r, dU_3, dU_xx, dU_xr, dU_x3, dU_rr, dU_r3, dU_33) + C_To_c (nvar, X, R, &x, &r, dU); + // Calculation of (y,z) and + // (dU, dU_x, dU_y, dU_z, dU_xx, dU_xy, dU_xz, dU_yy, dU_yz, dU_zz) + rx3_To_xyz (nvar, x, r, phi, &y, &z, dU); + LinEquations (A, B, X, R, x, r, phi, y, z, dU, U, values); + for (ivar = 0; ivar < nvar; ivar++) + values[ivar] *= FAC; + + free_derivs (&dU, nvar); + free_derivs (&U, nvar); +} + +// ------------------------------------------------------------------------------- +void +SetMatrix_JFD (int nvar, int n1, int n2, int n3, derivs u, + int *ncols, int **cols, double **Matrix) +{ + DECLARE_CCTK_PARAMETERS; + int column, row, mcol; + int i, i1, i_0, i_1, j, j1, j_0, j_1, k, k1, k_0, k_1, N1, N2, N3, + ivar, ivar1, ntotal = nvar * n1 * n2 * n3; + double *values; + derivs dv; + + values = dvector (0, nvar - 1); + allocate_derivs (&dv, ntotal); + + N1 = n1 - 1; + N2 = n2 - 1; + N3 = n3 - 1; + + for (i = 0; i < n1; i++) + { + for (j = 0; j < n2; j++) + { + for (k = 0; k < n3; k++) + { + for (ivar = 0; ivar < nvar; ivar++) + { + row = Index (ivar, i, j, k, nvar, n1, n2, n3); + ncols[row] = 0; + dv.d0[row] = 0; + } + } + } + } + for (i = 0; i < n1; i++) + { + for (j = 0; j < n2; j++) + { + for (k = 0; k < n3; k++) + { + for (ivar = 0; ivar < nvar; ivar++) + { + column = Index (ivar, i, j, k, nvar, n1, n2, n3); + dv.d0[column] = 1; + + i_0 = maximum2 (0, i - 1); + i_1 = minimum2 (N1, i + 1); + j_0 = maximum2 (0, j - 1); + j_1 = minimum2 (N2, j + 1); + k_0 = k - 1; + k_1 = k + 1; +/* i_0 = 0; + i_1 = N1; + j_0 = 0; + j_1 = N2; + k_0 = 0; + k_1 = N3;*/ + + for (i1 = i_0; i1 <= i_1; i1++) + { + for (j1 = j_0; j1 <= j_1; j1++) + { + for (k1 = k_0; k1 <= k_1; k1++) + { + JFD_times_dv (i1, j1, k1, nvar, n1, n2, n3, + dv, u, values); + for (ivar1 = 0; ivar1 < nvar; ivar1++) + { + if (values[ivar1] != 0) + { + row = Index (ivar1, i1, j1, k1, nvar, n1, n2, n3); + mcol = ncols[row]; + cols[row][mcol] = column; + Matrix[row][mcol] = values[ivar1]; + ncols[row] += 1; + } + } + } + } + } + + dv.d0[column] = 0; + } + } + } + } + free_derivs (&dv, ntotal); + free_dvector (values, 0, nvar - 1); +} + +// ------------------------------------------------------------------------------- +// Calculates the value of v at an arbitrary position (A,B,phi) +double +PunctEvalAtArbitPosition (double *v, double A, double B, double phi, + int n1, int n2, int n3) +{ + int i, j, k, N; + double *p, *values1, **values2, result; + + N = maximum3 (n1, n2, n3); + p = dvector (0, N); + values1 = dvector (0, N); + values2 = dmatrix (0, N, 0, N); + + for (k = 0; k < n3; k++) + { + for (j = 0; j < n2; j++) + { + for (i = 0; i < n1; i++) + p[i] = v[i + n1 * (j + n2 * k)]; + chebft_Zeros (p, n1, 0); + values2[j][k] = chebev (-1, 1, p, n1, A); + } + } + + for (k = 0; k < n3; k++) + { + for (j = 0; j < n2; j++) + p[j] = values2[j][k]; + chebft_Zeros (p, n2, 0); + values1[k] = chebev (-1, 1, p, n2, B); + } + + fourft (values1, n3, 0); + result = fourev (values1, n3, phi); + + free_dvector (p, 0, N); + free_dvector (values1, 0, N); + free_dmatrix (values2, 0, N, 0, N); + + return result; +} + +// ------------------------------------------------------------------------------- +void +calculate_derivs (int i, int j, int k, int ivar, int nvar, int n1, int n2, + int n3, derivs v, derivs vv) +{ + double al = Pih * (2 * i + 1) / n1, be = Pih * (2 * j + 1) / n2, + sin_al = sin (al), sin2_al = sin_al * sin_al, cos_al = cos (al), + sin_be = sin (be), sin2_be = sin_be * sin_be, cos_be = cos (be); + + vv.d0[0] = v.d0[Index (ivar, i, j, k, nvar, n1, n2, n3)]; + vv.d1[0] = v.d1[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin_al; + vv.d2[0] = v.d2[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin_be; + vv.d3[0] = v.d3[Index (ivar, i, j, k, nvar, n1, n2, n3)]; + vv.d11[0] = v.d11[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin2_al + + v.d1[Index (ivar, i, j, k, nvar, n1, n2, n3)] * cos_al; + vv.d12[0] = + v.d12[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin_al * sin_be; + vv.d13[0] = v.d13[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin_al; + vv.d22[0] = v.d22[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin2_be + + v.d2[Index (ivar, i, j, k, nvar, n1, n2, n3)] * cos_be; + vv.d23[0] = v.d23[Index (ivar, i, j, k, nvar, n1, n2, n3)] * sin_be; + vv.d33[0] = v.d33[Index (ivar, i, j, k, nvar, n1, n2, n3)]; +} + +// ------------------------------------------------------------------------------- +double +interpol (double a, double b, double c, derivs v) +{ + return v.d0[0] + + a * v.d1[0] + b * v.d2[0] + c * v.d3[0] + + 0.5 * a * a * v.d11[0] + a * b * v.d12[0] + a * c * v.d13[0] + + 0.5 * b * b * v.d22[0] + b * c * v.d23[0] + 0.5 * c * c * v.d33[0]; +} + +// ------------------------------------------------------------------------------- +// Calculates the value of v at an arbitrary position (A,B,phi) +double +PunctIntPolAtArbitPosition (int ivar, int nvar, int n1, + int n2, int n3, derivs v, double x, double y, + double z) +{ + DECLARE_CCTK_PARAMETERS; + double xs, ys, zs, rs2, phi, X, R, A, B, al, be, aux1, aux2, a, b, c, + result, Us, Ui; + int i, j, k; + derivs vv; + allocate_derivs (&vv, 1); + + xs = x / par_b; + ys = y / par_b; + zs = z / par_b; + rs2 = ys * ys + zs * zs; + phi = atan2 (z, y); + if (phi < 0) + phi += 2 * Pi; + + aux1 = 0.5 * (xs * xs + rs2 - 1); + aux2 = sqrt (aux1 * aux1 + rs2); + X = asinh (sqrt (aux1 + aux2)); + R = asin (sqrt (-aux1 + aux2)); + if (x < 0) + R = Pi - R; + + A = 2 * tanh (0.5 * X) - 1; + B = tan (0.5 * R - Piq); + al = Pi - acos (A); + be = Pi - acos (B); + + i = rint (al * n1 / Pi - 0.5); + j = rint (be * n2 / Pi - 0.5); + k = rint (0.5 * phi * n3 / Pi); + + a = al - Pi * (i + 0.5) / n1; + b = be - Pi * (j + 0.5) / n2; + c = phi - 2 * Pi * k / n3; + + calculate_derivs (i, j, k, ivar, nvar, n1, n2, n3, v, vv); + result = interpol (a, b, c, vv); + free_derivs (&vv, 1); + +// Us = (A-1)*PunctEvalAtArbitPosition(v.d0, A, B, phi, n1, n2, n3); + Ui = (A - 1) * result; +// printf("%e %e %e Us=%e Ui=%e 1-Ui/Us=%e\n",x,y,z,Us,Ui,1-Ui/Us); + + return Ui; + +/* calculate_derivs(i+1, j, k, ivar, nvar, n1, n2, n3, v, vv, 2); + calculate_derivs(i, j+1, k, ivar, nvar, n1, n2, n3, v, vv, 3); + calculate_derivs(i+1, j+1, k, ivar, nvar, n1, n2, n3, v, vv, 4); + calculate_derivs(i, j, k+1, ivar, nvar, n1, n2, n3, v, vv, 5); + calculate_derivs(i+1, j, k+1, ivar, nvar, n1, n2, n3, v, vv, 6); + calculate_derivs(i, j+1, k+1, ivar, nvar, n1, n2, n3, v, vv, 7); + calculate_derivs(i+1, j+1, k+1, ivar, nvar, n1, n2, n3, v, vv, 8); + v_intpol[2]=interpol(ha*(a-1),hb*b, hp*c, vv,2); + v_intpol[3]=interpol(ha*a, hb*(b-1),hp*c, vv,3); + v_intpol[4]=interpol(ha*(a-1),hb*(b-1),hp*c, vv,4); + v_intpol[5]=interpol(ha*a, hb*b, hp*(c-1),vv,5); + v_intpol[6]=interpol(ha*(a-1),hb*b, hp*(c-1),vv,6); + v_intpol[7]=interpol(ha*a, hb*(b-1),hp*(c-1),vv,7); + v_intpol[8]=interpol(ha*(a-1),hb*(b-1),hp*(c-1),vv,8); + for(j=1;j<=8;j++) + printf("Value U[V] at origin:%16.15f\tj=%d\n",-2*v_intpol[j],j);*/ +/* result = 0; + for(mi=i-npol; mi<=i+npol; mi++){ + al_m = Pih*(2*mi+1)/n1; + for(mj=j-npol; mj<=j+npol; mj++){ + be_m = Pih*(2*mj+1)/n2; + for(mk=k-npol; mk<=k+npol; mk++){ + phi_m = 2.*Pi*mk/n3; + g_m = 1; + for(ni=i-npol; ni<=i+npol; ni++){ + al_n = Pih*(2*ni+1)/n1; + if(ni != mi) g_m *= (al - al_n)/(al_m - al_n); + } + for(nj=j-npol; nj<=j+npol; nj++){ + be_n = Pih*(2*nj+1)/n2; + if(nj != mj) g_m *= (be - be_n)/(be_m - be_n); + } + for(nk=k-npol; nk<=k+npol; nk++){ + phi_n = 2.*Pi*nk/n3; + if(nk != mk) g_m *= (phi-phi_n)/(phi_m - phi_n); + } + result += g_m*v.d0[Index(ivar,mi,mj,mk,nvar,n1,n2,n3)]; + } + } + } */ +} + +// ------------------------------------------------------------------------------- diff --git a/src/Newton.c b/src/Newton.c new file mode 100644 index 0000000..42ceaa3 --- /dev/null +++ b/src/Newton.c @@ -0,0 +1,435 @@ +// TwoPunctures: File "Newton.c" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ctype.h> +#include "cctk_Parameters.h" +#include "TP_utilities.h" +#include "TwoPunctures.h" + +// ----------------------------------------------------------------------------------- +void +resid (double *res, int ntotal, double *dv, double *rhs, + int *ncols, int **cols, double **JFD) +{ + int i, m; + double JFDdv_i; + + for (i = 0; i < ntotal; i++) + { + JFDdv_i = 0; + for (m = 0; m < ncols[i]; m++) + JFDdv_i += JFD[i][m] * dv[cols[i][m]]; + res[i] = rhs[i] - JFDdv_i; + } +} + +// ----------------------------------------------------------------------------------- +void +LineRelax_al (double *dv, int j, int k, int nvar, int n1, int n2, int n3, + double *rhs, int *ncols, int **cols, double **JFD) +{ + int i, m, Ic, Ip, Im, col, ivar; + double *a, *b, *c, *r, *u; + a = dvector (0, n1 - 1); + b = dvector (0, n1 - 1); + c = dvector (0, n1 - 1); + r = dvector (0, n1 - 1); + u = dvector (0, n1 - 1); + + for (ivar = 0; ivar < nvar; ivar++) + { + for (i = 0; i < n1; i++) + { + Ip = Index (ivar, i + 1, j, k, nvar, n1, n2, n3); + Ic = Index (ivar, i, j, k, nvar, n1, n2, n3); + Im = Index (ivar, i - 1, j, k, nvar, n1, n2, n3); + a[i] = 0; + b[i] = 0; + c[i] = 0; + r[i] = rhs[Ic]; + for (m = 0; m < ncols[Ic]; m++) + { + col = cols[Ic][m]; + if (col != Ip && col != Ic && col != Im) + r[i] -= JFD[Ic][m] * dv[col]; + else + { + if (col == Im) + a[i] = JFD[Ic][m]; + if (col == Ic) + b[i] = JFD[Ic][m]; + if (col == Ip) + c[i] = JFD[Ic][m]; + } + } + } + tridag (a, b, c, r, u, n1); + for (i = 0; i < n1; i++) + { + Ic = Index (ivar, i, j, k, nvar, n1, n2, n3); + dv[Ic] = u[i]; + } + } + free_dvector (a, 0, n1 - 1); + free_dvector (b, 0, n1 - 1); + free_dvector (c, 0, n1 - 1); + free_dvector (r, 0, n1 - 1); + free_dvector (u, 0, n1 - 1); +} + +// ----------------------------------------------------------------------------------- +void +LineRelax_be (double *dv, int i, int k, int nvar, int n1, int n2, int n3, + double *rhs, int *ncols, int **cols, double **JFD) +{ + int j, m, Ic, Ip, Im, col, ivar; + double *a, *b, *c, *r, *u; + a = dvector (0, n2 - 1); + b = dvector (0, n2 - 1); + c = dvector (0, n2 - 1); + r = dvector (0, n2 - 1); + u = dvector (0, n2 - 1); + + for (ivar = 0; ivar < nvar; ivar++) + { + for (j = 0; j < n2; j++) + { + Ip = Index (ivar, i, j + 1, k, nvar, n1, n2, n3); + Ic = Index (ivar, i, j, k, nvar, n1, n2, n3); + Im = Index (ivar, i, j - 1, k, nvar, n1, n2, n3); + a[j] = 0; + b[j] = 0; + c[j] = 0; + r[j] = rhs[Ic]; + for (m = 0; m < ncols[Ic]; m++) + { + col = cols[Ic][m]; + if (col != Ip && col != Ic && col != Im) + r[j] -= JFD[Ic][m] * dv[col]; + else + { + if (col == Im) + a[j] = JFD[Ic][m]; + if (col == Ic) + b[j] = JFD[Ic][m]; + if (col == Ip) + c[j] = JFD[Ic][m]; + } + } + } + tridag (a, b, c, r, u, n2); + for (j = 0; j < n2; j++) + { + Ic = Index (ivar, i, j, k, nvar, n1, n2, n3); + dv[Ic] = u[j]; + } + } + free_dvector (a, 0, n2 - 1); + free_dvector (b, 0, n2 - 1); + free_dvector (c, 0, n2 - 1); + free_dvector (r, 0, n2 - 1); + free_dvector (u, 0, n2 - 1); +} + +// ----------------------------------------------------------------------------------- +static void +relax (double *dv, int nvar, int n1, int n2, int n3, + double *rhs, int *ncols, int **cols, double **JFD) +{ + int i, j, k, n; + + for (k = 0; k < n3; k = k + 2) + { + for (n = 0; n < N_PlaneRelax; n++) + { + for (i = 2; i < n1; i = i + 2) + LineRelax_be (dv, i, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + for (i = 1; i < n1; i = i + 2) + LineRelax_be (dv, i, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + for (j = 1; j < n2; j = j + 2) + LineRelax_al (dv, j, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + for (j = 0; j < n2; j = j + 2) + LineRelax_al (dv, j, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + } + } + for (k = 1; k < n3; k = k + 2) + { + for (n = 0; n < N_PlaneRelax; n++) + { + for (i = 0; i < n1; i = i + 2) + LineRelax_be (dv, i, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + for (i = 1; i < n1; i = i + 2) + LineRelax_be (dv, i, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + for (j = 1; j < n2; j = j + 2) + LineRelax_al (dv, j, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + for (j = 0; j < n2; j = j + 2) + LineRelax_al (dv, j, k, nvar, n1, n2, n3, rhs, ncols, cols, JFD); + } + } +} + +// ----------------------------------------------------------------------------------- +void +TestRelax (int nvar, int n1, int n2, int n3, derivs v, + double *dv) +{ + DECLARE_CCTK_PARAMETERS; + int ntotal = n1 * n2 * n3 * nvar, **cols, *ncols, maxcol = + StencilSize * nvar, j; + double *F, *res, **JFD; + derivs u; + + F = dvector (0, ntotal - 1); + res = dvector (0, ntotal - 1); + allocate_derivs (&u, ntotal); + + JFD = dmatrix (0, ntotal - 1, 0, maxcol - 1); + cols = imatrix (0, ntotal - 1, 0, maxcol - 1); + ncols = ivector (0, ntotal - 1); + + F_of_v (nvar, n1, n2, n3, v, F, u); + + SetMatrix_JFD (nvar, n1, n2, n3, u, ncols, cols, JFD); + + for (j = 0; j < ntotal; j++) + dv[j] = 0; + resid (res, ntotal, dv, F, ncols, cols, JFD); + printf ("Davor: |F|=%20.15e\n", norm1 (res, ntotal)); + for (j = 0; j < NRELAX; j++) + { + relax (dv, nvar, n1, n2, n3, F, ncols, cols, JFD); // solves JFD*sh = s + if (j % Step_Relax == 0) + { + resid (res, ntotal, dv, F, ncols, cols, JFD); + printf ("j=%d\t |F|=%20.15e\n", j, norm1 (res, ntotal)); + } + } + + resid (res, ntotal, dv, F, ncols, cols, JFD); + printf ("Danach: |F|=%20.15e\n", norm1 (res, ntotal)); + + free_dvector (F, 0, ntotal - 1); + free_dvector (res, 0, ntotal - 1); + free_derivs (&u, ntotal); + + free_dmatrix (JFD, 0, ntotal - 1, 0, maxcol - 1); + free_imatrix (cols, 0, ntotal - 1, 0, maxcol - 1); + free_ivector (ncols, 0, ntotal - 1); +} + +// ----------------------------------------------------------------------------------- +int +bicgstab (int nvar, int n1, int n2, int n3, derivs v, + derivs dv, int output, int itmax, double tol, double *normres) +{ + DECLARE_CCTK_PARAMETERS; + int ntotal = n1 * n2 * n3 * nvar, ii, j; + double alpha = 0, beta = 0; + double rho = 0, rho1 = 1, rhotol = 1e-50; + double omega = 0, omegatol = 1e-50; + double *p, *rt, *s, *t, *r, *vv; + double **JFD; + int **cols, *ncols, maxcol = StencilSize * nvar; + double *F; + derivs u, ph, sh; + + F = dvector (0, ntotal - 1); + allocate_derivs (&u, ntotal); + + JFD = dmatrix (0, ntotal - 1, 0, maxcol - 1); + cols = imatrix (0, ntotal - 1, 0, maxcol - 1); + ncols = ivector (0, ntotal - 1); + + F_of_v (nvar, n1, n2, n3, v, F, u); + SetMatrix_JFD (nvar, n1, n2, n3, u, ncols, cols, JFD); + + /* temporary storage */ + r = dvector (0, ntotal - 1); + p = dvector (0, ntotal - 1); + allocate_derivs (&ph, ntotal); +// ph = dvector(0, ntotal-1); + rt = dvector (0, ntotal - 1); + s = dvector (0, ntotal - 1); + allocate_derivs (&sh, ntotal); +// sh = dvector(0, ntotal-1); + t = dvector (0, ntotal - 1); + vv = dvector (0, ntotal - 1); + + /* check */ + if (output == 1) + printf ("bicgstab: itmax %d, tol %e\n", itmax, tol); + + /* compute initial residual rt = r = F - J*dv */ + J_times_dv (nvar, n1, n2, n3, dv, r, u); + for (j = 0; j < ntotal; j++) + rt[j] = r[j] = F[j] - r[j]; + + *normres = norm2 (r, ntotal); + if (output == 1) + printf ("bicgstab: %5d %10.3e\n", 0, *normres); + + if (*normres <= tol) + return 0; + + /* cgs iteration */ + for (ii = 0; ii < itmax; ii++) + { + rho = scalarproduct (rt, r, ntotal); + if (fabs (rho) < rhotol) + break; + + /* compute direction vector p */ + if (ii == 0) + for (j = 0; j < ntotal; j++) + p[j] = r[j]; + else + { + beta = (rho / rho1) * (alpha / omega); + for (j = 0; j < ntotal; j++) + p[j] = r[j] + beta * (p[j] - omega * vv[j]); + } + + /* compute direction adjusting vector ph and scalar alpha */ + for (j = 0; j < ntotal; j++) + ph.d0[j] = 0; + for (j = 0; j < NRELAX; j++) // solves JFD*ph = p by relaxation + relax (ph.d0, nvar, n1, n2, n3, p, ncols, cols, JFD); + + J_times_dv (nvar, n1, n2, n3, ph, vv, u); // vv=J*ph + alpha = rho / scalarproduct (rt, vv, ntotal); + for (j = 0; j < ntotal; j++) + s[j] = r[j] - alpha * vv[j]; + + /* early check of tolerance */ + *normres = norm2 (s, ntotal); + if (*normres <= tol) + { + for (j = 0; j < ntotal; j++) + dv.d0[j] += alpha * ph.d0[j]; + if (output == 1) + printf ("bicgstab: %5d %10.3e %10.3e %10.3e %10.3e\n", + ii + 1, *normres, alpha, beta, omega); + break; + } + + /* compute stabilizer vector sh and scalar omega */ + for (j = 0; j < ntotal; j++) + sh.d0[j] = 0; + for (j = 0; j < NRELAX; j++) // solves JFD*sh = s by relaxation + relax (sh.d0, nvar, n1, n2, n3, s, ncols, cols, JFD); + + J_times_dv (nvar, n1, n2, n3, sh, t, u); // t=J*sh + omega = scalarproduct (t, s, ntotal) / scalarproduct (t, t, ntotal); + + /* compute new solution approximation */ + for (j = 0; j < ntotal; j++) + { + dv.d0[j] += alpha * ph.d0[j] + omega * sh.d0[j]; + r[j] = s[j] - omega * t[j]; + } + /* are we done? */ + *normres = norm2 (r, ntotal); + if (output == 1) + printf ("bicgstab: %5d %10.3e %10.3e %10.3e %10.3e\n", + ii + 1, *normres, alpha, beta, omega); + if (*normres <= tol) + break; + rho1 = rho; + if (fabs (omega) < omegatol) + break; + + } + + /* free temporary storage */ + free_dvector (r, 0, ntotal - 1); + free_dvector (p, 0, ntotal - 1); +// free_dvector(ph, 0, ntotal-1); + free_derivs (&ph, ntotal); + free_dvector (rt, 0, ntotal - 1); + free_dvector (s, 0, ntotal - 1); +// free_dvector(sh, 0, ntotal-1); + free_derivs (&sh, ntotal); + free_dvector (t, 0, ntotal - 1); + free_dvector (vv, 0, ntotal - 1); + + free_dvector (F, 0, ntotal - 1); + free_derivs (&u, ntotal); + + free_dmatrix (JFD, 0, ntotal - 1, 0, maxcol - 1); + free_imatrix (cols, 0, ntotal - 1, 0, maxcol - 1); + free_ivector (ncols, 0, ntotal - 1); + + /* iteration failed */ + if (ii > itmax) + return -1; + + /* breakdown */ + if (fabs (rho) < rhotol) + return -10; + if (fabs (omega) < omegatol) + return -11; + + /* success! */ + return ii + 1; +} + +// ------------------------------------------------------------------- +void +Newton (int nvar, int n1, int n2, int n3, + derivs v, double tol, int itmax) +{ + DECLARE_CCTK_PARAMETERS; + int ntotal = n1 * n2 * n3 * nvar, ii, j, it; + double *F, dmax, normres; + derivs u, dv; + + F = dvector (0, ntotal - 1); + allocate_derivs (&dv, ntotal); + allocate_derivs (&u, ntotal); + +/* TestRelax(nvar, n1, n2, n3, v, dv.d0); */ + for (j = 0; j < ntotal; j++) + v.d0[j] = 0; + + it = 0; + dmax = 1; + while (dmax > tol && it < itmax) + { + if (it == 0) + { + F_of_v (nvar, n1, n2, n3, v, F, u); + dmax = -1; + for (j = 0; j < ntotal; j++) + { + if (fabs (F[j]) > dmax) + dmax = fabs (F[j]); + dv.d0[j] = 0; + } + } + printf ("Newton: it=%d \t |F|=%e \n", it, dmax); + ii = + bicgstab (nvar, n1, n2, n3, v, dv, 1, 100, dmax * 1.e-3, &normres); + for (j = 0; j < ntotal; j++) + v.d0[j] -= dv.d0[j]; + F_of_v (nvar, n1, n2, n3, v, F, u); + dmax = -1; + for (j = 0; j < ntotal; j++) + { + if (fabs (F[j]) > dmax) + { + dmax = fabs (F[j]); + } + } + it += 1; + } + printf ("Newton: it=%d \t |F|=%e \n", it, dmax); + + free_dvector (F, 0, ntotal - 1); + free_derivs (&dv, ntotal); + free_derivs (&u, ntotal); +} + +// ------------------------------------------------------------------- diff --git a/src/TP_utilities.c b/src/TP_utilities.c new file mode 100644 index 0000000..64edbfd --- /dev/null +++ b/src/TP_utilities.c @@ -0,0 +1,951 @@ +// TwoPunctures: File "utilities.c" + +#include <math.h> +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include "TP_utilities.h" + +//----------------------------------------------------------------------------- +void +nrerror (char error_text[]) +/* Numerical Recipes standard error handler */ +{ + fprintf (stderr, "Numerical Recipes run-time error...\n"); + fprintf (stderr, "%s\n", error_text); + fprintf (stderr, "...now exiting to system...\n"); + exit (1); +} + +//----------------------------------------------------------------------------- +int * +ivector (long nl, long nh) +/* allocate an int vector with subscript range v[nl..nh] */ +{ + int *v; + + v = (int *) malloc ((size_t) ((nh - nl + 1 + NR_END) * sizeof (int))); + if (!v) + nrerror ("allocation failure in ivector()"); + return v - nl + NR_END; +} + +//----------------------------------------------------------------------------- +double * +dvector (long nl, long nh) +/* allocate a double vector with subscript range v[nl..nh] */ +{ + double *v; + + v = (double *) malloc ((size_t) ((nh - nl + 1 + NR_END) * sizeof (double))); + if (!v) + nrerror ("allocation failure in dvector()"); + return v - nl + NR_END; +} + +//----------------------------------------------------------------------------- +int ** +imatrix (long nrl, long nrh, long ncl, long nch) +/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow = nrh - nrl + 1, ncol = nch - ncl + 1; + int **m; + + /* allocate pointers to rows */ + m = (int **) malloc ((size_t) ((nrow + NR_END) * sizeof (int *))); + if (!m) + nrerror ("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + + /* allocate rows and set pointers to them */ + m[nrl] = (int *) malloc ((size_t) ((nrow * ncol + NR_END) * sizeof (int))); + if (!m[nrl]) + nrerror ("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for (i = nrl + 1; i <= nrh; i++) + m[i] = m[i - 1] + ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +//----------------------------------------------------------------------------- +double ** +dmatrix (long nrl, long nrh, long ncl, long nch) +/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow = nrh - nrl + 1, ncol = nch - ncl + 1; + double **m; + + /* allocate pointers to rows */ + m = (double **) malloc ((size_t) ((nrow + NR_END) * sizeof (double *))); + if (!m) + nrerror ("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + /* allocate rows and set pointers to them */ + m[nrl] = + (double *) malloc ((size_t) ((nrow * ncol + NR_END) * sizeof (double))); + if (!m[nrl]) + nrerror ("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for (i = nrl + 1; i <= nrh; i++) + m[i] = m[i - 1] + ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +//----------------------------------------------------------------------------- +double *** +d3tensor (long nrl, long nrh, long ncl, long nch, long ndl, long ndh) +/* allocate a double 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */ +{ + long i, j, nrow = nrh - nrl + 1, ncol = nch - ncl + 1, ndep = ndh - ndl + 1; + double ***t; + + /* allocate pointers to pointers to rows */ + t = (double ***) malloc ((size_t) ((nrow + NR_END) * sizeof (double **))); + if (!t) + nrerror ("allocation failure 1 in f3tensor()"); + t += NR_END; + t -= nrl; + + /* allocate pointers to rows and set pointers to them */ + t[nrl] = + (double **) + malloc ((size_t) ((nrow * ncol + NR_END) * sizeof (double *))); + if (!t[nrl]) + nrerror ("allocation failure 2 in f3tensor()"); + t[nrl] += NR_END; + t[nrl] -= ncl; + + /* allocate rows and set pointers to them */ + t[nrl][ncl] = + (double *) + malloc ((size_t) ((nrow * ncol * ndep + NR_END) * sizeof (double))); + if (!t[nrl][ncl]) + nrerror ("allocation failure 3 in f3tensor()"); + t[nrl][ncl] += NR_END; + t[nrl][ncl] -= ndl; + + for (j = ncl + 1; j <= nch; j++) + t[nrl][j] = t[nrl][j - 1] + ndep; + for (i = nrl + 1; i <= nrh; i++) + { + t[i] = t[i - 1] + ncol; + t[i][ncl] = t[i - 1][ncl] + ncol * ndep; + for (j = ncl + 1; j <= nch; j++) + t[i][j] = t[i][j - 1] + ndep; + } + + /* return pointer to array of pointers to rows */ + return t; +} + +//----------------------------------------------------------------------------- +void +free_ivector (int *v, long nl, long nh) +/* free an int vector allocated with ivector() */ +{ + free ((FREE_ARG) (v + nl - NR_END)); +} + +//----------------------------------------------------------------------------- +void +free_dvector (double *v, long nl, long nh) +/* free a double vector allocated with dvector() */ +{ + free ((FREE_ARG) (v + nl - NR_END)); +} + +//----------------------------------------------------------------------------- +void +free_imatrix (int **m, long nrl, long nrh, long ncl, long nch) +/* free an int matrix allocated by imatrix() */ +{ + free ((FREE_ARG) (m[nrl] + ncl - NR_END)); + free ((FREE_ARG) (m + nrl - NR_END)); +} + +//----------------------------------------------------------------------------- +void +free_dmatrix (double **m, long nrl, long nrh, long ncl, long nch) +/* free a double matrix allocated by dmatrix() */ +{ + free ((FREE_ARG) (m[nrl] + ncl - NR_END)); + free ((FREE_ARG) (m + nrl - NR_END)); +} + +//----------------------------------------------------------------------------- +void +free_d3tensor (double ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh) +/* free a double f3tensor allocated by f3tensor() */ +{ + free ((FREE_ARG) (t[nrl][ncl] + ndl - NR_END)); + free ((FREE_ARG) (t[nrl] + ncl - NR_END)); + free ((FREE_ARG) (t + nrl - NR_END)); +} + +//----------------------------------------------------------------------------- +int +minimum2 (int i, int j) +{ + int result = i; + if (j < result) + result = j; + return result; +} + +//----------------------------------------------------------------------------- +int +minimum3 (int i, int j, int k) +{ + int result = i; + if (j < result) + result = j; + if (k < result) + result = k; + return result; +} + +//----------------------------------------------------------------------------- +int +maximum2 (int i, int j) +{ + int result = i; + if (j > result) + result = j; + return result; +} + +//----------------------------------------------------------------------------- +int +maximum3 (int i, int j, int k) +{ + int result = i; + if (j > result) + result = j; + if (k > result) + result = k; + return result; +} + +//----------------------------------------------------------------------------- +int +pow_int (int mantisse, int exponent) +{ + int i, result = 1; + + for (i = 1; i <= exponent; i++) + result *= mantisse; + + return result; +} + +//----------------------------------------------------------------------------- +double +atanh (double x) +{ + return 0.5 * log ((1 + x) / (1 - x)); +} + +//----------------------------------------------------------------------------- +double +asinh (double x) +{ + return log (x + sqrt (1 + x * x)); +} + +//----------------------------------------------------------------------------- +double +acosh (double x) +{ + return log (x + sqrt (x * x - 1)); +} + +//----------------------------------------------------------------------------- +dcomplex +Cadd (dcomplex a, dcomplex b) +{ + dcomplex c; + c.r = a.r + b.r; + c.i = a.i + b.i; + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Csub (dcomplex a, dcomplex b) +{ + dcomplex c; + c.r = a.r - b.r; + c.i = a.i - b.i; + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Cmul (dcomplex a, dcomplex b) +{ + dcomplex c; + c.r = a.r * b.r - a.i * b.i; + c.i = a.i * b.r + a.r * b.i; + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +RCmul (double x, dcomplex a) +{ + dcomplex c; + c.r = x * a.r; + c.i = x * a.i; + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Cdiv (dcomplex a, dcomplex b) +{ + dcomplex c; + double r, den; + if (fabs (b.r) >= fabs (b.i)) + { + r = b.i / b.r; + den = b.r + r * b.i; + c.r = (a.r + r * a.i) / den; + c.i = (a.i - r * a.r) / den; + } + else + { + r = b.r / b.i; + den = b.i + r * b.r; + c.r = (a.r * r + a.i) / den; + c.i = (a.i * r - a.r) / den; + } + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Complex (double re, double im) +{ + dcomplex c; + c.r = re; + c.i = im; + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Conjg (dcomplex z) +{ + dcomplex c; + c.r = z.r; + c.i = -z.i; + return c; +} + +//----------------------------------------------------------------------------- +double +Cabs (dcomplex z) +{ + double x, y, ans, temp; + x = fabs (z.r); + y = fabs (z.i); + if (x == 0.0) + ans = y; + else if (y == 0.0) + ans = x; + else if (x > y) + { + temp = y / x; + ans = x * sqrt (1.0 + temp * temp); + } + else + { + temp = x / y; + ans = y * sqrt (1.0 + temp * temp); + } + return ans; +} + +//----------------------------------------------------------------------------- +dcomplex +Csqrt (dcomplex z) +{ + dcomplex c; + double x, y, w, r; + if ((z.r == 0.0) && (z.i == 0.0)) + { + c.r = 0.0; + c.i = 0.0; + return c; + } + else + { + x = fabs (z.r); + y = fabs (z.i); + if (x >= y) + { + r = y / x; + w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + r * r))); + } + else + { + r = x / y; + w = sqrt (y) * sqrt (0.5 * (r + sqrt (1.0 + r * r))); + } + if (z.r >= 0.0) + { + c.r = w; + c.i = z.i / (2.0 * w); + } + else + { + c.i = (z.i >= 0) ? w : -w; + c.r = z.i / (2.0 * c.i); + } + return c; + } +} + +//----------------------------------------------------------------------------- +dcomplex +Cexp (dcomplex z) +{ + dcomplex c; + double exp_r = exp (z.r); + + c.r = exp_r * cos (z.i); + c.i = exp_r * sin (z.i); + + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Clog (dcomplex z) +{ + dcomplex c; + + c.r = 0.5 * log (z.r * z.r + z.i * z.i); + c.i = atan2 (z.i, z.r); + + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Csin (dcomplex z) +{ + dcomplex c; + + c.r = sin (z.r) * cosh (z.i); + c.i = cos (z.r) * sinh (z.i); + + return c; +} //----------------------------------------------------------------------------- + +dcomplex +Ccos (dcomplex z) +{ + dcomplex c; + + c.r = cos (z.r) * cosh (z.i); + c.i = -sin (z.r) * sinh (z.i); + + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Ctan (dcomplex z) +{ + return Cdiv (Csin (z), Ccos (z)); +} + +//----------------------------------------------------------------------------- +dcomplex +Ccot (dcomplex z) +{ + return Cdiv (Ccos (z), Csin (z)); +} + +//----------------------------------------------------------------------------- +dcomplex +Csinh (dcomplex z) +{ + dcomplex c; + + c.r = sinh (z.r) * cos (z.i); + c.i = cosh (z.r) * sin (z.i); + + return c; +} //----------------------------------------------------------------------------- + +dcomplex +Ccosh (dcomplex z) +{ + dcomplex c; + + c.r = cosh (z.r) * cos (z.i); + c.i = sinh (z.r) * sin (z.i); + + return c; +} + +//----------------------------------------------------------------------------- +dcomplex +Ctanh (dcomplex z) +{ + return Cdiv (Csinh (z), Ccosh (z)); +} + +//----------------------------------------------------------------------------- +dcomplex +Ccoth (dcomplex z) +{ + return Cdiv (Ccosh (z), Csinh (z)); +} + +//----------------------------------------------------------------------------- +void +chebft_Zeros (double u[], int n, int inv) +{ + int k, j, isignum; + double fac, sum, Pion, *c; + + c = dvector (0, n); + Pion = Pi / n; + if (inv == 0) + { + fac = 2.0 / n; + isignum = 1; + for (j = 0; j < n; j++) + { + sum = 0.0; + for (k = 0; k < n; k++) + sum += u[k] * cos (Pion * j * (k + 0.5)); + c[j] = fac * sum * isignum; + isignum = -isignum; + } + } + else + { + for (j = 0; j < n; j++) + { + sum = -0.5 * u[0]; + isignum = 1; + for (k = 0; k < n; k++) + { + sum += u[k] * cos (Pion * (j + 0.5) * k) * isignum; + isignum = -isignum; + } + c[j] = sum; + } + } + for (j = 0; j < n; j++) + u[j] = c[j]; + free_dvector (c, 0, n); +} + +// ------------------------------------------------------------------------------- + +void +chebft_Extremes (double u[], int n, int inv) +{ + int k, j, isignum, N = n - 1; + double fac, sum, PioN, *c; + + c = dvector (0, N); + PioN = Pi / N; + if (inv == 0) + { + fac = 2.0 / N; + isignum = 1; + for (j = 0; j < n; j++) + { + sum = 0.5 * (u[0] + u[N] * isignum); + for (k = 1; k < N; k++) + sum += u[k] * cos (PioN * j * k); + c[j] = fac * sum * isignum; + isignum = -isignum; + } + c[N] = 0.5 * c[N]; + } + else + { + for (j = 0; j < n; j++) + { + sum = -0.5 * u[0]; + isignum = 1; + for (k = 0; k < n; k++) + { + sum += u[k] * cos (PioN * j * k) * isignum; + isignum = -isignum; + } + c[j] = sum; + } + } + for (j = 0; j < n; j++) + u[j] = c[j]; + free_dvector (c, 0, N); +} + +// ------------------------------------------------------------------------------- + +void +chder (double *c, double *cder, int n) +{ + int j; + + cder[n] = 0.0; + cder[n - 1] = 0.0; + for (j = n - 2; j >= 0; j--) + cder[j] = cder[j + 2] + 2 * (j + 1) * c[j + 1]; +} + +// ------------------------------------------------------------------------------- +double +chebev (double a, double b, double c[], int m, double x) +{ + double d = 0.0, dd = 0.0, sv, y, y2; + int j; + + y2 = 2.0 * (y = (2.0 * x - a - b) / (b - a)); + for (j = m - 1; j >= 1; j--) + { + sv = d; + d = y2 * d - dd + c[j]; + dd = sv; + } + return y * d - dd + 0.5 * c[0]; +} + +// ------------------------------------------------------------------------------- +void +fourft (double *u, int N, int inv) +{ + int l, k, iy, M; + double x, x1, fac, Pi_fac, *a, *b; + + M = N / 2; + a = dvector (0, M); + b = dvector (1, M); // Actually: b=vector(1,M-1) but this is problematic if M=1 + fac = 1. / M; + Pi_fac = Pi * fac; + if (inv == 0) + { + for (l = 0; l <= M; l++) + { + a[l] = 0; + if (l > 0 && l < M) + b[l] = 0; + x1 = Pi_fac * l; + for (k = 0; k < N; k++) + { + x = x1 * k; + a[l] += fac * u[k] * cos (x); + if (l > 0 && l < M) + b[l] += fac * u[k] * sin (x); + } + } + u[0] = a[0]; + u[M] = a[M]; + for (l = 1; l < M; l++) + { + u[l] = a[l]; + u[l + M] = b[l]; + } + } + else + { + a[0] = u[0]; + a[M] = u[M]; + for (l = 1; l < M; l++) + { + a[l] = u[l]; + b[l] = u[M + l]; + } + iy = 1; + for (k = 0; k < N; k++) + { + u[k] = 0.5 * (a[0] + a[M] * iy); + x1 = Pi_fac * k; + for (l = 1; l < M; l++) + { + x = x1 * l; + u[k] += a[l] * cos (x) + b[l] * sin (x); + } + iy = -iy; + } + } + free_dvector (a, 0, M); + free_dvector (b, 1, M); +} + +/* -----------------------------------------*/ +void +fourder (double u[], double du[], int N) +{ + int l, M, lpM; + + M = N / 2; + du[0] = 0.; + du[M] = 0.; + for (l = 1; l < M; l++) + { + lpM = l + M; + du[l] = u[lpM] * l; + du[lpM] = -u[l] * l; + } +} + +/* -----------------------------------------*/ +void +fourder2 (double u[], double d2u[], int N) +{ + int l, l2, M, lpM; + + d2u[0] = 0.; + M = N / 2; + for (l = 1; l <= M; l++) + { + l2 = l * l; + lpM = l + M; + d2u[l] = -u[l] * l2; + if (l < M) + d2u[lpM] = -u[lpM] * l2; + } +} + +/* ----------------------------------------- */ +double +fourev (double *u, int N, double x) +{ + int l, M = N / 2; + double xl, result; + + result = 0.5 * (u[0] + u[M] * cos (x * M)); + for (l = 1; l < M; l++) + { + xl = x * l; + result += u[l] * cos (xl) + u[M + l] * sin (xl); + } + return result; +} + +// ------------------------------------------------------------------------------- +void +ludcmp (double **a, int n, int *indx, double *d) +{ // Version of 'ludcmp' of the numerical recipes for + // matrices a[0:n-1][0:n-1] + int i, imax, j, k; + double big, dum, sum, temp; + double *vv; + + vv = dvector (0, n - 1); + *d = 1.0; + for (i = 0; i < n; i++) + { + big = 0.0; + for (j = 0; j < n; j++) + if ((temp = fabs (a[i][j])) > big) + big = temp; + if (big == 0.0) + nrerror ("Singular matrix in routine ludcmp"); + vv[i] = 1.0 / big; + } + for (j = 0; j < n; j++) + { + for (i = 0; i < j; i++) + { + sum = a[i][j]; + for (k = 0; k < i; k++) + sum -= a[i][k] * a[k][j]; + a[i][j] = sum; + } + big = 0.0; + for (i = j; i < n; i++) + { + sum = a[i][j]; + for (k = 0; k < j; k++) + sum -= a[i][k] * a[k][j]; + a[i][j] = sum; + if ((dum = vv[i] * fabs (sum)) >= big) + { + big = dum; + imax = i; + } + } + if (j != imax) + { + for (k = 0; k < n; k++) + { + dum = a[imax][k]; + a[imax][k] = a[j][k]; + a[j][k] = dum; + } + *d = -(*d); + vv[imax] = vv[j]; + } + indx[j] = imax; + if (a[j][j] == 0.0) + a[j][j] = TINY; + if (j != n) + { + dum = 1.0 / (a[j][j]); + for (i = j + 1; i < n; i++) + a[i][j] *= dum; + } + } + free_dvector (vv, 0, n - 1); +} + +// ------------------------------------------------------------------------------- +void +lubksb (double **a, int n, int *indx, double b[]) +{ // Version of 'lubksb' of the numerical recipes for + // matrices a[0:n-1][0:n-1] and vectors b[0:n-1] + + int i, ii = 0, ip, j; + double sum; + + for (i = 0; i < n; i++) + { + ip = indx[i]; + sum = b[ip]; + b[ip] = b[i]; + if (ii) + for (j = ii; j <= i - 1; j++) + sum -= a[i][j] * b[j]; + else if (sum) + ii = i; + b[i] = sum; + } + for (i = n - 1; i >= 0; i--) + { + sum = b[i]; + for (j = i + 1; j <= n; j++) + sum -= a[i][j] * b[j]; + b[i] = sum / a[i][i]; + } +} + +// ----------------------------------------------------------------------------------- +void +tridag (double a[], double b[], double c[], double r[], double u[], int n) +{ // Version of 'tridag' of the numerical recipes for + // vectors a, b, c, r, u with indices in the range [0:n-1] + int j; + double bet, *gam; + + gam = dvector (0, n - 1); + if (b[0] == 0.0) + nrerror ("Error 1 in tridag"); + u[0] = r[0] / (bet = b[0]); + for (j = 1; j < n; j++) + { + gam[j] = c[j - 1] / bet; + bet = b[j] - a[j] * gam[j]; + if (bet == 0.0) + nrerror ("Error 2 in tridag"); + u[j] = (r[j] - a[j] * u[j - 1]) / bet; + } + for (j = (n - 2); j >= 0; j--) + u[j] -= gam[j + 1] * u[j + 1]; + free_dvector (gam, 0, n - 1); +} + +// ----------------------------------------------------------------------------------- +double +norm1 (double *v, int n) +{ + int i; + double result = -1; + + for (i = 0; i < n; i++) + if (fabs (v[i]) > result) + result = fabs (v[i]); + + return result; +} + +// ----------------------------------------------------------------------------------- +double +norm2 (double *v, int n) +{ + int i; + double result = 0; + + for (i = 0; i < n; i++) + result += v[i] * v[i]; + + return sqrt (result); +} + +// ----------------------------------------------------------------------------------- +double +scalarproduct (double *v, double *w, int n) +{ + int i; + double result = 0; + + for (i = 0; i < n; i++) + result += v[i] * w[i]; + + return result; +} + +// ----------------------------------------------------------------------------------- +double +plgndr (int l, int m, double x) +{ + void nrerror (char error_text[]); + double fact, pll, pmm, pmmp1, somx2; + int i, ll; + + if (m < 0 || m > l || fabs (x) > 1.0) + nrerror ("Bad arguments in routine plgndr"); + pmm = 1.0; + if (m > 0) + { + somx2 = sqrt ((1.0 - x) * (1.0 + x)); + fact = 1.0; + for (i = 1; i <= m; i++) + { + pmm *= -fact * somx2; + fact += 2.0; + } + } + if (l == m) + return pmm; + else + { + pmmp1 = x * (2 * m + 1) * pmm; + if (l == (m + 1)) + return pmmp1; + else + { + for (ll = m + 2; ll <= l; ll++) + { + pll = (x * (2 * ll - 1) * pmmp1 - (ll + m - 1) * pmm) / (ll - m); + pmm = pmmp1; + pmmp1 = pll; + } + return pll; + } + } +} + +// ----------------------------------------------------------------------------------- diff --git a/src/TP_utilities.h b/src/TP_utilities.h new file mode 100644 index 0000000..37db3f0 --- /dev/null +++ b/src/TP_utilities.h @@ -0,0 +1,91 @@ +// TwoPunctures: File "utilities.h" + +#define Pi 3.14159265358979323846264338328 +#define Pih 1.57079632679489661923132169164 // Pi/2 +#define Piq 0.78539816339744830961566084582 // Pi/4 + +#define TINY 1.0e-20 +#define SWAP(a,b) {temp=(a);(a)=(b);(b)=temp;} +#define NR_END 1 +#define FREE_ARG char* + +typedef struct DCOMPLEX +{ + double r, i; +} dcomplex; + +#define nrerror TP_nrerror +#define ivector TP_ivector +#define dvector TP_dvector +#define imatrix TP_imatrix +#define dmatrix TP_dmatrix +#define d3tensor TP_d3tensor +#define free_ivector TP_free_ivector +#define free_dvector TP_free_dvector +#define free_imatrix TP_free_imatrix +#define free_dmatrix TP_free_dmatrix +#define free_d3tensor TP_free_d3tensor + +void nrerror (char error_text[]); +int *ivector (long nl, long nh); +double *dvector (long nl, long nh); +int **imatrix (long nrl, long nrh, long ncl, long nch); +double **dmatrix (long nrl, long nrh, long ncl, long nch); +double ***d3tensor (long nrl, long nrh, long ncl, long nch, long ndl, + long ndh); +void free_ivector (int *v, long nl, long nh); +void free_dvector (double *v, long nl, long nh); +void free_imatrix (int **m, long nrl, long nrh, long ncl, long nch); +void free_dmatrix (double **m, long nrl, long nrh, long ncl, long nch); +void free_d3tensor (double ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh); + +int minimum2 (int i, int j); +int minimum3 (int i, int j, int k); +int maximum2 (int i, int j); +int maximum3 (int i, int j, int k); +int pow_int (int mantisse, int exponent); +double atanh (double x); +double asinh (double x); +double acosh (double x); + +dcomplex Cadd (dcomplex a, dcomplex b); +dcomplex Csub (dcomplex a, dcomplex b); +dcomplex Cmul (dcomplex a, dcomplex b); +dcomplex RCmul (double x, dcomplex a); +dcomplex Cdiv (dcomplex a, dcomplex b); +dcomplex Complex (double re, double im); +dcomplex Conjg (dcomplex z); +double Cabs (dcomplex z); + +dcomplex Csqrt (dcomplex z); +dcomplex Cexp (dcomplex z); +dcomplex Clog (dcomplex z); +dcomplex Csin (dcomplex z); +dcomplex Ccos (dcomplex z); +dcomplex Ctan (dcomplex z); +dcomplex Ccot (dcomplex z); +dcomplex Csinh (dcomplex z); +dcomplex Ccosh (dcomplex z); +dcomplex Ctanh (dcomplex z); +dcomplex Ccoth (dcomplex z); + +void chebft_Zeros (double u[], int n, int inv); +void chebft_Extremes (double u[], int n, int inv); +void chder (double *c, double *cder, int n); +double chebev (double a, double b, double c[], int m, double x); +void fourft (double *u, int N, int inv); +void fourder (double u[], double du[], int N); +void fourder2 (double u[], double d2u[], int N); +double fourev (double *u, int N, double x); + + +void ludcmp (double **a, int n, int *indx, double *d); +void lubksb (double **a, int n, int *indx, double b[]); +void tridag (double a[], double b[], double c[], double r[], double u[], + int n); +double norm1 (double *v, int n); +double norm2 (double *v, int n); +double scalarproduct (double *v, double *w, int n); + +double plgndr (int l, int m, double x); diff --git a/src/TwoPunctures.c b/src/TwoPunctures.c new file mode 100644 index 0000000..a43f22b --- /dev/null +++ b/src/TwoPunctures.c @@ -0,0 +1,128 @@ +// TwoPunctures: File "TwoPunctures.c" + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ctype.h> +#include "cctk.h" +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" +#include "TP_utilities.h" +#include "TwoPunctures.h" + +static inline double pow2 (const double x) +{ + return x*x; +} + +// ------------------------------------------------------------------- +void +TwoPunctures (CCTK_ARGUMENTS) +{ + DECLARE_CCTK_ARGUMENTS; + DECLARE_CCTK_PARAMETERS; + + int nvar = 1, n1 = npoints_A, n2 = npoints_B, n3 = npoints_phi; + + int i, j, k, ntotal = n1 * n2 * n3 * nvar; + double *F; + derivs u, v; + + F = dvector (0, ntotal - 1); + allocate_derivs (&u, ntotal); + allocate_derivs (&v, ntotal); + + CCTK_INFO ("Beginning elliptic solving"); + Newton (nvar, n1, n2, n3, v, 1.e-10, 5); + + F_of_v (nvar, n1, n2, n3, v, F, u); + + CCTK_INFO ("Interpolating result"); + if (CCTK_EQUALS(metric_type, "static conformal")) { + if (CCTK_EQUALS(conformal_storage, "factor")) { + *conformal_state = 1; + } else if (CCTK_EQUALS(conformal_storage, "factor+derivs")) { + *conformal_state = 2; + } else if (CCTK_EQUALS(conformal_storage, "factor+derivs+2nd derivs")) { + *conformal_state = 3; + } + } else { + *conformal_state = 0; + } + + for (k = 0; k < cctk_lsh[2]; ++k) + { + for (j = 0; j < cctk_lsh[1]; ++j) + { + for (i = 0; i < cctk_lsh[0]; ++i) + { + + const int ind = CCTK_GFINDEX3D (cctkGH, i, j, k); + + const double r_plus + = sqrt(pow2(x[ind] - par_b) + pow2(y[ind]) + pow2(z[ind])); + const double r_minus + = sqrt(pow2(x[ind] + par_b) + pow2(y[ind]) + pow2(z[ind])); + + const double U = PunctIntPolAtArbitPosition + (0, nvar, n1, n2, n3, v, x[ind], y[ind], z[ind]); + const double psi1 = 1 + 0.5 * par_m_plus / r_plus + + 0.5 * par_m_minus / r_minus + U; + const double psi4 = pow2(pow2(psi1)); + const double psim2 = 1.0/pow2(psi1); + + double Aij[3][3]; + BY_Aijofxyz (x[ind], y[ind], z[ind], Aij); + + switch (*conformal_state) { + case 0: + gxx[ind] = psi4; + gxy[ind] = 0; + gxz[ind] = 0; + gyy[ind] = psi4; + gyz[ind] = 0; + gzz[ind] = psi4; + break; + + case 3: + /* not yet supported */ + assert (0); + /* fall through */ + + case 2: + /* not yet supported */ + assert (0); + /* fall through */ + + case 1: + psi[ind] = psi1; + + gxx[ind] = 1; + gxy[ind] = 0; + gxz[ind] = 0; + gyy[ind] = 1; + gyz[ind] = 0; + gzz[ind] = 1; + break; + + default: + assert(0); + } + + kxx[ind] = psim2 * Aij[0][0]; + kxy[ind] = psim2 * Aij[0][1]; + kxz[ind] = psim2 * Aij[0][2]; + kyy[ind] = psim2 * Aij[1][1]; + kyz[ind] = psim2 * Aij[1][2]; + kzz[ind] = psim2 * Aij[2][2]; + + } + } + } + + free_dvector (F, 0, ntotal - 1); + free_derivs (&u, ntotal); + free_derivs (&v, ntotal); +} diff --git a/src/TwoPunctures.h b/src/TwoPunctures.h new file mode 100644 index 0000000..ab0d841 --- /dev/null +++ b/src/TwoPunctures.h @@ -0,0 +1,95 @@ +// TwoPunctures: File "TwoPunctures.h" + +#define StencilSize 19 +#define N_PlaneRelax 1 +#define NRELAX 200 +#define Step_Relax 1 + +typedef struct DERIVS +{ + double *d0, *d1, *d2, *d3, *d11, *d12, *d13, *d22, *d23, *d33; +} derivs; + +/* +Files of "TwoPunctures": + TwoPunctures.c + FuncAndJacobian.c + CoordTransf.c + Equations.c + Newton.c + utilities.c (see utilities.h) +************************** +*/ + +// Routines in "TwoPunctures.c" +double TestSolution (double A, double B, double X, double R, double phi); +void TestVector_w (double *par, int nvar, int n1, int n2, int n3, double *w); + +// Routines in "FuncAndJacobian.c" +int Index (int ivar, int i, int j, int k, int nvar, int n1, int n2, int n3); +void allocate_derivs (derivs * v, int n); +void free_derivs (derivs * v, int n); +void Derivatives_AB3 (int nvar, int n1, int n2, int n3, derivs v); +void F_of_v (int nvar, int n1, int n2, int n3, derivs v, + double *F, derivs u); +void J_times_dv (int nvar, int n1, int n2, int n3, derivs dv, + double *Jdv, derivs u); +void JFD_times_dv (int i, int j, int k, int nvar, int n1, + int n2, int n3, derivs dv, derivs u, double *values); +void SetMatrix_JFD (int nvar, int n1, int n2, int n3, + derivs u, int *ncols, int **cols, double **Matrix); +double PunctEvalAtArbitPosition (double *v, double A, double B, double phi, + int n1, int n2, int n3); +void calculate_derivs (int i, int j, int k, int ivar, int nvar, int n1, + int n2, int n3, derivs v, derivs vv); +double interpol (double a, double b, double c, derivs v); +double PunctIntPolAtArbitPosition (int ivar, int nvar, int n1, + int n2, int n3, derivs v, double x, + double y, double z); + +// Routines in "CoordTransf.c" +void AB_To_XR (int nvar, double A, double B, double *X, + double *R, derivs U); +void C_To_c (int nvar, double X, double R, double *x, + double *r, derivs U); +void rx3_To_xyz (int nvar, double x, double r, double phi, double *y, + double *z, derivs U); + +// Routines in "Equations.c" +double BY_KKofxyz (double x, double y, double z); +void BY_Aijofxyz (double x, double y, double z, double Aij[3][3]); +void NonLinEquations (double A, double B, double X, double R, + double x, double r, double phi, + double y, double z, derivs U, double *values); +void LinEquations (double A, double B, double X, double R, + double x, double r, double phi, + double y, double z, derivs dU, derivs U, double *values); + +// Routines in "Newton.c" +void resid (double *res, int ntotal, double *dv, double *rhs, + int *ncols, int **cols, double **JFD); +void LineRelax_al (double *dv, int j, int k, int nvar, int n1, int n2, int n3, + double *rhs, int *ncols, int **cols, double **JFD); +void LineRelax_be (double *dv, int i, int k, int nvar, int n1, int n2, int n3, + double *rhs, int *ncols, int **cols, double **JFD); +void relax (double *dv, int nvar, int n1, int n2, int n3, double *rhs, + int *ncols, int **cols, double **JFD); +void TestRelax (int nvar, int n1, int n2, int n3, derivs v, + double *dv); +int bicgstab (int nvar, int n1, int n2, int n3, derivs v, + derivs dv, int output, int itmax, double tol, double *normres); +void Newton (int nvar, int n1, int n2, int n3, derivs v, + double tol, int itmax); + + +/* + 27: -1.325691774825335e-03 + 37: -1.325691778944117e-03 + 47: -1.325691778942711e-03 + + 17: -1.510625972641537e-03 + 21: -1.511443006977708e-03 + 27: -1.511440785153687e-03 + 37: -1.511440809549005e-03 + 39: -1.511440809597588e-03 + */ diff --git a/src/make.code.defn b/src/make.code.defn new file mode 100644 index 0000000..726aec8 --- /dev/null +++ b/src/make.code.defn @@ -0,0 +1,8 @@ +# Main make.code.defn file for thorn TwoPunctures +# $Header$ + +# Source files in this directory +SRCS = CoordTransf.c Equations.c FuncAndJacobian.c Newton.c TwoPunctures.c TP_utilities.c + +# Subdirectories containing source files +SUBDIRS = diff --git a/test/twopunctures.par b/test/twopunctures.par new file mode 100644 index 0000000..09c5676 --- /dev/null +++ b/test/twopunctures.par @@ -0,0 +1,53 @@ +# $Header$ + +ActiveThorns = "Boundary CartGrid3D Time CoordBase SymBase PUGH PUGHReduce PUGHSlab IOASCII IOBasic IOUtil ADMBase StaticConformal TwoPunctures" + +Cactus::cctk_itlast = 0 + +Time::dtfac = 0.25 + +Grid::type = "byrange" +Grid::domain = "full" +Grid::xmin = -4 +Grid::xmax = 4 +Grid::ymin = -4 +Grid::ymax = 4 +Grid::zmin = -4 +Grid::zmax = 4 +Driver::global_nx = 35 +Driver::global_ny = 35 +Driver::global_nz = 35 + +ADMBase::initial_data = "twopunctures" + +TwoPunctures::npoints_A = 20 +TwoPunctures::npoints_B = 20 +TwoPunctures::npoints_phi = 12 + +TwoPunctures::par_b = 1.5 + +TwoPunctures::par_m_plus = 1.5 +TwoPunctures::par_P_plus[1] = 2.0 +TwoPunctures::par_S_plus[1] = 0.5 +TwoPunctures::par_S_plus[2] = 0.5 + +TwoPunctures::par_m_minus = 1.0 +TwoPunctures::par_P_minus[1] = -2.0 +TwoPunctures::par_S_minus[0] = -1.0 +TwoPunctures::par_S_minus[2] = 1.0 + +ADMBase::metric_type = "static conformal" +#StaticConformal::conformal_storage = "factor+derivs+2nd derivs" +StaticConformal::conformal_storage = "factor" + +ADMBase::lapse_evolution_method = "static" +ADMBase::initial_lapse = "one" + +IO::out_dir = $parfile +IO::out_fileinfo = "axis labels" + +IOBasic::outScalar_every = 1 +IOBasic::outScalar_vars = "staticconformal::psi admbase::metric admbase::curv" + +IOASCII::out1D_every = 1 +IOASCII::out1D_vars = "staticconformal::psi admbase::metric admbase::curv" |