RTModel 2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- RTModel/RTModel.py +293 -0
- RTModel/__init__.py +5 -0
- RTModel/bin/Finalizer.exe +0 -0
- RTModel/bin/InitCond.exe +0 -0
- RTModel/bin/LevMar.exe +0 -0
- RTModel/bin/ModelSelector.exe +0 -0
- RTModel/bin/Reader.exe +0 -0
- RTModel/data/ESPL.tbl +0 -0
- RTModel/data/TemplateLibrary.txt +114 -0
- RTModel/include/LevMarFit.h +81 -0
- RTModel/include/VBBinaryLensingLibrary.h +312 -0
- RTModel/include/bumper.h +32 -0
- RTModel/lib/Finalizer.cpp +412 -0
- RTModel/lib/InitCond.cpp +1398 -0
- RTModel/lib/LevMar.cpp +12 -0
- RTModel/lib/LevMarFit.cpp +1277 -0
- RTModel/lib/ModelSelector.cpp +913 -0
- RTModel/lib/Reader.cpp +670 -0
- RTModel/lib/VBBinaryLensingLibrary.cpp +4986 -0
- RTModel/lib/bumper.cpp +168 -0
- RTModel/plotmodel/__init__.py +5 -0
- RTModel/plotmodel/plotmodel.py +452 -0
- RTModel-2.0.dist-info/LICENSE +165 -0
- RTModel-2.0.dist-info/METADATA +61 -0
- RTModel-2.0.dist-info/RECORD +27 -0
- RTModel-2.0.dist-info/WHEEL +5 -0
- RTModel-2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,4986 @@
|
|
|
1
|
+
// VBBinaryLensing v3.7 (2024)
|
|
2
|
+
//
|
|
3
|
+
// This code has been developed by Valerio Bozza (University of Salerno) and collaborators.
|
|
4
|
+
// Any use of this code for scientific publications should be acknowledged by a citation to:
|
|
5
|
+
// V. Bozza, E. Bachelet, F. Bartolic, T.M. Heintz, A.R. Hoag, M. Hundertmark, MNRAS 479 (2018) 5157
|
|
6
|
+
// If you use astrometry, user-defined limb darkening or Keplerian orbital motion, please cite
|
|
7
|
+
// V. Bozza, E. Khalouei and E. Bachelet (arXiv:2011.04780)
|
|
8
|
+
// The original methods present in v1.0 are described in
|
|
9
|
+
// V. Bozza, MNRAS 408 (2010) 2188
|
|
10
|
+
// Check the repository at http://www.fisica.unisa.it/GravitationAstrophysics/VBBinaryLensing.htm
|
|
11
|
+
// for the newest version.
|
|
12
|
+
//
|
|
13
|
+
// The code relies on the root solving algorithm by Jan Skworon and Andy Gould
|
|
14
|
+
// described in Skowron & Gould arXiv:1203.1034.
|
|
15
|
+
// Please also cite this paper if specifically relevant in your scientific publication.
|
|
16
|
+
// The original Fortran code available on http://www.astrouw.edu.pl/~jskowron/cmplx_roots_sg/
|
|
17
|
+
// has been translated to C++ by Tyler M. Heintz and Ava R. Hoag (2017)
|
|
18
|
+
//
|
|
19
|
+
// GNU Lesser General Public License applies to all parts of this code.
|
|
20
|
+
// Please read the separate LICENSE.txt file for more details.
|
|
21
|
+
//#define _PRINT_ERRORS2
|
|
22
|
+
//#define _ERRORS_ANALYTIC
|
|
23
|
+
|
|
24
|
+
#define _CRT_SECURE_NO_WARNINGS
|
|
25
|
+
|
|
26
|
+
#ifdef _WIN32
|
|
27
|
+
char systemslash = '\\';
|
|
28
|
+
#else
|
|
29
|
+
char systemslash = '/';
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
#include "VBBinaryLensingLibrary.h"
|
|
33
|
+
#define _USE_MATH_DEFINES
|
|
34
|
+
#include <math.h>
|
|
35
|
+
#include <stdio.h>
|
|
36
|
+
#include <stdlib.h>
|
|
37
|
+
#include <string.h>
|
|
38
|
+
|
|
39
|
+
#ifndef __unmanaged
|
|
40
|
+
using namespace VBBinaryLensingLibrary;
|
|
41
|
+
#endif
|
|
42
|
+
//////////////////////////////
|
|
43
|
+
//////////////////////////////
|
|
44
|
+
////////Constructor and destructor
|
|
45
|
+
//////////////////////////////
|
|
46
|
+
//////////////////////////////
|
|
47
|
+
|
|
48
|
+
VBBinaryLensing::VBBinaryLensing() {
|
|
49
|
+
Obj[0] = -0.0397317;
|
|
50
|
+
Obj[1] = 0.998164;
|
|
51
|
+
Obj[2] = -0.045714;
|
|
52
|
+
// reference is ecliptic with x-axis toward the equinox.
|
|
53
|
+
// axial tilt at J2000 is 23:26:21.406 from JPL fundamental ephemeris
|
|
54
|
+
Eq2000[0] = 1;
|
|
55
|
+
Eq2000[1] = Eq2000[2] = Quad2000[0] = North2000[0] = 0;
|
|
56
|
+
Quad2000[1] = 0.9174820003578725;
|
|
57
|
+
Quad2000[2] = -0.3977772982704228;
|
|
58
|
+
North2000[1] = 0.3977772982704228;
|
|
59
|
+
North2000[2] = 0.9174820003578725;
|
|
60
|
+
t0old = 0.;
|
|
61
|
+
Tol = 1.e-2;
|
|
62
|
+
RelTol = 0;
|
|
63
|
+
tsat = 0;
|
|
64
|
+
possat = 0;
|
|
65
|
+
nsat = 0;
|
|
66
|
+
ndatasat = 0;
|
|
67
|
+
satellite = 0;
|
|
68
|
+
parallaxsystem = 0;
|
|
69
|
+
t0_par_fixed = -1;
|
|
70
|
+
t0_par = 7000;
|
|
71
|
+
minannuli = 1;
|
|
72
|
+
curLDprofile = LDlinear;
|
|
73
|
+
a1 = 0;
|
|
74
|
+
npLD = 0;
|
|
75
|
+
LDtab = rCLDtab = CLDtab=0;
|
|
76
|
+
Mag0 = 0;
|
|
77
|
+
NPcrit = 200;
|
|
78
|
+
ESPLoff = true;
|
|
79
|
+
multidark = false;
|
|
80
|
+
astrometry=false;
|
|
81
|
+
mass_luminosity_exponent = 4.0;
|
|
82
|
+
mass_radius_exponent = 0.9;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
VBBinaryLensing::~VBBinaryLensing() {
|
|
86
|
+
if (nsat) {
|
|
87
|
+
for (int i = 0; i<nsat; i++) {
|
|
88
|
+
for (int j = 0; j<ndatasat[i]; j++) free(possat[i][j]);
|
|
89
|
+
free(tsat[i]);
|
|
90
|
+
free(possat[i]);
|
|
91
|
+
}
|
|
92
|
+
free(tsat);
|
|
93
|
+
free(possat);
|
|
94
|
+
free(ndatasat);
|
|
95
|
+
}
|
|
96
|
+
if (npLD > 0) {
|
|
97
|
+
free(LDtab);
|
|
98
|
+
free(rCLDtab);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
//////////////////////////////
|
|
104
|
+
//////////////////////////////
|
|
105
|
+
////////Critical curves and caustics
|
|
106
|
+
//////////////////////////////
|
|
107
|
+
//////////////////////////////
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
_sols *VBBinaryLensing::PlotCrit(double a1, double q1) {
|
|
111
|
+
complex a, q, ej, zr[4], x1, x2;
|
|
112
|
+
_sols *CriticalCurves;
|
|
113
|
+
_curve *Prov, *Prov2, *isso;
|
|
114
|
+
_point *pisso;
|
|
115
|
+
double SD, MD, CD, centeroffset;
|
|
116
|
+
|
|
117
|
+
a = complex(a1, 0.0);
|
|
118
|
+
q = complex(q1, 0.0);
|
|
119
|
+
centeroffset = a1 / 2.0*(1.0 - q1) / (1.0 + q1);
|
|
120
|
+
|
|
121
|
+
CriticalCurves = new _sols;
|
|
122
|
+
for (int i = 0; i<4; i++) {
|
|
123
|
+
Prov = new _curve;
|
|
124
|
+
CriticalCurves->append(Prov);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (int j = 0; j<NPcrit; j++) {
|
|
128
|
+
ej = complex(cos(2 * j*M_PI / NPcrit), -sin(2 * j*M_PI / NPcrit));
|
|
129
|
+
complex coefs[5] = { a*a / 16.0*(4.0 - a*a*ej)*(1.0 + q),a*(q - 1.0),(q + 1.0)*(1.0 + a*a*ej / 2.0),0.0,-(1.0 + q)*ej };
|
|
130
|
+
cmplx_roots_gen(zr, coefs, 4, true, true);
|
|
131
|
+
if (j > 0) {
|
|
132
|
+
Prov2 = new _curve();
|
|
133
|
+
for (int i = 0; i < 4; i++) {
|
|
134
|
+
Prov2->append(zr[i].re + centeroffset, zr[i].im);
|
|
135
|
+
}
|
|
136
|
+
for (Prov = CriticalCurves->first; Prov; Prov = Prov->next) {
|
|
137
|
+
Prov2->closest(Prov->last, &pisso);
|
|
138
|
+
Prov2->drop(pisso);
|
|
139
|
+
Prov->append(pisso);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
Prov = CriticalCurves->first;
|
|
144
|
+
for (int i = 0; i < 4; i++) {
|
|
145
|
+
Prov->append(zr[i].re + centeroffset, zr[i].im);
|
|
146
|
+
Prov = Prov->next;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
Prov = CriticalCurves->first;
|
|
152
|
+
while (Prov->next) {
|
|
153
|
+
SD = *(Prov->first) - *(Prov->last);
|
|
154
|
+
MD = 1.e100;
|
|
155
|
+
isso = 0;
|
|
156
|
+
for (Prov2 = Prov->next; Prov2; Prov2 = Prov2->next) {
|
|
157
|
+
CD = *(Prov2->first) - *(Prov->last);
|
|
158
|
+
if (CD<MD) {
|
|
159
|
+
MD = CD;
|
|
160
|
+
isso = Prov2;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (MD<SD) {
|
|
164
|
+
CriticalCurves->drop(isso);
|
|
165
|
+
Prov->join(isso);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
Prov = Prov->next;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Caustics
|
|
173
|
+
|
|
174
|
+
for (Prov = CriticalCurves->last; Prov; Prov = Prov->prev) {
|
|
175
|
+
Prov2 = new _curve;
|
|
176
|
+
for (_point *scanpoint = Prov->first; scanpoint; scanpoint = scanpoint->next) {
|
|
177
|
+
x1 = complex(scanpoint->x1 - centeroffset, 0.0);
|
|
178
|
+
x2 = complex(scanpoint->x2, 0.0);
|
|
179
|
+
Prov2->append(real(_L1) + centeroffset, real(_L2));
|
|
180
|
+
}
|
|
181
|
+
CriticalCurves->append(Prov2);
|
|
182
|
+
}
|
|
183
|
+
return CriticalCurves;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
void VBBinaryLensing::PrintCau(double a, double q, double y1, double y2, double rho) {
|
|
187
|
+
_sols *CriticalCurves;
|
|
188
|
+
_curve *scancurve;
|
|
189
|
+
_point *scanpoint;
|
|
190
|
+
FILE *f;
|
|
191
|
+
int ncc;
|
|
192
|
+
|
|
193
|
+
CriticalCurves = PlotCrit(a, q);
|
|
194
|
+
f = fopen("outcurves.causticdata", "w");
|
|
195
|
+
fprintf(f, "%.16lf %.16lf %.16lf\n", y1,y2,rho);
|
|
196
|
+
ncc = CriticalCurves->length / 2;
|
|
197
|
+
scancurve = CriticalCurves->first;
|
|
198
|
+
for (int i = 0; i<2*ncc; i++) {
|
|
199
|
+
// scancurve = scancurve->next;
|
|
200
|
+
//}
|
|
201
|
+
|
|
202
|
+
//for (int i = 0; i<ncc; i++) {
|
|
203
|
+
fprintf(f, "Curve: %d\n", i + 1);
|
|
204
|
+
for (scanpoint = scancurve->first; scanpoint; scanpoint = scanpoint->next) {
|
|
205
|
+
fprintf(f, "%.16lf %.16lf\n", scanpoint->x1, scanpoint->x2);
|
|
206
|
+
}
|
|
207
|
+
scancurve = scancurve->next;
|
|
208
|
+
}
|
|
209
|
+
fclose(f);
|
|
210
|
+
delete CriticalCurves;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
//////////////////////////////
|
|
215
|
+
//////////////////////////////
|
|
216
|
+
////////Parallax settings and computation
|
|
217
|
+
//////////////////////////////
|
|
218
|
+
//////////////////////////////
|
|
219
|
+
|
|
220
|
+
void VBBinaryLensing::SetObjectCoordinates(char* modelfile, char* sateltabledir) {
|
|
221
|
+
double RA, Dec, dis, phiprec;
|
|
222
|
+
FILE* f;
|
|
223
|
+
char CoordinateString[512];
|
|
224
|
+
char filename[256];
|
|
225
|
+
int ic;
|
|
226
|
+
|
|
227
|
+
f = fopen(modelfile, "r");
|
|
228
|
+
if (f != 0) {
|
|
229
|
+
fscanf(f, "%[^\n]s", CoordinateString);
|
|
230
|
+
fclose(f);
|
|
231
|
+
SetObjectCoordinates(CoordinateString);
|
|
232
|
+
|
|
233
|
+
// Looking for satellite table files in the specified directory
|
|
234
|
+
sprintf(filename, "%s%csatellite*.txt", sateltabledir, systemslash);
|
|
235
|
+
nsat = 0;
|
|
236
|
+
for (unsigned char c = 32; c < 255; c++) {
|
|
237
|
+
filename[strlen(filename) - 5] = c;
|
|
238
|
+
f = fopen(filename, "r");
|
|
239
|
+
if (f != 0) {
|
|
240
|
+
nsat++;
|
|
241
|
+
fclose(f);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
tsat = (double**)malloc(sizeof(double*) * nsat);
|
|
247
|
+
possat = (double***)malloc(sizeof(double**) * nsat);
|
|
248
|
+
ndatasat = (int*)malloc(sizeof(int) * nsat);
|
|
249
|
+
|
|
250
|
+
// Reading satellite table files
|
|
251
|
+
ic = 0;
|
|
252
|
+
for (unsigned char c = 32; c < 255; c++) {
|
|
253
|
+
filename[strlen(filename) - 5] = c;
|
|
254
|
+
f = fopen(filename, "r");
|
|
255
|
+
if (f != 0) {
|
|
256
|
+
int flag2 = 0;
|
|
257
|
+
long startpos = 0;
|
|
258
|
+
char teststring[1000];
|
|
259
|
+
ndatasat[ic] = 1;
|
|
260
|
+
|
|
261
|
+
// Finding start of data
|
|
262
|
+
while (!feof(f)) {
|
|
263
|
+
fscanf(f, "%s", teststring);
|
|
264
|
+
if (!feof(f)) {
|
|
265
|
+
fseek(f, 1, SEEK_CUR);
|
|
266
|
+
teststring[5] = 0;
|
|
267
|
+
if (strcmp(teststring, "$$SOE") == 0) {
|
|
268
|
+
flag2 = 1;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Finding end of data
|
|
274
|
+
if (flag2) {
|
|
275
|
+
flag2 = 0;
|
|
276
|
+
startpos = ftell(f);
|
|
277
|
+
while (!feof(f)) {
|
|
278
|
+
fscanf(f, "%[^\n]s", teststring);
|
|
279
|
+
if (!feof(f)) {
|
|
280
|
+
fseek(f, 1, SEEK_CUR);
|
|
281
|
+
teststring[5] = 0;
|
|
282
|
+
if (strcmp(teststring, "$$EOE") == 0) {
|
|
283
|
+
flag2 = 1;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
ndatasat[ic]++;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Allocating memory according to the length of the table
|
|
294
|
+
tsat[ic] = (double*)malloc(sizeof(double) * ndatasat[ic]);
|
|
295
|
+
possat[ic] = (double**)malloc(sizeof(double*) * ndatasat[ic]);
|
|
296
|
+
for (int j = 0; j < ndatasat[ic]; j++) {
|
|
297
|
+
possat[ic][j] = (double*)malloc(sizeof(double) * 3);
|
|
298
|
+
}
|
|
299
|
+
ndatasat[ic]--;
|
|
300
|
+
|
|
301
|
+
// Reading data
|
|
302
|
+
if (f) {
|
|
303
|
+
fseek(f, startpos, SEEK_SET);
|
|
304
|
+
for (int id = 0; id < ndatasat[ic]; id++) {
|
|
305
|
+
|
|
306
|
+
if (fscanf(f, "%lf %lf %lf %lf %lf", &(tsat[ic][id]), &RA, &Dec, &dis, &phiprec) == 5) {
|
|
307
|
+
tsat[ic][id] -= 2450000;
|
|
308
|
+
RA *= M_PI / 180;
|
|
309
|
+
Dec *= M_PI / 180;
|
|
310
|
+
for (int i = 0; i < 3; i++) {
|
|
311
|
+
possat[ic][id][i] = dis * (cos(RA) * cos(Dec) * Eq2000[i] + sin(RA) * cos(Dec) * Quad2000[i] + sin(Dec) * North2000[i]);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
ndatasat[ic] = id;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
fclose(f);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
ic++;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
printf("\nFile not found!\n");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
void VBBinaryLensing::SetObjectCoordinates(char *CoordinateString) {
|
|
332
|
+
double RA, Dec, hr, mn, sc, deg, pr, ssc;
|
|
333
|
+
|
|
334
|
+
if (nsat) {
|
|
335
|
+
for (int i = 0; i<nsat; i++) {
|
|
336
|
+
for (int j = 0; j<ndatasat[i]; j++) free(possat[i][j]);
|
|
337
|
+
free(tsat[i]);
|
|
338
|
+
free(possat[i]);
|
|
339
|
+
}
|
|
340
|
+
free(tsat);
|
|
341
|
+
free(possat);
|
|
342
|
+
free(ndatasat);
|
|
343
|
+
}
|
|
344
|
+
sscanf(CoordinateString, "%lf:%lf:%lf %lf:%lf:%lf", &hr, &mn, &sc, °, &pr, &ssc);
|
|
345
|
+
RA = (hr + mn / 60 + sc / 3600) * M_PI / 12,
|
|
346
|
+
Dec = (fabs(deg) + pr / 60 + ssc / 3600) * M_PI / 180;
|
|
347
|
+
if (deg < 0) Dec = -Dec;
|
|
348
|
+
|
|
349
|
+
for (int i = 0; i < 3; i++) {
|
|
350
|
+
Obj[i] = (cos(RA) * cos(Dec) * Eq2000[i] + sin(RA) * cos(Dec) * Quad2000[i] + sin(Dec) * North2000[i]);
|
|
351
|
+
rad[i] = Eq2000[i];
|
|
352
|
+
tang[i] = North2000[i];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (t0_par_fixed == -1) t0_par_fixed = 0;
|
|
356
|
+
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
void VBBinaryLensing::ComputeParallax(double t, double t0, double *Et) {
|
|
360
|
+
static double a0 = 1.00000261, adot = 0.00000562; // Ephemeris from JPL website
|
|
361
|
+
static double e0 = 0.01671123, edot = -0.00004392;
|
|
362
|
+
static double inc0 = -0.00001531, incdot = -0.01294668;
|
|
363
|
+
static double L0 = 100.46457166, Ldot = 35999.37244981;
|
|
364
|
+
static double om0 = 102.93768193, omdot = 0.32327364;
|
|
365
|
+
static double deg = M_PI / 180;
|
|
366
|
+
static double a, e, inc, L, om, M, EE, dE, dM;
|
|
367
|
+
static double x1, y1, vx, vy, Ear[3], vEar[3];
|
|
368
|
+
static double Et0[2], vt0[2], r, sp, ty, Spit;
|
|
369
|
+
int c = 0, ic;
|
|
370
|
+
|
|
371
|
+
if (t0_par_fixed == 0) t0_par = t0;
|
|
372
|
+
if (t0_par_fixed == -1) {
|
|
373
|
+
printf("\nUse SetObjectCoordinates to input target coordinates");
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
|
|
377
|
+
if (t0_par != t0old) {
|
|
378
|
+
t0old = t0_par;
|
|
379
|
+
ty = (t0_par - 1545) / 36525.0;
|
|
380
|
+
|
|
381
|
+
a = a0 + adot*ty;
|
|
382
|
+
e = e0 + edot*ty;
|
|
383
|
+
inc = (inc0 + incdot*ty)*deg;
|
|
384
|
+
L = (L0 + Ldot*ty)*deg;
|
|
385
|
+
om = (om0 + omdot*ty)*deg;
|
|
386
|
+
|
|
387
|
+
M = L - om;
|
|
388
|
+
M -= floor((M + M_PI) / (2 * M_PI)) * 2 * M_PI;
|
|
389
|
+
|
|
390
|
+
EE = M + e*sin(M);
|
|
391
|
+
dE = 1;
|
|
392
|
+
while (fabs(dE) > 1.e-8) {
|
|
393
|
+
dM = M - (EE - e*sin(EE));
|
|
394
|
+
dE = dM / (1 - e*cos(EE));
|
|
395
|
+
EE += dE;
|
|
396
|
+
}
|
|
397
|
+
x1 = a*(cos(EE) - e);
|
|
398
|
+
y1 = a*sqrt(1 - e*e)*sin(EE);
|
|
399
|
+
// r=a*(1-e*cos(EE));
|
|
400
|
+
vx = -a / (1 - e*cos(EE))*sin(EE)*Ldot*deg / 36525;
|
|
401
|
+
vy = a / (1 - e*cos(EE))*cos(EE)*sqrt(1 - e*e)*Ldot*deg / 36525;
|
|
402
|
+
|
|
403
|
+
Ear[0] = x1*cos(om) - y1*sin(om);
|
|
404
|
+
Ear[1] = x1*sin(om)*cos(inc) + y1*cos(om)*cos(inc);
|
|
405
|
+
Ear[2] = x1*sin(om)*sin(inc) + y1*cos(om)*sin(inc);
|
|
406
|
+
vEar[0] = vx*cos(om) - vy*sin(om);
|
|
407
|
+
vEar[1] = vx*sin(om)*cos(inc) + vy*cos(om)*cos(inc);
|
|
408
|
+
vEar[2] = vx*sin(om)*sin(inc) + vy*cos(om)*sin(inc);
|
|
409
|
+
|
|
410
|
+
sp = 0;
|
|
411
|
+
switch (parallaxsystem) {
|
|
412
|
+
case 1:
|
|
413
|
+
for (int i = 0; i < 3; i++) sp += North2000[i] * Obj[i];
|
|
414
|
+
for (int i = 0; i < 3; i++) rad[i] = -North2000[i] + sp*Obj[i];
|
|
415
|
+
break;
|
|
416
|
+
default:
|
|
417
|
+
for (int i = 0; i < 3; i++) sp += Ear[i] * Obj[i];
|
|
418
|
+
for (int i = 0; i < 3; i++) rad[i] = Ear[i] - sp*Obj[i];
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
r = sqrt(rad[0] * rad[0] + rad[1] * rad[1] + rad[2] * rad[2]);
|
|
423
|
+
rad[0] /= r;
|
|
424
|
+
rad[1] /= r;
|
|
425
|
+
rad[2] /= r;
|
|
426
|
+
tang[0] = rad[1] * Obj[2] - rad[2] * Obj[1];
|
|
427
|
+
tang[1] = rad[2] * Obj[0] - rad[0] * Obj[2];
|
|
428
|
+
tang[2] = rad[0] * Obj[1] - rad[1] * Obj[0];
|
|
429
|
+
|
|
430
|
+
Et0[0] = Et0[1] = vt0[0] = vt0[1] = 0;
|
|
431
|
+
for (int i = 0; i < 3; i++) {
|
|
432
|
+
Et0[0] += Ear[i] * rad[i];
|
|
433
|
+
Et0[1] += Ear[i] * tang[i];
|
|
434
|
+
vt0[0] += vEar[i] * rad[i];
|
|
435
|
+
vt0[1] += vEar[i] * tang[i];
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
ty = (t - 1545) / 36525.0;
|
|
440
|
+
|
|
441
|
+
a = a0 + adot*ty;
|
|
442
|
+
e = e0 + edot*ty;
|
|
443
|
+
inc = (inc0 + incdot*ty)*deg;
|
|
444
|
+
L = (L0 + Ldot*ty)*deg;
|
|
445
|
+
om = (om0 + omdot*ty)*deg;
|
|
446
|
+
|
|
447
|
+
M = L - om;
|
|
448
|
+
M -= floor((M + M_PI) / (2 * M_PI)) * 2 * M_PI;
|
|
449
|
+
|
|
450
|
+
EE = M + e*sin(M);
|
|
451
|
+
dE = 1;
|
|
452
|
+
while (dE > 1.e-8) {
|
|
453
|
+
dM = M - (EE - e*sin(EE));
|
|
454
|
+
dE = dM / (1 - e*cos(EE));
|
|
455
|
+
EE += dE;
|
|
456
|
+
}
|
|
457
|
+
x1 = a*(cos(EE) - e);
|
|
458
|
+
y1 = a*sqrt(1 - e*e)*sin(EE);
|
|
459
|
+
// r=a*(1-e*cos(EE));
|
|
460
|
+
|
|
461
|
+
Ear[0] = x1*cos(om) - y1*sin(om);
|
|
462
|
+
Ear[1] = x1*sin(om)*cos(inc) + y1*cos(om)*cos(inc);
|
|
463
|
+
Ear[2] = x1*sin(om)*sin(inc) + y1*cos(om)*sin(inc);
|
|
464
|
+
Et[0] = Et[1] = 0;
|
|
465
|
+
for (int i = 0; i < 3; i++) {
|
|
466
|
+
Et[0] += Ear[i] * rad[i];
|
|
467
|
+
Et[1] += Ear[i] * tang[i];
|
|
468
|
+
}
|
|
469
|
+
Et[0] += -Et0[0] - vt0[0] * (t - t0_par);
|
|
470
|
+
Et[1] += -Et0[1] - vt0[1] * (t - t0_par);
|
|
471
|
+
|
|
472
|
+
if (satellite > 0 && satellite <= nsat) {
|
|
473
|
+
if (ndatasat[satellite - 1] > 2) {
|
|
474
|
+
int left, right;
|
|
475
|
+
if (t < tsat[satellite - 1][0]) {
|
|
476
|
+
ic = 0;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
if (t > tsat[satellite - 1][ndatasat[satellite - 1] - 1]) {
|
|
480
|
+
ic = ndatasat[satellite - 1] - 2;
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
left = 0;
|
|
484
|
+
right = ndatasat[satellite - 1] - 1;
|
|
485
|
+
while (right - left > 1) {
|
|
486
|
+
ic = (right + left) / 2;
|
|
487
|
+
if (tsat[satellite - 1][ic] > t) {
|
|
488
|
+
right = ic;
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
left = ic;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
ic = left;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
ty = t - tsat[satellite - 1][ic];
|
|
498
|
+
for (int i = 0; i < 3; i++) {
|
|
499
|
+
Spit = possat[satellite - 1][ic][i] * (1 - ty) + possat[satellite - 1][ic + 1][i] * ty;
|
|
500
|
+
Et[0] += Spit*rad[i];
|
|
501
|
+
Et[1] += Spit*tang[i];
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
//////////////////////////////
|
|
509
|
+
//////////////////////////////
|
|
510
|
+
////////Basic magnification functions
|
|
511
|
+
//////////////////////////////
|
|
512
|
+
//////////////////////////////
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
double VBBinaryLensing::BinaryMag0(double a1, double q1, double y1v, double y2v, _sols **Images) {
|
|
516
|
+
static complex a, q, m1, m2, y;
|
|
517
|
+
static double av = -1.0, qv = -1.0;
|
|
518
|
+
static complex coefs[24], d1, d2, dy, dJ, dz;
|
|
519
|
+
static double Mag, Ai;
|
|
520
|
+
|
|
521
|
+
static _theta *stheta;
|
|
522
|
+
static _curve *Prov, *Prov2;
|
|
523
|
+
static _point *scan1, *scan2;
|
|
524
|
+
|
|
525
|
+
Mag = Ai = -1.0;
|
|
526
|
+
stheta = new _theta(-1.);
|
|
527
|
+
if ((a1 != av) || (q1 != qv)) {
|
|
528
|
+
av = a1;
|
|
529
|
+
qv = q1;
|
|
530
|
+
if (q1<1) {
|
|
531
|
+
a = complex(-a1, 0);
|
|
532
|
+
q = complex(q1, 0);
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
a = complex(a1, 0);
|
|
536
|
+
q = complex(1 / q1, 0);
|
|
537
|
+
}
|
|
538
|
+
m1 = 1.0 / (1.0 + q);
|
|
539
|
+
m2 = q*m1;
|
|
540
|
+
|
|
541
|
+
coefs[20] = a;
|
|
542
|
+
coefs[21] = m1;
|
|
543
|
+
coefs[22] = m2;
|
|
544
|
+
coefs[6] = a*a;
|
|
545
|
+
coefs[7] = coefs[6] * a;
|
|
546
|
+
coefs[8] = m2*m2;
|
|
547
|
+
coefs[9] = coefs[6] * coefs[8];
|
|
548
|
+
coefs[10] = a*m2;
|
|
549
|
+
coefs[11] = a*m1;
|
|
550
|
+
coefs[23] = 0;
|
|
551
|
+
|
|
552
|
+
}
|
|
553
|
+
y = complex(y1v, y2v);
|
|
554
|
+
(*Images) = new _sols;
|
|
555
|
+
corrquad = corrquad2 = 0;
|
|
556
|
+
safedist = 10;
|
|
557
|
+
Prov = NewImages(y, coefs, stheta);
|
|
558
|
+
if (Prov->length == 0) {
|
|
559
|
+
delete Prov;
|
|
560
|
+
delete stheta;
|
|
561
|
+
return -1;
|
|
562
|
+
}
|
|
563
|
+
if (q.re < 0.01) {
|
|
564
|
+
safedist = y1v + coefs[11].re-1/a.re;
|
|
565
|
+
safedist *= safedist;
|
|
566
|
+
safedist += y2v*y2v - 36 * q1/(a1*a1);
|
|
567
|
+
}
|
|
568
|
+
Mag = 0.;
|
|
569
|
+
astrox1=0.;
|
|
570
|
+
astrox2=0.;
|
|
571
|
+
nim0 = 0;
|
|
572
|
+
for (scan1 = Prov->first; scan1; scan1 = scan2) {
|
|
573
|
+
scan2 = scan1->next;
|
|
574
|
+
Prov2 = new _curve(scan1);
|
|
575
|
+
//Prov2->append(scan1->x1, scan1->x2);
|
|
576
|
+
//Prov2->last->theta = stheta;
|
|
577
|
+
//Prov2->last->d = Prov2->first->d;
|
|
578
|
+
//Prov2->last->dJ = Prov2->first->dJ;
|
|
579
|
+
//Prov2->last->J2 = Prov2->first->J2;
|
|
580
|
+
//Prov2->last->ds = Prov2->first->ds;
|
|
581
|
+
(*Images)->append(Prov2);
|
|
582
|
+
Ai=fabs(1 / scan1->dJ);
|
|
583
|
+
Mag += Ai;
|
|
584
|
+
if(astrometry){
|
|
585
|
+
astrox1 +=scan1->x1*Ai;
|
|
586
|
+
astrox2 +=(scan1->x2)*Ai;
|
|
587
|
+
}
|
|
588
|
+
nim0++;
|
|
589
|
+
}
|
|
590
|
+
Prov->length = 0;
|
|
591
|
+
delete Prov;
|
|
592
|
+
delete stheta;
|
|
593
|
+
if(astrometry){
|
|
594
|
+
astrox1 /= (Mag);
|
|
595
|
+
astrox1 -=coefs[11].re;
|
|
596
|
+
astrox2 /= (Mag);
|
|
597
|
+
}
|
|
598
|
+
NPS = 1;
|
|
599
|
+
return Mag;
|
|
600
|
+
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
double VBBinaryLensing::BinaryMag0(double a1, double q1, double y1v, double y2v) {
|
|
604
|
+
static _sols *images;
|
|
605
|
+
static double mag;
|
|
606
|
+
mag = BinaryMag0(a1, q1, y1v, y2v, &images);
|
|
607
|
+
delete images;
|
|
608
|
+
return mag;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
double VBBinaryLensing::BinaryMagSafe(double s, double q, double y1v, double y2v, double RS, _sols **images) {
|
|
612
|
+
static double Mag, mag1, mag2, RSi, RSo, delta1,delta2;
|
|
613
|
+
static int NPSsafe;
|
|
614
|
+
Mag = BinaryMag(s, q, y1v, y2v, RS,Tol,images);
|
|
615
|
+
RSi = RS;
|
|
616
|
+
RSo = RS;
|
|
617
|
+
NPSsafe = NPS;
|
|
618
|
+
if (Mag < 0) {
|
|
619
|
+
mag1 = -1;
|
|
620
|
+
delta1 = 3.33333333e-8;
|
|
621
|
+
while (mag1 < 0.1 && RSi>=0) {
|
|
622
|
+
delete *images;
|
|
623
|
+
delta1 *= 3.;
|
|
624
|
+
RSi = RS - delta1;
|
|
625
|
+
mag1 = (RSi > 0) ? BinaryMag(s, q, y1v, y2v, RSi, Tol, images) : BinaryMag0(s,q,y1v,y2v,images);
|
|
626
|
+
// printf("\n-safe1 %lf %lf %d", RSi, mag1, NPS);
|
|
627
|
+
NPSsafe += NPS;
|
|
628
|
+
}
|
|
629
|
+
if(mag1<0) mag1=1.0;
|
|
630
|
+
mag2 = -1;
|
|
631
|
+
delta2 = 3.33333333e-8;
|
|
632
|
+
while (mag2 < 0.1) {
|
|
633
|
+
delta2 *= 3.;
|
|
634
|
+
RSo = RS + delta2;
|
|
635
|
+
delete *images;
|
|
636
|
+
mag2 = BinaryMag(s, q, y1v, y2v, RSo, Tol, images);
|
|
637
|
+
// printf("\n-safe2 %lf %lf %d", RSo,mag2,NPS);
|
|
638
|
+
NPSsafe += NPS;
|
|
639
|
+
}
|
|
640
|
+
Mag = (mag1*delta2 + mag2*delta1)/(delta1+delta2);
|
|
641
|
+
}
|
|
642
|
+
NPS = NPSsafe;
|
|
643
|
+
|
|
644
|
+
return Mag;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
double VBBinaryLensing::BinaryMag(double a1, double q1, double y1v, double y2v, double RSv, double Tol, _sols **Images) {
|
|
648
|
+
static complex a, q, m1, m2, y0, y, yc, z, zc;
|
|
649
|
+
static double av = -1.0, qv = -1.0;
|
|
650
|
+
static complex coefs[24], d1, d2, dy, dJ, dz;
|
|
651
|
+
static double thoff = 0.01020304,errbuff;
|
|
652
|
+
static double Mag, th;
|
|
653
|
+
////////////////////////////
|
|
654
|
+
static double errimage, maxerr, currerr, Magold;
|
|
655
|
+
static int NPSmax, flag, NPSold,flagbad,flagbadmax=3;
|
|
656
|
+
static _curve *Prov, *Prov2;
|
|
657
|
+
static _point *scan1, *scan2;
|
|
658
|
+
static _thetas *Thetas;
|
|
659
|
+
static _theta *stheta, *itheta;
|
|
660
|
+
|
|
661
|
+
#ifdef _PRINT_TIMES
|
|
662
|
+
static double tim0, tim1;
|
|
663
|
+
#endif
|
|
664
|
+
|
|
665
|
+
// Initialization of the equation coefficients
|
|
666
|
+
|
|
667
|
+
if ((a1 != av) || (q1 != qv)) {
|
|
668
|
+
av = a1;
|
|
669
|
+
qv = q1;
|
|
670
|
+
if (q1<1) {
|
|
671
|
+
a = complex(-a1, 0);
|
|
672
|
+
q = complex(q1, 0);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
a = complex(a1, 0);
|
|
676
|
+
q = complex(1 / q1, 0);
|
|
677
|
+
}
|
|
678
|
+
m1 = 1.0 / (1.0 + q);
|
|
679
|
+
m2 = q*m1;
|
|
680
|
+
|
|
681
|
+
coefs[20] = a;
|
|
682
|
+
coefs[21] = m1;
|
|
683
|
+
coefs[22] = m2;
|
|
684
|
+
coefs[6] = a*a;
|
|
685
|
+
coefs[7] = coefs[6] * a;
|
|
686
|
+
coefs[8] = m2*m2;
|
|
687
|
+
coefs[9] = coefs[6] * coefs[8];
|
|
688
|
+
coefs[10] = a*m2;
|
|
689
|
+
coefs[11] = a*m1;
|
|
690
|
+
|
|
691
|
+
}
|
|
692
|
+
coefs[23] = RSv;
|
|
693
|
+
|
|
694
|
+
y0 = complex(y1v, y2v);
|
|
695
|
+
NPS = 1;
|
|
696
|
+
if (Tol>1.) {
|
|
697
|
+
errimage = 0.;
|
|
698
|
+
NPSmax = (int)(Tol);
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
errimage = Tol*M_PI*RSv*RSv;
|
|
702
|
+
NPSmax =10000; // era 32000
|
|
703
|
+
}
|
|
704
|
+
errbuff = 0;
|
|
705
|
+
|
|
706
|
+
// Calculation of the images
|
|
707
|
+
|
|
708
|
+
(*Images) = new _sols;
|
|
709
|
+
Thetas = new _thetas;
|
|
710
|
+
th = thoff;
|
|
711
|
+
stheta = Thetas->insert(th);
|
|
712
|
+
stheta->maxerr = 1.e100;
|
|
713
|
+
y = y0 + complex(RSv*cos(thoff), RSv*sin(thoff));
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
#ifdef _PRINT_TIMES
|
|
717
|
+
tim0 = Environment::TickCount;
|
|
718
|
+
#endif
|
|
719
|
+
flag = 0;
|
|
720
|
+
flagbad = 0;
|
|
721
|
+
while (flag == 0) {
|
|
722
|
+
Prov = NewImages(y, coefs, stheta);
|
|
723
|
+
if (Prov->length > 0) {
|
|
724
|
+
flag = 1;
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
delete Prov;
|
|
728
|
+
stheta->th += 0.01;
|
|
729
|
+
if (stheta->th > 2.0 * M_PI) {
|
|
730
|
+
delete Thetas;
|
|
731
|
+
return -1;
|
|
732
|
+
}
|
|
733
|
+
y = y0 + complex(RSv*cos(stheta->th), RSv*sin(stheta->th));
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
#ifdef _PRINT_TIMES
|
|
737
|
+
tim1 = Environment::TickCount;
|
|
738
|
+
GM += tim1 - tim0;
|
|
739
|
+
#endif
|
|
740
|
+
stheta = Thetas->insert(2.0*M_PI + Thetas->first->th);
|
|
741
|
+
stheta->maxerr = 0.;
|
|
742
|
+
stheta->Mag = 0.;
|
|
743
|
+
stheta->astrox1 = 0.;
|
|
744
|
+
stheta->astrox2 = 0.;
|
|
745
|
+
stheta->errworst = Thetas->first->errworst;
|
|
746
|
+
for (scan1 = Prov->first; scan1; scan1 = scan2) {
|
|
747
|
+
scan2 = scan1->next;
|
|
748
|
+
Prov2 = new _curve(scan1);
|
|
749
|
+
Prov2->append(scan1->x1, scan1->x2);
|
|
750
|
+
Prov2->last->theta = stheta;
|
|
751
|
+
Prov2->last->d = Prov2->first->d;
|
|
752
|
+
Prov2->last->dJ = Prov2->first->dJ;
|
|
753
|
+
Prov2->last->ds = Prov2->first->ds;
|
|
754
|
+
(*Images)->append(Prov2);
|
|
755
|
+
}
|
|
756
|
+
Prov->length = 0;
|
|
757
|
+
delete Prov;
|
|
758
|
+
|
|
759
|
+
th = M_PI + Thetas->first->th;
|
|
760
|
+
flag = 0;
|
|
761
|
+
Magold = -1.;
|
|
762
|
+
NPSold = 2;
|
|
763
|
+
currerr = 1.e100;
|
|
764
|
+
do {
|
|
765
|
+
stheta = Thetas->insert(th);
|
|
766
|
+
y = y0 + complex(RSv*cos(th), RSv*sin(th));
|
|
767
|
+
#ifdef _PRINT_TIMES
|
|
768
|
+
tim0 = Environment::TickCount;
|
|
769
|
+
#endif
|
|
770
|
+
//if (NPS == 422) {
|
|
771
|
+
// NPS = NPS;
|
|
772
|
+
//}
|
|
773
|
+
|
|
774
|
+
Prov = NewImages(y, coefs, stheta);
|
|
775
|
+
#ifdef _PRINT_TIMES
|
|
776
|
+
tim1 = Environment::TickCount;
|
|
777
|
+
GM += tim1 - tim0;
|
|
778
|
+
#endif
|
|
779
|
+
if (Prov->length > 0) {
|
|
780
|
+
flagbad = 0;
|
|
781
|
+
OrderImages((*Images), Prov);
|
|
782
|
+
if ((stheta->th - stheta->prev->th)*RSv < 1.e-11/* || stheta->maxerr > jumperrfactor * currerr || stheta->prev->maxerr > jumperrfactor * currerr*/) {
|
|
783
|
+
errbuff += stheta->maxerr + stheta->prev->maxerr;
|
|
784
|
+
stheta->maxerr = 0;
|
|
785
|
+
stheta->prev->maxerr = 0;
|
|
786
|
+
}
|
|
787
|
+
} else {
|
|
788
|
+
delete Prov;
|
|
789
|
+
flagbad++;
|
|
790
|
+
if (flagbad == flagbadmax) {
|
|
791
|
+
if (NPS < 16) {
|
|
792
|
+
delete Thetas;
|
|
793
|
+
return -1;
|
|
794
|
+
}
|
|
795
|
+
errbuff += stheta->prev->maxerr;
|
|
796
|
+
stheta->prev->maxerr = 0;
|
|
797
|
+
NPS--;
|
|
798
|
+
NPSmax--;
|
|
799
|
+
}
|
|
800
|
+
else {
|
|
801
|
+
th = (th - stheta->prev->th >= stheta->next->th - th) ? (th + flagbad * stheta->prev->th) / (1 + flagbad) : (th + flagbad * stheta->next->th) / (1 + flagbad);
|
|
802
|
+
}
|
|
803
|
+
Thetas->remove(stheta);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
if (flagbad == 0 || flagbad == flagbadmax) {
|
|
807
|
+
maxerr = currerr = Mag = 0.;
|
|
808
|
+
|
|
809
|
+
astrox1 = astrox2 = 0.;
|
|
810
|
+
stheta = Thetas->first;
|
|
811
|
+
|
|
812
|
+
while (stheta->next) {
|
|
813
|
+
currerr += stheta->maxerr;
|
|
814
|
+
Mag += stheta->Mag;
|
|
815
|
+
|
|
816
|
+
if (astrometry) {
|
|
817
|
+
astrox1 += stheta->astrox1;
|
|
818
|
+
astrox2 += stheta->astrox2;
|
|
819
|
+
}
|
|
820
|
+
#ifndef _uniform
|
|
821
|
+
if (stheta->maxerr > maxerr) {
|
|
822
|
+
maxerr = stheta->maxerr;
|
|
823
|
+
#else
|
|
824
|
+
if (stheta->next->th * 0.99999 - stheta->th > maxerr) {
|
|
825
|
+
maxerr = stheta->next->th - stheta->th;
|
|
826
|
+
#endif
|
|
827
|
+
itheta = stheta;
|
|
828
|
+
}
|
|
829
|
+
stheta = stheta->next;
|
|
830
|
+
#ifdef _selectimage
|
|
831
|
+
if ((NPS == NPSmax - 1) && (fabs(floor(stheta->th / M_PI * _npoints / 2 + 0.5) - stheta->th / M_PI * _npoints / 2) < 1.e-8)) {
|
|
832
|
+
printf("%d %.15le\n", (int)floor(stheta->th / M_PI * _npoints / 2 + 0.5), Mag);
|
|
833
|
+
}
|
|
834
|
+
#endif
|
|
835
|
+
}
|
|
836
|
+
th = (itheta->th + itheta->next->th) / 2;
|
|
837
|
+
NPS++;
|
|
838
|
+
#ifndef _uniform
|
|
839
|
+
if (fabs(Magold - Mag) * 2 < errimage) {
|
|
840
|
+
flag++;
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
flag = 0;
|
|
844
|
+
Magold = Mag;
|
|
845
|
+
NPSold = NPS + 8;
|
|
846
|
+
}
|
|
847
|
+
#else
|
|
848
|
+
currerr = 2 * errimage;
|
|
849
|
+
if (NPS == 2 * NPSold) {
|
|
850
|
+
if (fabs(Magold - Mag) * 2 < errimage) {
|
|
851
|
+
flag = NPSold;
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
flag = 0;
|
|
855
|
+
NPSold = NPS;
|
|
856
|
+
Magold = Mag;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
#endif
|
|
860
|
+
#ifdef _PRINT_ERRORS2
|
|
861
|
+
printf("\nNPS= %d Mag = %lf maxerr= %lg currerr =%lg th = %lf", NPS, Mag / (M_PI * RSv * RSv), maxerr / (M_PI * RSv * RSv), currerr / (M_PI * RSv * RSv), th);
|
|
862
|
+
#endif
|
|
863
|
+
}
|
|
864
|
+
} while ((currerr > errimage) && (currerr > RelTol * Mag) && (NPS < NPSmax) && ((flag < NPSold)/* || NPS<8 ||(currerr>10*errimage)*/)/*&&(flagits)*/);
|
|
865
|
+
if(astrometry){
|
|
866
|
+
astrox1 /= (Mag);
|
|
867
|
+
astrox2 /= (Mag);
|
|
868
|
+
}
|
|
869
|
+
Mag /= (M_PI*RSv*RSv);
|
|
870
|
+
therr = (currerr+errbuff) / (M_PI*RSv*RSv);
|
|
871
|
+
|
|
872
|
+
delete Thetas;
|
|
873
|
+
// if (NPS == NPSmax) return 1.e100*Tol; // Only for testing
|
|
874
|
+
return Mag;
|
|
875
|
+
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
double VBBinaryLensing::BinaryMag(double a1, double q1, double y1v, double y2v, double RSv, double Tol) {
|
|
879
|
+
static _sols *images;
|
|
880
|
+
static double mag;
|
|
881
|
+
mag = BinaryMag(a1, q1, y1v, y2v, RSv, Tol, &images);
|
|
882
|
+
delete images;
|
|
883
|
+
return mag;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
double VBBinaryLensing::BinaryMag2(double s, double q, double y1v, double y2v, double rho) {
|
|
887
|
+
static double Mag, rho2, y2a;//, sms , dy1, dy2;
|
|
888
|
+
static int c;
|
|
889
|
+
static _sols *Images;
|
|
890
|
+
|
|
891
|
+
c = 0;
|
|
892
|
+
|
|
893
|
+
y2a = fabs(y2v);
|
|
894
|
+
|
|
895
|
+
Mag0 = BinaryMag0(s, q, y1v, y2a, &Images);
|
|
896
|
+
delete Images;
|
|
897
|
+
rho2 = rho*rho;
|
|
898
|
+
corrquad *= 6 * (rho2 + 1.e-4*Tol);
|
|
899
|
+
corrquad2 *= (rho+1.e-3);
|
|
900
|
+
if (corrquad<Tol && corrquad2<1 && (/*rho2 * s * s<q || */ safedist>4 * rho2)) {
|
|
901
|
+
Mag = Mag0;
|
|
902
|
+
}
|
|
903
|
+
else {
|
|
904
|
+
Mag = BinaryMagDark(s, q, y1v, y2a, rho, Tol);
|
|
905
|
+
}
|
|
906
|
+
Mag0 = 0;
|
|
907
|
+
|
|
908
|
+
if (y2v < 0) {
|
|
909
|
+
y_2 = y2v;
|
|
910
|
+
astrox2 = -astrox2;
|
|
911
|
+
}
|
|
912
|
+
return Mag;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
double VBBinaryLensing::BinaryMagDark(double a, double q, double y1, double y2, double RSv, double Tolnew) {
|
|
917
|
+
static double Mag, Magold, Tolv;
|
|
918
|
+
static double LDastrox1,LDastrox2;
|
|
919
|
+
static double tc, lc, rc, cb,rb;
|
|
920
|
+
static int c, flag;
|
|
921
|
+
static double currerr, maxerr;
|
|
922
|
+
static annulus *first, *scan, *scan2;
|
|
923
|
+
static int nannold, totNPS;
|
|
924
|
+
static _sols *Images;
|
|
925
|
+
|
|
926
|
+
Mag = -1.0;
|
|
927
|
+
Magold = 0.;
|
|
928
|
+
Tolv = Tol;
|
|
929
|
+
LDastrox1 = LDastrox2 = 0.0;
|
|
930
|
+
c = 0;
|
|
931
|
+
totNPS = 1;
|
|
932
|
+
|
|
933
|
+
Tol = Tolnew;
|
|
934
|
+
y_1 = y1;
|
|
935
|
+
y_2 = y2;
|
|
936
|
+
while ((Mag<0.9) && (c<3)) {
|
|
937
|
+
|
|
938
|
+
first = new annulus;
|
|
939
|
+
first->bin = 0.;
|
|
940
|
+
first->cum = 0.;
|
|
941
|
+
if (Mag0 > 0.5) {
|
|
942
|
+
first->Mag = Mag0;
|
|
943
|
+
first->nim = nim0;
|
|
944
|
+
}
|
|
945
|
+
else {
|
|
946
|
+
first->Mag = BinaryMag0(a, q, y_1, y_2, &Images);
|
|
947
|
+
first->nim = Images->length;
|
|
948
|
+
delete Images;
|
|
949
|
+
}
|
|
950
|
+
if (astrometry) {
|
|
951
|
+
first->LDastrox1 = astrox1 * first->Mag;
|
|
952
|
+
first->LDastrox2 = astrox2 * first->Mag;
|
|
953
|
+
}
|
|
954
|
+
scr2 = sscr2 = 0;
|
|
955
|
+
first->f = LDprofile(0);
|
|
956
|
+
first->err = 0;
|
|
957
|
+
first->prev = 0;
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
first->next = new annulus;
|
|
961
|
+
scan = first->next;
|
|
962
|
+
scan->prev = first;
|
|
963
|
+
scan->next = 0;
|
|
964
|
+
scan->bin = 1.;
|
|
965
|
+
scan->cum = 1.;
|
|
966
|
+
scan->Mag = BinaryMagSafe(a, q, y_1, y_2, RSv, &Images);
|
|
967
|
+
if(astrometry){
|
|
968
|
+
scan->LDastrox1 = astrox1*scan->Mag;
|
|
969
|
+
scan->LDastrox2 = astrox2*scan->Mag;
|
|
970
|
+
}
|
|
971
|
+
totNPS += NPS;
|
|
972
|
+
scan->nim = Images->length;
|
|
973
|
+
delete Images;
|
|
974
|
+
scr2 = sscr2 = 1;
|
|
975
|
+
scan->f = LDprofile(0.9999999);
|
|
976
|
+
if (scan->nim == scan->prev->nim) {
|
|
977
|
+
scan->err = fabs((scan->Mag - scan->prev->Mag)*(scan->prev->f - scan->f) / 4);
|
|
978
|
+
}
|
|
979
|
+
else {
|
|
980
|
+
scan->err = fabs((scan->Mag)*(scan->prev->f - scan->f) / 4);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
Magold = Mag = scan->Mag;
|
|
984
|
+
if(astrometry){
|
|
985
|
+
LDastrox1=scan->LDastrox1;
|
|
986
|
+
LDastrox2=scan->LDastrox2;
|
|
987
|
+
}
|
|
988
|
+
// scan->err+=scan->Mag*Tolv*0.25; //Impose calculation of intermediate annulus at mag>4. Why?
|
|
989
|
+
currerr = scan->err;
|
|
990
|
+
flag = 0;
|
|
991
|
+
nannuli = nannold = 1;
|
|
992
|
+
while (((flag<nannold + 5) && (currerr>Tolv) && (currerr>RelTol*Mag)) || (nannuli<minannuli)) {
|
|
993
|
+
maxerr = 0;
|
|
994
|
+
for (scan2 = first->next; scan2; scan2 = scan2->next) {
|
|
995
|
+
#ifdef _PRINT_ERRORS_DARK
|
|
996
|
+
printf("\n%d %lf %le | %lf %le", nannuli, scan2->Mag, scan2->err, Mag, currerr);
|
|
997
|
+
#endif
|
|
998
|
+
if (scan2->err>maxerr) {
|
|
999
|
+
maxerr = scan2->err;
|
|
1000
|
+
scan = scan2;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
nannuli++;
|
|
1005
|
+
Magold = Mag;
|
|
1006
|
+
Mag -= (scan->Mag*scan->bin*scan->bin - scan->prev->Mag*scan->prev->bin*scan->prev->bin)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1007
|
+
if(astrometry){
|
|
1008
|
+
LDastrox1 -= (scan->LDastrox1*scan->bin*scan->bin - scan->prev->LDastrox1*scan->prev->bin*scan->prev->bin)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1009
|
+
LDastrox2 -= (scan->LDastrox2*scan->bin*scan->bin - scan->prev->LDastrox2*scan->prev->bin*scan->prev->bin)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1010
|
+
}
|
|
1011
|
+
currerr -= scan->err;
|
|
1012
|
+
lc = scan->prev->cum;
|
|
1013
|
+
rc = scan->cum;
|
|
1014
|
+
tc = (lc + rc) *0.5;
|
|
1015
|
+
cb = rCLDprofile(tc,scan->prev,scan);
|
|
1016
|
+
scan->prev->next = new annulus;
|
|
1017
|
+
scan->prev->next->prev = scan->prev;
|
|
1018
|
+
scan->prev = scan->prev->next;
|
|
1019
|
+
scan->prev->next = scan;
|
|
1020
|
+
scan->prev->bin = cb;
|
|
1021
|
+
scan->prev->cum = tc;
|
|
1022
|
+
scan->prev->f = LDprofile(cb);
|
|
1023
|
+
scan->prev->Mag = BinaryMagSafe(a, q, y_1, y_2, RSv*cb, &Images);
|
|
1024
|
+
if(astrometry){
|
|
1025
|
+
scan->prev->LDastrox1=astrox1*scan->prev->Mag;
|
|
1026
|
+
scan->prev->LDastrox2=astrox2*scan->prev->Mag;
|
|
1027
|
+
}
|
|
1028
|
+
totNPS += NPS;
|
|
1029
|
+
scan->prev->nim = Images->length;
|
|
1030
|
+
if (scan->prev->prev->nim == scan->prev->nim) {
|
|
1031
|
+
scan->prev->err = fabs((scan->prev->Mag - scan->prev->prev->Mag)*(scan->prev->prev->f - scan->prev->f)*(scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin) / 4);
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1034
|
+
scan->prev->err = fabs((scan->prev->bin*scan->prev->bin*scan->prev->Mag - scan->prev->prev->bin*scan->prev->prev->bin*scan->prev->prev->Mag)*(scan->prev->prev->f - scan->prev->f) / 4);
|
|
1035
|
+
}
|
|
1036
|
+
if (scan->nim == scan->prev->nim) {
|
|
1037
|
+
scan->err = fabs((scan->Mag - scan->prev->Mag)*(scan->prev->f - scan->f)*(scan->bin*scan->bin - scan->prev->bin*scan->prev->bin) / 4);
|
|
1038
|
+
}
|
|
1039
|
+
else {
|
|
1040
|
+
scan->err = fabs((scan->bin*scan->bin*scan->Mag - scan->prev->bin*scan->prev->bin*scan->prev->Mag)*(scan->prev->f - scan->f) / 4);
|
|
1041
|
+
}
|
|
1042
|
+
rb = (scan->Mag + scan->prev->prev->Mag - 2 * scan->prev->Mag);
|
|
1043
|
+
scan->prev->err += fabs(rb*(scan->prev->prev->f - scan->prev->f)*(scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin));
|
|
1044
|
+
scan->err += fabs(rb*(scan->prev->f - scan->f)*(scan->bin*scan->bin - scan->prev->bin*scan->prev->bin));
|
|
1045
|
+
#ifdef _PRINT_ERRORS_DARK
|
|
1046
|
+
printf("\n%d", Images->length);
|
|
1047
|
+
#endif
|
|
1048
|
+
delete Images;
|
|
1049
|
+
|
|
1050
|
+
Mag += (scan->bin*scan->bin*scan->Mag - cb*cb*scan->prev->Mag)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1051
|
+
Mag += (cb*cb*scan->prev->Mag - scan->prev->prev->bin*scan->prev->prev->bin*scan->prev->prev->Mag)*(scan->prev->cum - scan->prev->prev->cum) / (scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin);
|
|
1052
|
+
currerr += scan->err + scan->prev->err;
|
|
1053
|
+
if(astrometry){
|
|
1054
|
+
LDastrox1 += ( scan->bin*scan->bin*scan->LDastrox1 - cb*cb*scan->prev->LDastrox1)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1055
|
+
LDastrox1 += ( cb*cb*scan->prev->LDastrox1 - scan->prev->prev->bin*scan->prev->prev->bin*scan->prev->prev->LDastrox1)*(scan->prev->cum - scan->prev->prev->cum) / (scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin);
|
|
1056
|
+
LDastrox2 += ( scan->bin*scan->bin*scan->LDastrox2 - cb*cb*scan->prev->LDastrox2)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1057
|
+
LDastrox2 += ( cb*cb*scan->prev->LDastrox2 - scan->prev->prev->bin*scan->prev->prev->bin*scan->prev->prev->LDastrox2)*(scan->prev->cum - scan->prev->prev->cum) / (scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
if (fabs(Magold - Mag) * 2<Tolv) {
|
|
1062
|
+
flag++;
|
|
1063
|
+
}
|
|
1064
|
+
else {
|
|
1065
|
+
flag = 0;
|
|
1066
|
+
nannold = nannuli;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
if (multidark) {
|
|
1072
|
+
annlist = first;
|
|
1073
|
+
}else{
|
|
1074
|
+
while (first) {
|
|
1075
|
+
scan = first->next;
|
|
1076
|
+
delete first;
|
|
1077
|
+
first = scan;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
Tolv /= 10;
|
|
1082
|
+
c++;
|
|
1083
|
+
}
|
|
1084
|
+
NPS = totNPS;
|
|
1085
|
+
therr = currerr;
|
|
1086
|
+
if(astrometry){
|
|
1087
|
+
LDastrox1/=Mag;
|
|
1088
|
+
LDastrox2/=Mag;
|
|
1089
|
+
astrox1=LDastrox1;
|
|
1090
|
+
astrox2=LDastrox2;
|
|
1091
|
+
}
|
|
1092
|
+
return Mag;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
void VBBinaryLensing::BinaryMagMultiDark(double a, double q, double y1, double y2, double RSv, double *a1_list, int nfil, double *mag_list, double Tol) {
|
|
1096
|
+
annulus *scan;
|
|
1097
|
+
int imax = 0;
|
|
1098
|
+
double Mag,r2,cr2,scr2,a1;
|
|
1099
|
+
|
|
1100
|
+
multidark = true;
|
|
1101
|
+
|
|
1102
|
+
for (int i = 1; i < nfil; i++) {
|
|
1103
|
+
if (a1_list[i] > a1_list[imax]) imax = i;
|
|
1104
|
+
}
|
|
1105
|
+
a1 = a1_list[imax];
|
|
1106
|
+
mag_list[imax] = BinaryMagDark(a, q, y1, y2, RSv, Tol);
|
|
1107
|
+
|
|
1108
|
+
for (int i = 0; i < nfil; i++) {
|
|
1109
|
+
if (i != imax) {
|
|
1110
|
+
Mag = 0;
|
|
1111
|
+
a1 = a1_list[i];
|
|
1112
|
+
for (scan = annlist->next; scan; scan = scan->next) {
|
|
1113
|
+
r2 = scan->bin*scan->bin;
|
|
1114
|
+
cr2 = 1 - r2;
|
|
1115
|
+
scr2 = sqrt(cr2);
|
|
1116
|
+
scan->cum = (3 * r2*(1 - a1) - 2 * a1*(scr2*cr2 - 1)) / (3 - a1);
|
|
1117
|
+
Mag += (scan->bin*scan->bin*scan->Mag - scan->prev->bin*scan->prev->bin*scan->prev->Mag)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1118
|
+
}
|
|
1119
|
+
mag_list[i] = Mag;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
while (annlist) {
|
|
1124
|
+
scan = annlist->next;
|
|
1125
|
+
delete annlist;
|
|
1126
|
+
annlist = scan;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
multidark = false;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
double VBBinaryLensing::LDprofile(double r) {
|
|
1133
|
+
static int ir;
|
|
1134
|
+
static double rr,ret;
|
|
1135
|
+
switch(curLDprofile){
|
|
1136
|
+
case LDuser:
|
|
1137
|
+
rr = r * npLD;
|
|
1138
|
+
ir = (int)rr;
|
|
1139
|
+
rr -= ir;
|
|
1140
|
+
ret= LDtab[ir] * (1 - rr) + LDtab[ir + 1] * rr;
|
|
1141
|
+
break;
|
|
1142
|
+
case LDlinear:
|
|
1143
|
+
ret = 3 / (3 - a1)*(1 - a1 * scr2);
|
|
1144
|
+
break;
|
|
1145
|
+
case LDsquareroot:
|
|
1146
|
+
ret= 3 / (3 - a1 - 0.6*a2)*(1 - a1 * scr2 - a2 * sscr2);
|
|
1147
|
+
case LDquadratic:
|
|
1148
|
+
ret = 3 / (3 - a1 - 0.5*a2)*(1 - a1 * scr2 - a2 * sscr2);
|
|
1149
|
+
break;
|
|
1150
|
+
case LDlog:
|
|
1151
|
+
ret = 3 / (3 - a1 + 0.666666666666 * a2)*(1 - a1 * scr2 - a2 * sscr2);
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
return ret;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
double VBBinaryLensing::rCLDprofile(double tc,annulus *left,annulus *right) {
|
|
1158
|
+
static int ic;
|
|
1159
|
+
static double rc,cb,lc,r2,cr2,cc,lb,rb;
|
|
1160
|
+
|
|
1161
|
+
switch (curLDprofile) {
|
|
1162
|
+
case LDuser:
|
|
1163
|
+
rc = tc * npLD;
|
|
1164
|
+
ic = (int)rc;
|
|
1165
|
+
rc -= ic;
|
|
1166
|
+
cb = rCLDtab[ic] * (1 - rc) + rCLDtab[ic + 1] * rc;
|
|
1167
|
+
break;
|
|
1168
|
+
case LDlinear:
|
|
1169
|
+
lb = left->bin;
|
|
1170
|
+
rb = right->bin;
|
|
1171
|
+
lc = left->cum;
|
|
1172
|
+
rc = right->cum;
|
|
1173
|
+
do {
|
|
1174
|
+
cb = rb + (tc - rc)*(rb - lb) / (rc - lc);
|
|
1175
|
+
r2 = cb * cb;
|
|
1176
|
+
cr2 = 1 - r2;
|
|
1177
|
+
scr2 = 1-sqrt(cr2);
|
|
1178
|
+
cc = (3 * r2 - a1 * (r2 - 2 * scr2*cr2)) / (3 - a1);
|
|
1179
|
+
if (cc > tc) {
|
|
1180
|
+
rb = cb;
|
|
1181
|
+
rc = cc;
|
|
1182
|
+
}
|
|
1183
|
+
else {
|
|
1184
|
+
lb = cb;
|
|
1185
|
+
lc = cc;
|
|
1186
|
+
}
|
|
1187
|
+
} while (fabs(cc - tc) > 1.e-5);
|
|
1188
|
+
break;
|
|
1189
|
+
case LDsquareroot:
|
|
1190
|
+
lb = left->bin;
|
|
1191
|
+
rb = right->bin;
|
|
1192
|
+
lc = left->cum;
|
|
1193
|
+
rc = right->cum;
|
|
1194
|
+
do {
|
|
1195
|
+
cb = rb + (tc - rc)*(rb - lb) / (rc - lc);
|
|
1196
|
+
r2 = cb * cb;
|
|
1197
|
+
cr2 = 1 - r2;
|
|
1198
|
+
scr2 = sqrt(cr2);
|
|
1199
|
+
sscr2 = 1 - sqrt(scr2);
|
|
1200
|
+
scr2 = 1 - scr2;
|
|
1201
|
+
cc = (3 * r2 - a1 * (r2 - 2 * scr2*cr2) - 0.6*a2*(r2 - 4 * sscr2*cr2)) / (3 - a1 - 0.6*a2);
|
|
1202
|
+
if (cc > tc) {
|
|
1203
|
+
rb = cb;
|
|
1204
|
+
rc = cc;
|
|
1205
|
+
}
|
|
1206
|
+
else {
|
|
1207
|
+
lb = cb;
|
|
1208
|
+
lc = cc;
|
|
1209
|
+
}
|
|
1210
|
+
} while (fabs(cc - tc) > 1.e-5);
|
|
1211
|
+
break;
|
|
1212
|
+
case LDquadratic:
|
|
1213
|
+
lb = left->bin;
|
|
1214
|
+
rb = right->bin;
|
|
1215
|
+
lc = left->cum;
|
|
1216
|
+
rc = right->cum;
|
|
1217
|
+
do {
|
|
1218
|
+
cb = rb + (tc - rc)*(rb - lb) / (rc - lc);
|
|
1219
|
+
r2 = cb * cb;
|
|
1220
|
+
cr2 = 1 - r2;
|
|
1221
|
+
scr2 = 1- sqrt(cr2);
|
|
1222
|
+
sscr2 = scr2*scr2;
|
|
1223
|
+
cc = (3 * r2 - a1 * (r2 - 2 * scr2*cr2) + a2*(4*scr2-(2+4*scr2)*r2+1.5*r2*r2)) / (3 - a1 - 0.5*a2);
|
|
1224
|
+
if (cc > tc) {
|
|
1225
|
+
rb = cb;
|
|
1226
|
+
rc = cc;
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
lb = cb;
|
|
1230
|
+
lc = cc;
|
|
1231
|
+
}
|
|
1232
|
+
} while (fabs(cc - tc) > 1.e-5);
|
|
1233
|
+
break;
|
|
1234
|
+
case LDlog:
|
|
1235
|
+
lb = left->bin;
|
|
1236
|
+
rb = right->bin;
|
|
1237
|
+
lc = left->cum;
|
|
1238
|
+
rc = right->cum;
|
|
1239
|
+
do {
|
|
1240
|
+
cb = rb + (tc - rc)*(rb - lb) / (rc - lc);
|
|
1241
|
+
r2 = cb * cb;
|
|
1242
|
+
cr2 = 1 - r2;
|
|
1243
|
+
scr2 = sqrt(cr2);
|
|
1244
|
+
sscr2 = scr2*log(scr2);
|
|
1245
|
+
scr2 = 1 - scr2;
|
|
1246
|
+
cc = (3 * r2 - a1 * (r2 - 2 * scr2*cr2) + 2*a2*(scr2*(1+scr2*(scr2/3-1)) + sscr2*cr2)) / (3 - a1 + 0.6666666666666666*a2);
|
|
1247
|
+
if (cc > tc) {
|
|
1248
|
+
rb = cb;
|
|
1249
|
+
rc = cc;
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
lb = cb;
|
|
1253
|
+
lc = cc;
|
|
1254
|
+
}
|
|
1255
|
+
} while (fabs(cc - tc) > 1.e-5);
|
|
1256
|
+
break;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
return cb;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
void VBBinaryLensing::SetLDprofile(double (*UserLDprofile)(double),int newnpLD) {
|
|
1263
|
+
int ic,ir;
|
|
1264
|
+
if (npLD > 0) {
|
|
1265
|
+
free(LDtab);
|
|
1266
|
+
free(rCLDtab);
|
|
1267
|
+
}
|
|
1268
|
+
if (newnpLD > 0) {
|
|
1269
|
+
npLD = newnpLD;
|
|
1270
|
+
double npLD2 = npLD * npLD;
|
|
1271
|
+
LDtab = (double *)malloc(sizeof(double)*(npLD+1));
|
|
1272
|
+
CLDtab = (double *)malloc(sizeof(double)*(npLD + 1));
|
|
1273
|
+
rCLDtab = (double *)malloc(sizeof(double)*(npLD+1));
|
|
1274
|
+
|
|
1275
|
+
LDtab[0] = UserLDprofile(0.);
|
|
1276
|
+
CLDtab[0] = 0.;
|
|
1277
|
+
for (int i = 1; i <= npLD; i++) {
|
|
1278
|
+
LDtab[i] = UserLDprofile(((double) i)/ npLD);
|
|
1279
|
+
CLDtab[i] = CLDtab[i-1]+(LDtab[i]*i + LDtab[i - 1]*(i-1));
|
|
1280
|
+
}
|
|
1281
|
+
for (int i = 0; i <= npLD; i++) {
|
|
1282
|
+
LDtab[i] *= npLD2/CLDtab[npLD];
|
|
1283
|
+
CLDtab[i] /= CLDtab[npLD];
|
|
1284
|
+
}
|
|
1285
|
+
ic = 1;
|
|
1286
|
+
rCLDtab[0] = 0;
|
|
1287
|
+
ir = 1;
|
|
1288
|
+
while (ic < npLD) {
|
|
1289
|
+
while (CLDtab[ir] * npLD < ic && ir<npLD) ir++;
|
|
1290
|
+
rCLDtab[ic] = ((CLDtab[ir] - ((double) ic) / npLD)*(ir-1) + (((double)ic) / npLD - CLDtab[ir-1])*ir) / (CLDtab[ir] - CLDtab[ir - 1])/npLD;
|
|
1291
|
+
ic++;
|
|
1292
|
+
}
|
|
1293
|
+
rCLDtab[npLD] = 1;
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
//printf("\n\n--------------------");
|
|
1297
|
+
//annulus left, right;
|
|
1298
|
+
//left.cum = left.bin=0;
|
|
1299
|
+
//right.cum = right.bin=1;
|
|
1300
|
+
//for (int i = 0; i <= npLD; i++) {
|
|
1301
|
+
// double rl, fl;
|
|
1302
|
+
// rl = ((double)i) / npLD;
|
|
1303
|
+
// scr2 = 1 - sqrt(1 - rl * rl);
|
|
1304
|
+
// fl = LDprofile(rl);
|
|
1305
|
+
// rl = rCLDprofile(((double) i) / npLD,&left,&right);
|
|
1306
|
+
// printf("\n%lf %lf %lf %lf", fl, LDtab[i], rl, rCLDtab[i]);
|
|
1307
|
+
//}
|
|
1308
|
+
//printf("\n--------------------\n\n");
|
|
1309
|
+
|
|
1310
|
+
free(CLDtab);
|
|
1311
|
+
curLDprofile = LDuser;
|
|
1312
|
+
}
|
|
1313
|
+
else {
|
|
1314
|
+
npLD = 0;
|
|
1315
|
+
curLDprofile = LDlinear;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
void VBBinaryLensing::SetLDprofile(LDprofiles LDval) {
|
|
1320
|
+
if(npLD > 0) {
|
|
1321
|
+
npLD = 0;
|
|
1322
|
+
free(LDtab);
|
|
1323
|
+
free(rCLDtab);
|
|
1324
|
+
}
|
|
1325
|
+
curLDprofile = LDval;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
void VBBinaryLensing::LoadESPLTable(char *filename){
|
|
1329
|
+
FILE *f;
|
|
1330
|
+
|
|
1331
|
+
if((f = fopen(filename, "rb"))!=0){
|
|
1332
|
+
fread(ESPLin, sizeof(double), __rsize * __zsize, f);
|
|
1333
|
+
fread(ESPLout, sizeof(double), __rsize * __zsize, f);
|
|
1334
|
+
fread(ESPLinastro, sizeof(double), __rsize * __zsize, f);
|
|
1335
|
+
fread(ESPLoutastro, sizeof(double), __rsize * __zsize, f);
|
|
1336
|
+
fclose(f);
|
|
1337
|
+
ESPLoff=false;
|
|
1338
|
+
}else{
|
|
1339
|
+
printf("\nESPL table not found !");
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
double VBBinaryLensing::PSPLMag(double u) {
|
|
1345
|
+
static double u2,u22;
|
|
1346
|
+
u2 = u * u;
|
|
1347
|
+
u22 = u2 + 2;
|
|
1348
|
+
if (astrometry) {
|
|
1349
|
+
astrox1 = u+u/u22;
|
|
1350
|
+
}
|
|
1351
|
+
return u22 / sqrt(u2 * (u2 + 4));
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
double VBBinaryLensing::ESPLMag(double u, double RSv) {
|
|
1356
|
+
double mag,z,fr,cz,cr,u2;
|
|
1357
|
+
int iz, ir;
|
|
1358
|
+
|
|
1359
|
+
if (ESPLoff) {
|
|
1360
|
+
printf("\nLoad ESPL table first!");
|
|
1361
|
+
return 0;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
fr = -10.857362047581296* log(0.01* RSv);
|
|
1365
|
+
if (fr > __rsize - 1) fr = __rsize -1.000001;
|
|
1366
|
+
if (fr < 0) printf("Source too large!");
|
|
1367
|
+
ir = (int) floor(fr);
|
|
1368
|
+
fr -= ir;
|
|
1369
|
+
cr = 1 - fr;
|
|
1370
|
+
|
|
1371
|
+
z = u / RSv;
|
|
1372
|
+
|
|
1373
|
+
if (z < 1) {
|
|
1374
|
+
z *= __zsize -1;
|
|
1375
|
+
iz = (int) floor(z);
|
|
1376
|
+
z -= iz;
|
|
1377
|
+
cz = 1 - z;
|
|
1378
|
+
mag = sqrt(1 + 4. / (RSv*RSv));
|
|
1379
|
+
mag *= ESPLin[ir][iz] * cr*cz + ESPLin[ir + 1][iz] * fr*cz + ESPLin[ir][iz + 1] * cr*z + ESPLin[ir + 1][iz + 1] * fr*z;
|
|
1380
|
+
if (astrometry) {
|
|
1381
|
+
astrox1=(1-1./(4+RSv*RSv))*u;
|
|
1382
|
+
astrox1 *= ESPLinastro[ir][iz] * cr*cz + ESPLinastro[ir + 1][iz] * fr*cz + ESPLinastro[ir][iz + 1] * cr*z + ESPLinastro[ir + 1][iz + 1] * fr*z;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
else {
|
|
1386
|
+
z = 0.99999999999999 / z;
|
|
1387
|
+
z *= __zsize - 1;
|
|
1388
|
+
iz = (int)floor(z);
|
|
1389
|
+
z -= iz;
|
|
1390
|
+
cz = 1 - z;
|
|
1391
|
+
|
|
1392
|
+
u2 = u*u;
|
|
1393
|
+
mag = (u2 + 2) / sqrt(u2*(u2 + 4));
|
|
1394
|
+
mag *= ESPLout[ir][iz] * cr*cz + ESPLout[ir + 1][iz] * fr*cz + ESPLout[ir][iz + 1] * cr*z + ESPLout[ir + 1][iz + 1] * fr*z;
|
|
1395
|
+
if (astrometry) {
|
|
1396
|
+
astrox1 = u * (u2 + 3) / (u2 + 2);
|
|
1397
|
+
astrox1 *= ESPLoutastro[ir][iz] * cr*cz + ESPLoutastro[ir + 1][iz] * fr*cz + ESPLoutastro[ir][iz + 1] * cr*z + ESPLoutastro[ir + 1][iz + 1] * fr*z;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
return mag;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
double VBBinaryLensing::ESPLMag2(double u, double rho) {
|
|
1405
|
+
double Mag, u2,u6,rho2Tol;
|
|
1406
|
+
int c = 0;
|
|
1407
|
+
|
|
1408
|
+
//Tol1_4 = sqrt(2 / Tol);
|
|
1409
|
+
//u2 = u*u;
|
|
1410
|
+
//u3Tol = u2*u*Tol;
|
|
1411
|
+
|
|
1412
|
+
//if (u2 < Tol1_4) {
|
|
1413
|
+
// rho2 = rho*rho;
|
|
1414
|
+
// if (u3Tol > rho2*(1 + Tol1_4*rho)) {
|
|
1415
|
+
|
|
1416
|
+
u2 = u*u;
|
|
1417
|
+
rho2Tol = rho*rho/Tol;
|
|
1418
|
+
u6 = u2*u2*u2;
|
|
1419
|
+
|
|
1420
|
+
if (u6*(1+0.003*rho2Tol) > 0.027680640625*rho2Tol*rho2Tol) {
|
|
1421
|
+
Mag = (u2+2)/(u*sqrt(u2+4));
|
|
1422
|
+
if (astrometry) {
|
|
1423
|
+
astrox1 = u * (1 + 1 / (u2 + 2));
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
else {
|
|
1427
|
+
Mag = ESPLMagDark(u, rho);
|
|
1428
|
+
}
|
|
1429
|
+
Mag0 = 0;
|
|
1430
|
+
return Mag;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
double VBBinaryLensing::ESPLMagDark(double u, double RSv) {
|
|
1434
|
+
double Mag = -1.0, Magold = 0., Tolv = Tol;
|
|
1435
|
+
double tc, rb, lc, rc, cb,u2;
|
|
1436
|
+
int c = 0, flag;
|
|
1437
|
+
double currerr, maxerr;
|
|
1438
|
+
annulus *first, *scan, *scan2;
|
|
1439
|
+
int nannold, totNPS = 1;
|
|
1440
|
+
double LDastrox1=0.0;
|
|
1441
|
+
|
|
1442
|
+
while ((Mag < 0.9) && (c < 3)) {
|
|
1443
|
+
|
|
1444
|
+
first = new annulus;
|
|
1445
|
+
first->bin = 0.;
|
|
1446
|
+
first->cum = 0.;
|
|
1447
|
+
|
|
1448
|
+
u2 = u * u;
|
|
1449
|
+
first->Mag = Mag0 = (u2 + 2) / (u*sqrt(u2 + 4));
|
|
1450
|
+
first->nim = 2;
|
|
1451
|
+
if (astrometry) {
|
|
1452
|
+
astrox1 = u * (u2 + 3) / (u2 + 2);
|
|
1453
|
+
first->LDastrox1 = astrox1 * first->Mag;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
scr2 = sscr2 = 0;
|
|
1457
|
+
first->f = LDprofile(0);
|
|
1458
|
+
first->err = 0;
|
|
1459
|
+
first->prev = 0;
|
|
1460
|
+
|
|
1461
|
+
|
|
1462
|
+
first->next = new annulus;
|
|
1463
|
+
scan = first->next;
|
|
1464
|
+
scan->prev = first;
|
|
1465
|
+
scan->next = 0;
|
|
1466
|
+
scan->bin = 1.;
|
|
1467
|
+
scan->cum = 1.;
|
|
1468
|
+
scan->Mag = ESPLMag(u, RSv);//ESPLMag(u, RSv, Tolv, &Images);
|
|
1469
|
+
if (astrometry) {
|
|
1470
|
+
scan->LDastrox1 = astrox1 * scan->Mag;
|
|
1471
|
+
}
|
|
1472
|
+
scan->nim = 2;
|
|
1473
|
+
scr2 = sscr2 = 1;
|
|
1474
|
+
scan->f = LDprofile(0.9999999);
|
|
1475
|
+
scan->err = fabs((scan->Mag - scan->prev->Mag)*(scan->prev->f - scan->f) / 4);
|
|
1476
|
+
|
|
1477
|
+
Magold = Mag = scan->Mag;
|
|
1478
|
+
if(astrometry){
|
|
1479
|
+
LDastrox1=scan->LDastrox1;
|
|
1480
|
+
}
|
|
1481
|
+
//
|
|
1482
|
+
// scan->err+=scan->Mag*Tolv*0.25; //Impose calculation of intermediate annulus at mag>4. Why?
|
|
1483
|
+
currerr = scan->err;
|
|
1484
|
+
flag = 0;
|
|
1485
|
+
nannuli = nannold = 1;
|
|
1486
|
+
while (((flag<nannold + 5) && (currerr>Tolv) && (currerr>RelTol*Mag)) || (nannuli<minannuli)) {
|
|
1487
|
+
maxerr = 0;
|
|
1488
|
+
for (scan2 = first->next; scan2; scan2 = scan2->next) {
|
|
1489
|
+
#ifdef _PRINT_ERRORS_DARK
|
|
1490
|
+
printf("\n%d %lf %le | %lf %le", nannuli, scan2->Mag, scan2->err, Mag, currerr);
|
|
1491
|
+
#endif
|
|
1492
|
+
if (scan2->err>maxerr) {
|
|
1493
|
+
maxerr = scan2->err;
|
|
1494
|
+
scan = scan2;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
nannuli++;
|
|
1499
|
+
Magold = Mag;
|
|
1500
|
+
Mag -= (scan->Mag*scan->bin*scan->bin - scan->prev->Mag*scan->prev->bin*scan->prev->bin)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1501
|
+
if(astrometry){
|
|
1502
|
+
LDastrox1 -= (scan->LDastrox1*scan->bin*scan->bin - scan->prev->LDastrox1*scan->prev->bin*scan->prev->bin)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1503
|
+
|
|
1504
|
+
}
|
|
1505
|
+
currerr -= scan->err;
|
|
1506
|
+
rc = scan->cum;
|
|
1507
|
+
lc = scan->prev->cum;
|
|
1508
|
+
tc = (lc + rc) / 2;
|
|
1509
|
+
cb = rCLDprofile(tc, scan->prev, scan);
|
|
1510
|
+
|
|
1511
|
+
scan->prev->next = new annulus;
|
|
1512
|
+
scan->prev->next->prev = scan->prev;
|
|
1513
|
+
scan->prev = scan->prev->next;
|
|
1514
|
+
scan->prev->next = scan;
|
|
1515
|
+
scan->prev->bin = cb;
|
|
1516
|
+
scan->prev->cum = tc;
|
|
1517
|
+
scan->prev->f = LDprofile(cb);
|
|
1518
|
+
scan->prev->Mag = ESPLMag(u, RSv*cb);
|
|
1519
|
+
if(astrometry){
|
|
1520
|
+
scan->prev->LDastrox1=astrox1*scan->prev->Mag;
|
|
1521
|
+
|
|
1522
|
+
}
|
|
1523
|
+
scan->prev->nim = 2;
|
|
1524
|
+
scan->prev->err = fabs((scan->prev->Mag - scan->prev->prev->Mag)*(scan->prev->prev->f - scan->prev->f)*(scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin) / 4);
|
|
1525
|
+
scan->err = fabs((scan->Mag - scan->prev->Mag)*(scan->prev->f - scan->f)*(scan->bin*scan->bin - scan->prev->bin*scan->prev->bin) / 4);
|
|
1526
|
+
rb = (scan->Mag + scan->prev->prev->Mag - 2 * scan->prev->Mag);
|
|
1527
|
+
scan->prev->err += fabs(rb*(scan->prev->prev->f - scan->prev->f)*(scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin));
|
|
1528
|
+
scan->err += fabs(rb*(scan->prev->f - scan->f)*(scan->bin*scan->bin - scan->prev->bin*scan->prev->bin));
|
|
1529
|
+
#ifdef _PRINT_ERRORS_DARK
|
|
1530
|
+
printf("\n%d", Images->length);
|
|
1531
|
+
#endif
|
|
1532
|
+
|
|
1533
|
+
Mag += (scan->bin*scan->bin*scan->Mag - cb*cb*scan->prev->Mag)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1534
|
+
Mag += (cb*cb*scan->prev->Mag - scan->prev->prev->bin*scan->prev->prev->bin*scan->prev->prev->Mag)*(scan->prev->cum - scan->prev->prev->cum) / (scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin);
|
|
1535
|
+
if(astrometry){
|
|
1536
|
+
LDastrox1 += ( scan->bin*scan->bin*scan->LDastrox1 - cb*cb*scan->prev->LDastrox1)*(scan->cum - scan->prev->cum) / (scan->bin*scan->bin - scan->prev->bin*scan->prev->bin);
|
|
1537
|
+
LDastrox1 += ( cb*cb*scan->prev->LDastrox1 - scan->prev->prev->bin*scan->prev->prev->bin*scan->prev->prev->LDastrox1)*(scan->prev->cum - scan->prev->prev->cum) / (scan->prev->bin*scan->prev->bin - scan->prev->prev->bin*scan->prev->prev->bin);
|
|
1538
|
+
|
|
1539
|
+
}
|
|
1540
|
+
currerr += scan->err + scan->prev->err;
|
|
1541
|
+
|
|
1542
|
+
if (fabs(Magold - Mag) * 2<Tolv) {
|
|
1543
|
+
flag++;
|
|
1544
|
+
}
|
|
1545
|
+
else {
|
|
1546
|
+
flag = 0;
|
|
1547
|
+
nannold = nannuli;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
while (first) {
|
|
1553
|
+
scan = first->next;
|
|
1554
|
+
delete first;
|
|
1555
|
+
first = scan;
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
Tolv /= 10;
|
|
1559
|
+
c++;
|
|
1560
|
+
}
|
|
1561
|
+
therr = currerr;
|
|
1562
|
+
if(astrometry){
|
|
1563
|
+
LDastrox1/=Mag;
|
|
1564
|
+
astrox1=LDastrox1;
|
|
1565
|
+
|
|
1566
|
+
}
|
|
1567
|
+
return Mag;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
//////////////////////////////
|
|
1571
|
+
//////////////////////////////
|
|
1572
|
+
////////New (v2) light curve functions
|
|
1573
|
+
//////////////////////////////
|
|
1574
|
+
//////////////////////////////
|
|
1575
|
+
|
|
1576
|
+
void VBBinaryLensing::PSPLLightCurve(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1577
|
+
double u0=exp(pr[0]), t0=pr[2],tE_inv=exp(-pr[1]),tn,u;
|
|
1578
|
+
|
|
1579
|
+
for (int i = 0; i < np; i++) {
|
|
1580
|
+
tn = (ts[i] - t0) *tE_inv;
|
|
1581
|
+
u = tn*tn + u0*u0;
|
|
1582
|
+
|
|
1583
|
+
y1s[i] = -tn;
|
|
1584
|
+
y2s[i] = -u0;
|
|
1585
|
+
mags[i]= (u + 2) / sqrt(u*(u + 4));
|
|
1586
|
+
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
void VBBinaryLensing::PSPLLightCurveParallax(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1592
|
+
double u0 = pr[0], t0 = pr[2], tE_inv = exp(-pr[1]), tn, u,u1,pai1=pr[3],pai2=pr[4];
|
|
1593
|
+
double Et[2];
|
|
1594
|
+
t0old = 0;
|
|
1595
|
+
|
|
1596
|
+
for (int i = 0; i < np; i++) {
|
|
1597
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1598
|
+
tn = (ts[i] - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
1599
|
+
u1 = u0 + pai1*Et[1] - pai2*Et[0];
|
|
1600
|
+
u = tn*tn + u1*u1;
|
|
1601
|
+
|
|
1602
|
+
y1s[i] = -tn;
|
|
1603
|
+
y2s[i] = -u1;
|
|
1604
|
+
mags[i] = (u + 2) / sqrt(u*(u + 4));
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
void VBBinaryLensing::ESPLLightCurve(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1611
|
+
double u0 = exp(pr[0]), t0 = pr[2], tE_inv = exp(-pr[1]), tn, u,rho=exp(pr[3]);
|
|
1612
|
+
|
|
1613
|
+
for (int i = 0; i < np; i++) {
|
|
1614
|
+
tn = (ts[i] - t0) *tE_inv;
|
|
1615
|
+
u = sqrt(tn*tn + u0*u0);
|
|
1616
|
+
|
|
1617
|
+
y1s[i] = -tn;
|
|
1618
|
+
y2s[i] = -u0;
|
|
1619
|
+
mags[i] = ESPLMag2(u,rho);
|
|
1620
|
+
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
void VBBinaryLensing::ESPLLightCurveParallax(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1625
|
+
double u0 = pr[0], t0 = pr[2], tE_inv = exp(-pr[1]), tn, u, u1, rho = exp(pr[3]), pai1 = pr[4], pai2 = pr[5];
|
|
1626
|
+
double Et[2];
|
|
1627
|
+
t0old = 0;
|
|
1628
|
+
|
|
1629
|
+
for (int i = 0; i < np; i++) {
|
|
1630
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1631
|
+
tn = (ts[i] - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
1632
|
+
u1 = u0 + pai1*Et[1] - pai2*Et[0];
|
|
1633
|
+
u = sqrt( tn*tn + u1*u1);
|
|
1634
|
+
|
|
1635
|
+
y1s[i] = -tn;
|
|
1636
|
+
y2s[i] = -u1;
|
|
1637
|
+
mags[i] = ESPLMag2(u, rho);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
void VBBinaryLensing::BinaryLightCurve(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1644
|
+
double s = exp(pr[0]), q = exp(pr[1]), rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]);
|
|
1645
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
1646
|
+
|
|
1647
|
+
// _sols *Images; double Mag; // For debugging
|
|
1648
|
+
|
|
1649
|
+
for (int i = 0; i < np; i++) {
|
|
1650
|
+
tn = (ts[i] - pr[6]) * tE_inv;
|
|
1651
|
+
y1s[i] = pr[2] * salpha - tn*calpha;
|
|
1652
|
+
y2s[i] = -pr[2] * calpha - tn*salpha;
|
|
1653
|
+
mags[i] = BinaryMag2(s, q, y1s[i], y2s[i], rho);
|
|
1654
|
+
|
|
1655
|
+
//Mag=BinaryMag(s, q, y1s[i], y2s[i], rho, Tol,&Images); // For debugging
|
|
1656
|
+
//delete Images;
|
|
1657
|
+
//mags[i] -= Mag;
|
|
1658
|
+
//if (fabs(mags[i]) > Tol) {
|
|
1659
|
+
// printf("\n%lf %lf %lf", y1s[i], y2s[i], mags[i]);
|
|
1660
|
+
//}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
void VBBinaryLensing::BinaryLightCurveW(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1666
|
+
double s = exp(pr[0]), q = exp(pr[1]), rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]),t0,u0;
|
|
1667
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]),xc;
|
|
1668
|
+
|
|
1669
|
+
xc = (s - 1 / s) / (1 + q);
|
|
1670
|
+
if (xc<0) xc = 0.;
|
|
1671
|
+
t0 = pr[6] + xc*calpha/tE_inv;
|
|
1672
|
+
u0 = pr[2] + xc*salpha;
|
|
1673
|
+
|
|
1674
|
+
for (int i = 0; i < np; i++) {
|
|
1675
|
+
tn = (ts[i] - t0) * tE_inv;
|
|
1676
|
+
y1s[i] = u0 * salpha - tn*calpha;
|
|
1677
|
+
y2s[i] = -u0 * calpha - tn*salpha;
|
|
1678
|
+
mags[i] = BinaryMag2(s, q, y1s[i], y2s[i], rho);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
void VBBinaryLensing::BinaryLightCurveParallax(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1684
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], rho = exp(pr[4]), tn,u, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8];
|
|
1685
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
1686
|
+
double Et[2];
|
|
1687
|
+
t0old = 0;
|
|
1688
|
+
|
|
1689
|
+
for (int i = 0; i < np; i++) {
|
|
1690
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1691
|
+
tn = (ts[i] - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
1692
|
+
u = u0 + pai1*Et[1] - pai2*Et[0];
|
|
1693
|
+
y1s[i] = u * salpha - tn*calpha;
|
|
1694
|
+
y2s[i] = -u * calpha - tn*salpha;
|
|
1695
|
+
mags[i] = BinaryMag2(s, q, y1s[i], y2s[i], rho);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
void VBBinaryLensing::BinaryLightCurveOrbital(double *pr, double *ts, double *mags, double *y1s, double *y2s, double *seps, int np) {
|
|
1701
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11];
|
|
1702
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
1703
|
+
double Et[2];
|
|
1704
|
+
double w, phi0, inc, phi, Cinc, Sinc, Cphi, Sphi, Cphi0, Sphi0, COm, SOm,s_true;
|
|
1705
|
+
double w13, w123, den, den0, u;
|
|
1706
|
+
t0old = 0;
|
|
1707
|
+
|
|
1708
|
+
w13 = w1*w1 + w3*w3;
|
|
1709
|
+
w123 = sqrt(w13 + w2*w2);
|
|
1710
|
+
w13 = sqrt(w13);
|
|
1711
|
+
if (w13>1.e-8) {
|
|
1712
|
+
w3 = (w3>1.e-8) ? w3 : 1.e-8;
|
|
1713
|
+
w = w3*w123 / w13;
|
|
1714
|
+
inc = acos(w2*w3 / w13 / w123);
|
|
1715
|
+
phi0 = atan2(-w1*w123, w3*w13);
|
|
1716
|
+
}
|
|
1717
|
+
else {
|
|
1718
|
+
w = w2;
|
|
1719
|
+
inc = 0.;
|
|
1720
|
+
phi0 = 0.;
|
|
1721
|
+
}
|
|
1722
|
+
Cphi0 = cos(phi0);
|
|
1723
|
+
Sphi0 = sin(phi0);
|
|
1724
|
+
Cinc = cos(inc);
|
|
1725
|
+
Sinc = sin(inc);
|
|
1726
|
+
den0 = sqrt(Cphi0*Cphi0 + Cinc*Cinc*Sphi0*Sphi0);
|
|
1727
|
+
s_true = s / den0; // orbital radius
|
|
1728
|
+
COm = (Cphi0*calpha + Cinc*salpha*Sphi0) / den0;
|
|
1729
|
+
SOm = (Cphi0*salpha - Cinc*calpha*Sphi0) / den0;
|
|
1730
|
+
|
|
1731
|
+
for (int i = 0; i < np; i++) {
|
|
1732
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1733
|
+
|
|
1734
|
+
phi = (ts[i] - t0_par)*w + phi0;
|
|
1735
|
+
Cphi = cos(phi);
|
|
1736
|
+
Sphi = sin(phi);
|
|
1737
|
+
den = sqrt(Cphi*Cphi + Cinc*Cinc*Sphi*Sphi);
|
|
1738
|
+
seps[i] = s_true*den; // projected separation at time ts[i]
|
|
1739
|
+
|
|
1740
|
+
u = u0 + pai1*Et[1] - pai2*Et[0];
|
|
1741
|
+
tn = (ts[i] - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
1742
|
+
y1s[i] = (Cphi*(u*SOm - tn*COm) + Cinc*Sphi*(u*COm + tn*SOm)) / den;
|
|
1743
|
+
y2s[i] = (-Cphi*(u*COm + tn*SOm) - Cinc*Sphi*(tn*COm - u*SOm)) / den;
|
|
1744
|
+
mags[i] = BinaryMag2(seps[i], q, y1s[i], y2s[i], rho);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
void VBBinaryLensing::BinaryLightCurveKepler(double *pr, double *ts, double *mags, double *y1s, double *y2s, double *seps, int np) {
|
|
1750
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], alpha = pr[3], rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11], szs = pr[12], ar = pr[13]+1.e-8;
|
|
1751
|
+
double Et[2];
|
|
1752
|
+
double u, w22, w11, w33, w12, w23, szs2, ar2, EE, dE;
|
|
1753
|
+
double wt2, smix, sqsmix, e, h, snu, co1EE0, co2EE0,cosE,sinE, co1tperi, tperi, EE0, M, a, St, psi, dM, conu, n;
|
|
1754
|
+
double arm1, arm2;
|
|
1755
|
+
double X[3], Y[3], Z[3],r[2],x[2];
|
|
1756
|
+
t0old = 0;
|
|
1757
|
+
|
|
1758
|
+
smix = 1 + szs * szs;
|
|
1759
|
+
sqsmix = sqrt(smix);
|
|
1760
|
+
w22 = w2 * w2;
|
|
1761
|
+
w11 = w1 * w1;
|
|
1762
|
+
w33 = w3 * w3;
|
|
1763
|
+
w12 = w11 + w22;
|
|
1764
|
+
w23 = w22 + w33;
|
|
1765
|
+
wt2 = w12 + w33;
|
|
1766
|
+
|
|
1767
|
+
szs2 = szs * szs;
|
|
1768
|
+
ar2 = ar * ar;
|
|
1769
|
+
arm1 = ar - 1;
|
|
1770
|
+
arm2 = 2 * ar - 1;
|
|
1771
|
+
// n = sqrt(wt2) / (ar*sqrt(-1 + 2 * ar)*sqrt(smix));
|
|
1772
|
+
n = sqrt(wt2 / arm2 / smix) / ar;
|
|
1773
|
+
Z[0] = -szs * w2;
|
|
1774
|
+
Z[1] = szs * w1 - w3;
|
|
1775
|
+
Z[2] = w2;
|
|
1776
|
+
h = sqrt(Z[0] * Z[0] + Z[1] * Z[1] + Z[2] * Z[2]);
|
|
1777
|
+
for (int i = 0; i < 3; i++) Z[i] /= h;
|
|
1778
|
+
X[0] = -ar * w11 + arm1 * w22 - arm2 * szs*w1*w3 + arm1 * w33;
|
|
1779
|
+
X[1] = -arm2 *w2*(w1 + szs * w3);
|
|
1780
|
+
X[2] = arm1 * szs*w12 - arm2 * w1*w3 - ar * szs*w33;
|
|
1781
|
+
e = sqrt(X[0] * X[0] + X[1] * X[1] + X[2] * X[2]);
|
|
1782
|
+
for (int i = 0; i < 3; i++) X[i] /= e;
|
|
1783
|
+
e /= ar * sqsmix*wt2;
|
|
1784
|
+
Y[0] = Z[1] * X[2] - Z[2] * X[1];
|
|
1785
|
+
Y[1] = Z[2] * X[0] - Z[0] * X[2];
|
|
1786
|
+
Y[2] = Z[0] * X[1] - Z[1] * X[0];
|
|
1787
|
+
|
|
1788
|
+
// h = sqrt((smix)*w22 + (szs*w1 - w3)*(szs*w1 - w3));
|
|
1789
|
+
// co1e = (1 - ar)*(1 - ar) + ar2 * szs2 + (-1 + 2 * ar)*(w11*(1 - szs2) - szs2 * w22 + 2 * szs*w1*w3) / wt2;
|
|
1790
|
+
// co1nu = ar2 * szs2 + arm2 * (w11*(1 - szs2) - szs2 * w22 + 2 * szs*w1*w3) / wt2;
|
|
1791
|
+
// co1e = arm1*arm1 + co1nu;
|
|
1792
|
+
// coe2 = ar2 * smix;
|
|
1793
|
+
// e = sqrt(co1e/coe2);
|
|
1794
|
+
// co1nu = (-1 + 2 * ar)*sqrt(smix)*(w1 + szs * w3)*(szs2*(w12)-2 * szs*w1*w3 + w23);
|
|
1795
|
+
// co2nu = ar * e*h*(smix)*sqrt((smix))*wt2;
|
|
1796
|
+
conu = (X[0] + X[2] * szs) / sqsmix;
|
|
1797
|
+
co1EE0 = conu + e;
|
|
1798
|
+
co2EE0 = 1 + e * conu;
|
|
1799
|
+
cosE = co1EE0 / co2EE0;
|
|
1800
|
+
EE0 = acos(cosE);
|
|
1801
|
+
snu = (Y[0] + Y[2] * szs);
|
|
1802
|
+
EE0 *= (snu > 0) ? 1 : -1;
|
|
1803
|
+
sinE = sqrt(1 - cosE * cosE)*((snu > 0) ? 1 : -1);
|
|
1804
|
+
co1tperi = e * sinE;
|
|
1805
|
+
tperi = t0_par - (EE0 - co1tperi) / n;
|
|
1806
|
+
// coX = ar * e*sqrt(smix)*wt2;
|
|
1807
|
+
//coX1 = -ar * w11 + (-1 + ar)*w22 + (1 - 2 * ar)*szs*w1*w3 + (-1 + ar)*w33;
|
|
1808
|
+
//coX2 = (-1 + 2 * ar)*w1*w23 + szs2 * w1*((-1 + ar)*w12 - ar * w33) + szs * w3*((2 - 3 * ar)*w11 + ar * w23);
|
|
1809
|
+
//coY1 = -(-1 + 2 * ar)*w2*(w1 + szs * w3);
|
|
1810
|
+
//coY2 = w2 * (-szs2 * w12 + 2 * szs*w1*w3 - w23 + ar * (-4 * szs*w1*w3 + szs2 * (w12 - w33) + (-w11 + w23)));
|
|
1811
|
+
for (int i = 0; i < np; i++) {
|
|
1812
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1813
|
+
M = n * (ts[i] - tperi);
|
|
1814
|
+
EE = M + e * sin(M);
|
|
1815
|
+
dE = 1;
|
|
1816
|
+
while (fabs(dE) > 1.e-8) {
|
|
1817
|
+
dM = M - (EE - e * sin(EE));
|
|
1818
|
+
dE = dM / (1 - e * cos(EE));
|
|
1819
|
+
EE += dE;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
a = ar * s*sqrt(smix);
|
|
1823
|
+
|
|
1824
|
+
r[0] = a * (cos(EE) - e);
|
|
1825
|
+
r[1] = a * sqrt(1 - e * e)*sin(EE);
|
|
1826
|
+
x[0] = r[0] * X[0] + r[1] * Y[0]; // (coX1*x[1] + coX2 * y[1] / h) / coX;
|
|
1827
|
+
x[1] = r[0] * X[1] + r[1] * Y[1]; //(coY1*x[1] + y[1] * coY2 / h) / coX;
|
|
1828
|
+
St = sqrt(x[0] * x[0] + x[1] * x[1]);
|
|
1829
|
+
psi = atan2(x[1], x[0]);// +((ar > 1) ? 0 : M_PI);
|
|
1830
|
+
u = u0 + pai1 * Et[1] - pai2 * Et[0];
|
|
1831
|
+
tn = (ts[i] - t0) * tE_inv + pai1 * Et[0] + pai2 * Et[1];
|
|
1832
|
+
y1s[i] = -tn * cos(alpha + psi) + u * sin(alpha + psi);
|
|
1833
|
+
y2s[i] = -u * cos(alpha + psi) - tn * sin(alpha + psi);
|
|
1834
|
+
seps[i] = St;
|
|
1835
|
+
|
|
1836
|
+
mags[i] = BinaryMag2(seps[i], q, y1s[i], y2s[i], rho);
|
|
1837
|
+
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
void VBBinaryLensing::BinSourceLightCurve(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1842
|
+
double u1 = pr[2], u2=pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR=exp(pr[1]), tn, u;
|
|
1843
|
+
|
|
1844
|
+
for (int i = 0; i < np; i++) {
|
|
1845
|
+
tn = (ts[i] - t01) * tE_inv;
|
|
1846
|
+
u = tn*tn + u1*u1;
|
|
1847
|
+
|
|
1848
|
+
y1s[i] = -tn;
|
|
1849
|
+
y2s[i] = -u1;
|
|
1850
|
+
mags[i] = (u + 2) / sqrt(u*(u + 4));
|
|
1851
|
+
|
|
1852
|
+
tn = (ts[i] - t02) * tE_inv;
|
|
1853
|
+
u = tn*tn + u2*u2;
|
|
1854
|
+
|
|
1855
|
+
mags[i] += FR*(u + 2) / sqrt(u*(u + 4));
|
|
1856
|
+
mags[i] /= (1 + FR);
|
|
1857
|
+
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
void VBBinaryLensing::BinSourceLightCurveParallax(double *pr, double *ts, double *mags, double *y1s, double *y2s, int np) {
|
|
1864
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), tn, u, u0, pai1 = pr[6], pai2 = pr[7], w1 = pr[8], w2 = pr[9], w3 = pr[10];
|
|
1865
|
+
double Et[2];
|
|
1866
|
+
t0old = 0;
|
|
1867
|
+
|
|
1868
|
+
for (int i = 0; i < np; i++) {
|
|
1869
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1870
|
+
|
|
1871
|
+
tn = (ts[i] - t01) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
1872
|
+
u0 = u1 + pai1*Et[1] - pai2*Et[0];
|
|
1873
|
+
u = tn*tn + u0*u0;
|
|
1874
|
+
|
|
1875
|
+
y1s[i] = -tn;
|
|
1876
|
+
y2s[i] = -u0;
|
|
1877
|
+
mags[i] = (u + 2) / sqrt(u*(u + 4));
|
|
1878
|
+
|
|
1879
|
+
tn = (ts[i] - t02) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
1880
|
+
u0 = u2 + pai1*Et[1] - pai2*Et[0];
|
|
1881
|
+
u = tn*tn + u0*u0;
|
|
1882
|
+
|
|
1883
|
+
mags[i] += FR*(u + 2) / sqrt(u*(u + 4));
|
|
1884
|
+
mags[i] /= (1 + FR);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
|
|
1889
|
+
void VBBinaryLensing::BinSourceLightCurveXallarap(double *pr, double *ts, double *mags, double *y1s, double *y2s,double *seps, int np) {
|
|
1890
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), tn, u, u0, pai1 = pr[6], pai2 = pr[7], q = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11];
|
|
1891
|
+
double th,Cth,Sth;
|
|
1892
|
+
double Et[2];
|
|
1893
|
+
double s,s_true,w, phi0, inc, phi, Cinc, Sinc, Cphi, Sphi, Cphi0, Sphi0, COm, SOm;
|
|
1894
|
+
double w13, w123, den, den0,du0,dt0;
|
|
1895
|
+
t0old = 0;
|
|
1896
|
+
|
|
1897
|
+
s = sqrt((u1 - u2)*(u1 - u2) + (t01 - t02)*(t01 - t02) * (tE_inv*tE_inv));
|
|
1898
|
+
th = atan2((u1 - u2) , (tE_inv*(t01 - t02)));
|
|
1899
|
+
Cth = cos(th);
|
|
1900
|
+
Sth = sin(th);
|
|
1901
|
+
u0 = (u1 + u2*q) / (1 + q);
|
|
1902
|
+
t0 = (t01 + t02*q) / (1 + q);
|
|
1903
|
+
|
|
1904
|
+
w13 = w1*w1 + w3*w3;
|
|
1905
|
+
w123 = sqrt(w13 + w2*w2);
|
|
1906
|
+
w13 = sqrt(w13);
|
|
1907
|
+
if (w13>1.e-8) {
|
|
1908
|
+
w3 = (w3>1.e-8) ? w3 : 1.e-8;
|
|
1909
|
+
w = w3*w123 / w13;
|
|
1910
|
+
inc = acos(w2*w3 / w13 / w123);
|
|
1911
|
+
phi0 = atan2(-w1*w123, w3*w13);
|
|
1912
|
+
}
|
|
1913
|
+
else {
|
|
1914
|
+
w = w2;
|
|
1915
|
+
inc = 0.;
|
|
1916
|
+
phi0 = 0.;
|
|
1917
|
+
}
|
|
1918
|
+
Cphi0 = cos(phi0);
|
|
1919
|
+
Sphi0 = sin(phi0);
|
|
1920
|
+
Cinc = cos(inc);
|
|
1921
|
+
Sinc = sin(inc);
|
|
1922
|
+
den0 = sqrt(Cphi0*Cphi0 + Cinc*Cinc*Sphi0*Sphi0);
|
|
1923
|
+
s_true = s / den0;
|
|
1924
|
+
COm = (Cphi0*Cth + Cinc*Sth*Sphi0) / den0;
|
|
1925
|
+
SOm = (Cphi0*Sth - Cinc*Cth*Sphi0) / den0;
|
|
1926
|
+
|
|
1927
|
+
|
|
1928
|
+
for (int i = 0; i < np; i++) {
|
|
1929
|
+
ComputeParallax(ts[i], t0, Et);
|
|
1930
|
+
|
|
1931
|
+
phi = (ts[i] - t0_par)*w + phi0;
|
|
1932
|
+
Cphi = cos(phi);
|
|
1933
|
+
Sphi = sin(phi);
|
|
1934
|
+
den = sqrt(Cphi*Cphi + Cinc*Cinc*Sphi*Sphi);
|
|
1935
|
+
seps[i] = s_true*den;
|
|
1936
|
+
|
|
1937
|
+
dt0 = s_true*(COm*Cphi-Cinc*SOm*Sphi)/(1+q)*q; //Position of the primary component with respect to center of mass
|
|
1938
|
+
du0 = s_true*(SOm*Cphi + Cinc*COm*Sphi) / (1 + q)*q;
|
|
1939
|
+
|
|
1940
|
+
tn= -((ts[i] - t0_par) * tE_inv + dt0 + pai1*Et[0] + pai2*Et[1]);
|
|
1941
|
+
u= -(u0+du0 + pai1*Et[1] - pai2*Et[0]);
|
|
1942
|
+
y1s[i] = tn;
|
|
1943
|
+
y2s[i] = u;
|
|
1944
|
+
u = tn*tn + u*u;
|
|
1945
|
+
|
|
1946
|
+
mags[i] = (u + 2) / sqrt(u*(u + 4));
|
|
1947
|
+
|
|
1948
|
+
tn =-( (ts[i] - t0_par) * tE_inv -dt0/q + pai1*Et[0] + pai2*Et[1]); // Position of the secondary component
|
|
1949
|
+
u =-( u0 - du0/q + pai1*Et[1] - pai2*Et[0]);
|
|
1950
|
+
u = tn*tn + u*u;
|
|
1951
|
+
|
|
1952
|
+
mags[i] += FR*(u + 2) / sqrt(u*(u + 4));
|
|
1953
|
+
mags[i] /= (1 + FR);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
void VBBinaryLensing::BinSourceExtLightCurve(double* pr, double* ts, double* mags, double* y1s, double* y2s, int np) {
|
|
1959
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), rho = exp(pr[6]), rho2, tn, u;
|
|
1960
|
+
|
|
1961
|
+
for (int i = 0; i < np; i++) {
|
|
1962
|
+
tn = (ts[i] - t01) * tE_inv;
|
|
1963
|
+
u = tn * tn + u1 * u1;
|
|
1964
|
+
|
|
1965
|
+
y1s[i] = -tn;
|
|
1966
|
+
y2s[i] = -u1;
|
|
1967
|
+
mags[i] = ESPLMag2(sqrt(u),rho);
|
|
1968
|
+
|
|
1969
|
+
tn = (ts[i] - t02) * tE_inv;
|
|
1970
|
+
u = tn * tn + u2 * u2;
|
|
1971
|
+
rho2 = rho * pow(FR, mass_radius_exponent / mass_luminosity_exponent);
|
|
1972
|
+
mags[i] += FR * ESPLMag2(sqrt(u), rho2);
|
|
1973
|
+
mags[i] /= (1 + FR);
|
|
1974
|
+
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
void VBBinaryLensing::BinSourceBinLensXallarap(double* pr, double* ts, double* mags, double* y1s, double* y2s, int np) {
|
|
1980
|
+
double s = exp(pr[0]), q = exp(pr[1]), rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), u0;
|
|
1981
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]), xi1 = pr[7], xi2 = pr[8], omega = pr[9], inc = pr[10], phi = pr[11], qs = exp(pr[12]);
|
|
1982
|
+
|
|
1983
|
+
double Xal[2], phit, disp[2], Xal2[2], disp2[2];
|
|
1984
|
+
double Mag, Mag2, u02, rho2, tn2, y1s2, y2s2, qs4;
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
|
|
1988
|
+
if (t0_par_fixed == 0) t0_par = pr[6];
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
for (int i = 0; i < np; i++) {
|
|
1992
|
+
|
|
1993
|
+
phit = omega * (ts[i] - t0_par);
|
|
1994
|
+
|
|
1995
|
+
disp[0] = sin(inc) * (-cos(phi) + cos(phi + phit) + phit * sin(phi));
|
|
1996
|
+
|
|
1997
|
+
disp[1] = -phit * cos(phi) - sin(phi) + sin(phi + phit);
|
|
1998
|
+
|
|
1999
|
+
Xal[0] = xi1 * disp[0] + xi2 * disp[1];
|
|
2000
|
+
Xal[1] = xi2 * disp[0] - xi1 * disp[1];
|
|
2001
|
+
tn = (ts[i] - pr[6]) * tE_inv + Xal[0];
|
|
2002
|
+
u0 = pr[2] + Xal[1];
|
|
2003
|
+
y1s[i] = u0 * salpha - tn * calpha;
|
|
2004
|
+
y2s[i] = -u0 * calpha - tn * salpha;
|
|
2005
|
+
Mag = BinaryMag2(s, q, y1s[i], y2s[i], rho);
|
|
2006
|
+
|
|
2007
|
+
disp2[0] = -sin(inc) * (cos(phi) + cos(phi + phit) / qs - phit * sin(phi));
|
|
2008
|
+
|
|
2009
|
+
disp2[1] = phit * cos(phi) + sin(phi) + sin(phi + phit) / qs;
|
|
2010
|
+
|
|
2011
|
+
Xal2[0] = xi1 * disp2[0] - xi2 * disp2[1];
|
|
2012
|
+
Xal2[1] = xi2 * disp2[0] + xi1 * disp2[1];
|
|
2013
|
+
tn2 = (ts[i] - pr[6]) * tE_inv + Xal2[0];
|
|
2014
|
+
u02 = pr[2] + Xal2[1];
|
|
2015
|
+
y1s2 = u02 * salpha - tn2 * calpha;
|
|
2016
|
+
y2s2 = -u02 * calpha - tn2 * salpha;
|
|
2017
|
+
rho2 = rho * pow(qs, mass_radius_exponent);
|
|
2018
|
+
Mag2 = BinaryMag2(s, q, y1s2, y2s2, rho2);
|
|
2019
|
+
qs4 = pow(qs, mass_luminosity_exponent);
|
|
2020
|
+
mags[i] = (Mag + qs4 * Mag2) / (1 + qs4);
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
void VBBinaryLensing::BinSourceSingleLensXallarap(double* pr, double* ts, double* mags, double* y1s, double* y2s, double* y1s2, double* y2s2, int np) {
|
|
2025
|
+
double t0 = pr[1], rho = exp(pr[3]), tn, tE_inv = exp(-pr[2]), u0;
|
|
2026
|
+
double xi1 = pr[4], xi2 = pr[5], omega = pr[6], inc = pr[7], phi = pr[8], qs = exp(pr[9]);
|
|
2027
|
+
|
|
2028
|
+
double Xal[2], phit, disp[2], Xal2[2], disp2[2];
|
|
2029
|
+
double Mag, Mag2, u02, rho2, tn2, qs4, u, u2;
|
|
2030
|
+
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
t0_par = pr[1];
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
for (int i = 0; i < np; i++) {
|
|
2037
|
+
|
|
2038
|
+
phit = omega * (ts[i] - t0_par);
|
|
2039
|
+
|
|
2040
|
+
disp[0] = cos(inc) * (-cos(phi) + cos(phi + phit) + phit * sin(phi));
|
|
2041
|
+
|
|
2042
|
+
disp[1] = -phit * cos(phi) - sin(phi) + sin(phi + phit);
|
|
2043
|
+
|
|
2044
|
+
Xal[0] = xi1 * disp[0] + xi2 * disp[1];
|
|
2045
|
+
Xal[1] = xi2 * disp[0] - xi1 * disp[1];
|
|
2046
|
+
tn = (ts[i] - pr[1]) * tE_inv + Xal[0];
|
|
2047
|
+
u0 = pr[0] + Xal[1];
|
|
2048
|
+
u = sqrt(tn * tn + u0 * u0);
|
|
2049
|
+
|
|
2050
|
+
y1s[i] = -tn;
|
|
2051
|
+
y2s[i] = -u0;
|
|
2052
|
+
Mag = ESPLMag2(u, rho); /*If you want only the second source put =0, otherwise replace ESPLMag2(u, rho);*/
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
disp2[0] = -cos(inc) * (cos(phi) + cos(phi + phit) / qs - phit * sin(phi));
|
|
2056
|
+
|
|
2057
|
+
disp2[1] = phit * cos(phi) + sin(phi) + sin(phi + phit) / qs;
|
|
2058
|
+
|
|
2059
|
+
Xal2[0] = xi1 * disp2[0] - xi2 * disp2[1];
|
|
2060
|
+
Xal2[1] = xi2 * disp2[0] + xi1 * disp2[1];
|
|
2061
|
+
tn2 = (ts[i] - pr[1]) * tE_inv + Xal2[0];
|
|
2062
|
+
u02 = pr[0] + Xal2[1];
|
|
2063
|
+
u2 = sqrt(tn2 * tn2 + u02 * u02);
|
|
2064
|
+
y1s2[i] = -tn2;
|
|
2065
|
+
y2s2[i] = -u02;
|
|
2066
|
+
rho2 = rho * pow(qs, mass_radius_exponent);
|
|
2067
|
+
Mag2 = ESPLMag2(u2, rho2); /*If you want only the second source put =0, otherwise replace ESPLMag2(u2, rho2);*/
|
|
2068
|
+
qs4 = pow(qs, mass_luminosity_exponent);
|
|
2069
|
+
mags[i] = (Mag + qs4 * Mag2) / (1 + qs4);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
//////////////////////////////
|
|
2074
|
+
//////////////////////////////
|
|
2075
|
+
////////Old (v1) light curve functions
|
|
2076
|
+
//////////////////////////////
|
|
2077
|
+
//////////////////////////////
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
double VBBinaryLensing::PSPLLightCurve(double *pr, double t) {
|
|
2081
|
+
double u0 = exp(pr[0]), t0 = pr[2], tE_inv = exp(-pr[1]), tn, u;
|
|
2082
|
+
|
|
2083
|
+
tn = (t - t0) *tE_inv;
|
|
2084
|
+
u = tn*tn + u0*u0;
|
|
2085
|
+
|
|
2086
|
+
y_1 = -tn;
|
|
2087
|
+
y_2 = -u0;
|
|
2088
|
+
return (u + 2) / sqrt(u*(u + 4));
|
|
2089
|
+
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
double VBBinaryLensing::PSPLLightCurveParallax(double *pr, double t) {
|
|
2094
|
+
double u0 = pr[0], t0 = pr[2], tE_inv = exp(-pr[1]), tn, u, u1, pai1 = pr[3], pai2 = pr[4];
|
|
2095
|
+
double Et[2];
|
|
2096
|
+
|
|
2097
|
+
ComputeParallax(t, t0, Et);
|
|
2098
|
+
tn = (t - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
2099
|
+
u1 = u0 + pai1*Et[1] - pai2*Et[0];
|
|
2100
|
+
u = tn*tn + u1*u1;
|
|
2101
|
+
|
|
2102
|
+
y_1 = -tn;
|
|
2103
|
+
y_2 = -u1;
|
|
2104
|
+
return (u + 2) / sqrt(u*(u + 4));
|
|
2105
|
+
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
double VBBinaryLensing::ESPLLightCurve(double *pr, double t) {
|
|
2110
|
+
double u0 = exp(pr[0]), t0 = pr[2], tE_inv = exp(-pr[1]), tn, u, rho = exp(pr[3]);
|
|
2111
|
+
|
|
2112
|
+
tn = (t - t0) *tE_inv;
|
|
2113
|
+
u = sqrt(tn*tn + u0*u0);
|
|
2114
|
+
|
|
2115
|
+
y_1 = -tn;
|
|
2116
|
+
y_2 = -u0;
|
|
2117
|
+
return ESPLMag2(u, rho);
|
|
2118
|
+
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
double VBBinaryLensing::ESPLLightCurveParallax(double *pr, double t) {
|
|
2122
|
+
double u0 = pr[0], t0 = pr[2], tE_inv = exp(-pr[1]), tn, u, u1, rho = exp(pr[3]), pai1 = pr[4], pai2 = pr[5];
|
|
2123
|
+
double Et[2];
|
|
2124
|
+
|
|
2125
|
+
ComputeParallax(t, t0, Et);
|
|
2126
|
+
tn = (t - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
2127
|
+
u1 = u0 + pai1*Et[1] - pai2*Et[0];
|
|
2128
|
+
u = sqrt(tn*tn + u1*u1);
|
|
2129
|
+
|
|
2130
|
+
y_1 = -tn;
|
|
2131
|
+
y_2 = -u1;
|
|
2132
|
+
return ESPLMag2(u, rho);
|
|
2133
|
+
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
double VBBinaryLensing::BinaryLightCurve(double *pr, double t) {
|
|
2138
|
+
double s = exp(pr[0]), q = exp(pr[1]), rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]);
|
|
2139
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
2140
|
+
|
|
2141
|
+
tn = (t - pr[6]) * tE_inv;
|
|
2142
|
+
y_1 = pr[2] * salpha - tn*calpha;
|
|
2143
|
+
y_2 = -pr[2] * calpha - tn*salpha;
|
|
2144
|
+
return BinaryMag2(s, q, y_1, y_2, rho);
|
|
2145
|
+
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
double VBBinaryLensing::BinaryLightCurveW(double *pr, double t) {
|
|
2150
|
+
double s = exp(pr[0]), q = exp(pr[1]), rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), t0, u0;
|
|
2151
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]), xc;
|
|
2152
|
+
|
|
2153
|
+
xc = (s - 1 / s) / (1 + q);
|
|
2154
|
+
if (xc<0) xc = 0.;
|
|
2155
|
+
t0 = pr[6] + xc*calpha / tE_inv;
|
|
2156
|
+
u0 = pr[2] + xc*salpha;
|
|
2157
|
+
|
|
2158
|
+
tn = (t - t0) * tE_inv;
|
|
2159
|
+
y_1 = u0 * salpha - tn*calpha;
|
|
2160
|
+
y_2 = -u0 * calpha - tn*salpha;
|
|
2161
|
+
return BinaryMag2(s, q, y_1, y_2, rho);
|
|
2162
|
+
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
|
|
2166
|
+
double VBBinaryLensing::BinaryLightCurveParallax(double *pr, double t) {
|
|
2167
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], rho = exp(pr[4]), tn, u, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8];
|
|
2168
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
2169
|
+
double Et[2];
|
|
2170
|
+
|
|
2171
|
+
ComputeParallax(t, t0, Et);
|
|
2172
|
+
tn = (t - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
2173
|
+
u = u0 + pai1*Et[1] - pai2*Et[0];
|
|
2174
|
+
y_1 = u * salpha - tn*calpha;
|
|
2175
|
+
y_2 = -u * calpha - tn*salpha;
|
|
2176
|
+
return BinaryMag2(s, q, y_1, y_2, rho);
|
|
2177
|
+
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
double VBBinaryLensing::BinaryLightCurveOrbital(double *pr, double t) {
|
|
2184
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11];
|
|
2185
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
2186
|
+
double Et[2];
|
|
2187
|
+
double w, phi0, inc, phi, Cinc, Sinc, Cphi, Sphi, Cphi0, Sphi0, COm, SOm, s_true;
|
|
2188
|
+
double w13, w123, den, den0, u;
|
|
2189
|
+
|
|
2190
|
+
w13 = w1*w1 + w3*w3;
|
|
2191
|
+
w123 = sqrt(w13 + w2*w2);
|
|
2192
|
+
w13 = sqrt(w13);
|
|
2193
|
+
if (w13>1.e-8) {
|
|
2194
|
+
w3 = (w3>1.e-8) ? w3 : 1.e-8;
|
|
2195
|
+
w = w3*w123 / w13;
|
|
2196
|
+
inc = acos(w2*w3 / w13 / w123);
|
|
2197
|
+
phi0 = atan2(-w1*w123, w3*w13);
|
|
2198
|
+
}
|
|
2199
|
+
else {
|
|
2200
|
+
w = w2;
|
|
2201
|
+
inc = 0.;
|
|
2202
|
+
phi0 = 0.;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
Cphi0 = cos(phi0);
|
|
2206
|
+
Sphi0 = sin(phi0);
|
|
2207
|
+
Cinc = cos(inc);
|
|
2208
|
+
Sinc = sin(inc);
|
|
2209
|
+
den0 = sqrt(Cphi0*Cphi0 + Cinc*Cinc*Sphi0*Sphi0);
|
|
2210
|
+
s_true = s / den0;
|
|
2211
|
+
COm = (Cphi0*calpha + Cinc*salpha*Sphi0) / den0;
|
|
2212
|
+
SOm = (Cphi0*salpha - Cinc*calpha*Sphi0) / den0;
|
|
2213
|
+
|
|
2214
|
+
ComputeParallax(t, t0, Et);
|
|
2215
|
+
|
|
2216
|
+
phi = (t - t0_par)*w + phi0;
|
|
2217
|
+
Cphi = cos(phi);
|
|
2218
|
+
Sphi = sin(phi);
|
|
2219
|
+
den = sqrt(Cphi*Cphi + Cinc*Cinc*Sphi*Sphi);
|
|
2220
|
+
av = s_true*den;
|
|
2221
|
+
|
|
2222
|
+
u = u0 + pai1*Et[1] - pai2*Et[0];
|
|
2223
|
+
tn = (t - t0) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
2224
|
+
y_1 = (Cphi*(u*SOm - tn*COm) + Cinc*Sphi*(u*COm + tn*SOm)) / den;
|
|
2225
|
+
y_2 = (-Cphi*(u*COm + tn*SOm) - Cinc*Sphi*(tn*COm - u*SOm)) / den;
|
|
2226
|
+
return BinaryMag2(av, q, y_1, y_2, rho);
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
double VBBinaryLensing::BinaryLightCurveKepler(double *pr, double t) {
|
|
2230
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], alpha = pr[3], rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11], szs = pr[12], ar = pr[13]+1.e-8;
|
|
2231
|
+
double Et[2];
|
|
2232
|
+
double u, w22, w11, w33, w12, w23, szs2, ar2, EE, dE;
|
|
2233
|
+
double wt2, smix, sqsmix, e, h, snu, co1EE0, co2EE0, cosE, sinE, co1tperi, tperi, EE0, M, a, St, psi, dM, conu, n;
|
|
2234
|
+
double arm1, arm2;
|
|
2235
|
+
double X[3], Y[3], Z[3], r[2], x[2];
|
|
2236
|
+
t0old = 0;
|
|
2237
|
+
|
|
2238
|
+
smix = 1 + szs * szs;
|
|
2239
|
+
sqsmix = sqrt(smix);
|
|
2240
|
+
w22 = w2 * w2;
|
|
2241
|
+
w11 = w1 * w1;
|
|
2242
|
+
w33 = w3 * w3;
|
|
2243
|
+
w12 = w11 + w22;
|
|
2244
|
+
w23 = w22 + w33;
|
|
2245
|
+
wt2 = w12 + w33;
|
|
2246
|
+
|
|
2247
|
+
szs2 = szs * szs;
|
|
2248
|
+
ar2 = ar * ar;
|
|
2249
|
+
arm1 = ar - 1;
|
|
2250
|
+
arm2 = 2 * ar - 1;
|
|
2251
|
+
n = sqrt(wt2 / arm2 / smix) / ar;
|
|
2252
|
+
Z[0] = -szs * w2;
|
|
2253
|
+
Z[1] = szs * w1 - w3;
|
|
2254
|
+
Z[2] = w2;
|
|
2255
|
+
h = sqrt(Z[0] * Z[0] + Z[1] * Z[1] + Z[2] * Z[2]);
|
|
2256
|
+
for (int i = 0; i < 3; i++) Z[i] /= h;
|
|
2257
|
+
X[0] = -ar * w11 + arm1 * w22 - arm2 * szs*w1*w3 + arm1 * w33;
|
|
2258
|
+
X[1] = -arm2 * w2*(w1 + szs * w3);
|
|
2259
|
+
X[2] = arm1 * szs*w12 - arm2 * w1*w3 - ar * szs*w33;
|
|
2260
|
+
e = sqrt(X[0] * X[0] + X[1] * X[1] + X[2] * X[2]);
|
|
2261
|
+
for (int i = 0; i < 3; i++) X[i] /= e;
|
|
2262
|
+
e /= ar * sqsmix*wt2;
|
|
2263
|
+
Y[0] = Z[1] * X[2] - Z[2] * X[1];
|
|
2264
|
+
Y[1] = Z[2] * X[0] - Z[0] * X[2];
|
|
2265
|
+
Y[2] = Z[0] * X[1] - Z[1] * X[0];
|
|
2266
|
+
|
|
2267
|
+
conu = (X[0] + X[2] * szs) / sqsmix;
|
|
2268
|
+
co1EE0 = conu + e;
|
|
2269
|
+
co2EE0 = 1 + e * conu;
|
|
2270
|
+
cosE = co1EE0 / co2EE0;
|
|
2271
|
+
EE0 = acos(cosE);
|
|
2272
|
+
snu = (Y[0] + Y[2] * szs);
|
|
2273
|
+
EE0 *= (snu > 0) ? 1 : -1;
|
|
2274
|
+
sinE = sqrt(1 - cosE * cosE)*((snu > 0) ? 1 : -1);
|
|
2275
|
+
co1tperi = e * sinE;
|
|
2276
|
+
tperi = t0_par - (EE0 - co1tperi) / n;
|
|
2277
|
+
|
|
2278
|
+
ComputeParallax(t, t0, Et);
|
|
2279
|
+
M = n * (t - tperi);
|
|
2280
|
+
EE = M + e * sin(M);
|
|
2281
|
+
dE = 1;
|
|
2282
|
+
while (fabs(dE) > 1.e-8) {
|
|
2283
|
+
dM = M - (EE - e * sin(EE));
|
|
2284
|
+
dE = dM / (1 - e * cos(EE));
|
|
2285
|
+
EE += dE;
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
a = ar * s*sqrt(smix);
|
|
2289
|
+
|
|
2290
|
+
r[0] = a * (cos(EE) - e);
|
|
2291
|
+
r[1] = a * sqrt(1 - e * e)*sin(EE);
|
|
2292
|
+
x[0] = r[0] * X[0] + r[1] * Y[0]; // (coX1*x[1] + coX2 * y[1] / h) / coX;
|
|
2293
|
+
x[1] = r[0] * X[1] + r[1] * Y[1]; //(coY1*x[1] + y[1] * coY2 / h) / coX;
|
|
2294
|
+
St = sqrt(x[0] * x[0] + x[1] * x[1]);
|
|
2295
|
+
psi = atan2(x[1], x[0]);// +((ar > 1) ? 0 : M_PI);
|
|
2296
|
+
|
|
2297
|
+
u = u0 + pai1 * Et[1] - pai2 * Et[0];
|
|
2298
|
+
tn = (t - t0) * tE_inv + pai1 * Et[0] + pai2 * Et[1];
|
|
2299
|
+
y_1 = -tn * cos(alpha + psi) + u * sin(alpha + psi);
|
|
2300
|
+
y_2 = -u * cos(alpha + psi) - tn * sin(alpha + psi);
|
|
2301
|
+
|
|
2302
|
+
return BinaryMag2(St, q, y_1, y_2, rho);
|
|
2303
|
+
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
//double VBBinaryLensing::BinaryLightCurveKepler(double *pr, double t) {
|
|
2307
|
+
// double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], alpha = pr[3], rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), t0 = pr[6], pai1 = pr[7], pai2 = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11], szs = pr[12], ar = pr[13];
|
|
2308
|
+
// double Et[2];
|
|
2309
|
+
// double u, w22, w11, w33, w12, w23, szs2, ar2, coe2, coX, coX1, coX2, coY1, coY2, EE, dE;
|
|
2310
|
+
// double wt2, smix, e, h, co1e, co1nu, co2nu, co1EE0, co2EE0, co1tperi, tperi, EE0, nu, M, a, St, psi, dM, conu, n;
|
|
2311
|
+
// double x[3], y[3];
|
|
2312
|
+
// t0old = 0;
|
|
2313
|
+
//
|
|
2314
|
+
// wt2 = w1 * w1 + w2 * w2 + w3 * w3;
|
|
2315
|
+
// smix = 1 + szs * szs;
|
|
2316
|
+
// w22 = w2 * w2;
|
|
2317
|
+
// w11 = w1 * w1;
|
|
2318
|
+
//
|
|
2319
|
+
// w33 = w3 * w3;
|
|
2320
|
+
// w12 = w11 + w22;
|
|
2321
|
+
// w23 = w22 + w33;
|
|
2322
|
+
// szs2 = szs * szs;
|
|
2323
|
+
// ar2 = ar * ar;
|
|
2324
|
+
// n = sqrt(wt2) / (ar*sqrt(-1 + 2 * ar)*sqrt(smix));
|
|
2325
|
+
// h = sqrt((smix)*w22 + (szs*w1 - w3)*(szs*w1 - w3));
|
|
2326
|
+
// co1e = (1 - ar)*(1 - ar) + ar2 * szs2 + (-1 + 2 * ar)*(w11*(1 - szs2) - szs2 * w22 + 2 * szs*w1*w3) / wt2;
|
|
2327
|
+
// coe2 = ar2 * (smix);
|
|
2328
|
+
// e = sqrt(co1e) / sqrt(coe2);
|
|
2329
|
+
// co1nu = (-1 + 2 * ar)*sqrt(smix)*(w1 + szs * w3)*(szs2*(w12)-2 * szs*w1*w3 + w23);
|
|
2330
|
+
// co2nu = ar * e*h*(smix)*sqrt((smix))*wt2;
|
|
2331
|
+
// nu = asin(co1nu / co2nu);
|
|
2332
|
+
// conu = cos(nu);
|
|
2333
|
+
// co1EE0 = conu + e;
|
|
2334
|
+
// co2EE0 = 1 + e * conu;
|
|
2335
|
+
// EE0 = acos(co1EE0 / co2EE0);
|
|
2336
|
+
// co1tperi = e * sin(EE0);
|
|
2337
|
+
// tperi = t0_par - (EE0 - co1tperi) / n;
|
|
2338
|
+
// coX = ar * e*sqrt(smix)*wt2;
|
|
2339
|
+
// coX1 = -ar * w11 + (-1 + ar)*w22 + (1 - 2 * ar)*szs*w1*w3 + (-1 + ar)*w33;
|
|
2340
|
+
// coX2 = (-1 + 2 * ar)*w1*w23 + szs2 * w1*((-1 + ar)*w12 - ar * w33) + szs * w3*((2 - 3 * ar)*w11 + ar * w23);
|
|
2341
|
+
// coY1 = -(-1 + 2 * ar)*w2*(w1 + szs * w3);
|
|
2342
|
+
// coY2 = w2 * (-szs2 * w12 + 2 * szs*w1*w3 - w23 + ar * (-4 * szs*w1*w3 + szs2 * (w12 - w33) + (-w11 + w23)));
|
|
2343
|
+
//
|
|
2344
|
+
// ComputeParallax(t, t0, Et);
|
|
2345
|
+
// M = n * (t - tperi);
|
|
2346
|
+
// EE = M + e * sin(M);
|
|
2347
|
+
// dE = 1;
|
|
2348
|
+
// while (fabs(dE) > 1.e-8) {
|
|
2349
|
+
// dM = M - (EE - e * sin(EE));
|
|
2350
|
+
// dE = dM / (1 - e * cos(EE));
|
|
2351
|
+
// EE += dE;
|
|
2352
|
+
// }
|
|
2353
|
+
//
|
|
2354
|
+
// a = ar * s*sqrt(smix);
|
|
2355
|
+
//
|
|
2356
|
+
// x[1] = a * (cos(EE) - e);
|
|
2357
|
+
// y[1] = a * sqrt(1 - e * e)*sin(EE);
|
|
2358
|
+
// x[2] = (coX1*x[1] + coX2 * y[1] / h) / coX;
|
|
2359
|
+
// y[2] = (coY1*x[1] + y[1] * coY2 / h) / coX;
|
|
2360
|
+
// St = sqrt(x[2] * x[2] + y[2] * y[2]);
|
|
2361
|
+
// psi = atan2(y[2], x[2])+ ((ar>1)? 0 : M_PI);
|
|
2362
|
+
// u = u0 + pai1 * Et[1] - pai2 * Et[0];
|
|
2363
|
+
// tn = (t - t0) * tE_inv + pai1 * Et[0] + pai2 * Et[1];
|
|
2364
|
+
// y_1 = -tn * cos(alpha + psi) + u * sin(alpha + psi);
|
|
2365
|
+
// y_2 = -u * cos(alpha + psi) - tn * sin(alpha + psi);
|
|
2366
|
+
//
|
|
2367
|
+
// return BinaryMag2(St, q, y_1, y_2, rho);
|
|
2368
|
+
//
|
|
2369
|
+
//}
|
|
2370
|
+
|
|
2371
|
+
double VBBinaryLensing::BinSourceLightCurve(double *pr, double t) {
|
|
2372
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), tn, u,mag;
|
|
2373
|
+
|
|
2374
|
+
tn = (t - t01) * tE_inv;
|
|
2375
|
+
u = tn*tn + u1*u1;
|
|
2376
|
+
|
|
2377
|
+
y_1 = -tn;
|
|
2378
|
+
y_2 = -u1;
|
|
2379
|
+
mag = (u + 2) / sqrt(u*(u + 4));
|
|
2380
|
+
|
|
2381
|
+
tn = (t - t02) * tE_inv;
|
|
2382
|
+
u = tn*tn + u2*u2;
|
|
2383
|
+
|
|
2384
|
+
mag += FR*(u + 2) / sqrt(u*(u + 4));
|
|
2385
|
+
mag /= (1 + FR);
|
|
2386
|
+
|
|
2387
|
+
return mag;
|
|
2388
|
+
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
double VBBinaryLensing::BinSourceLightCurveParallax(double *pr, double t) {
|
|
2392
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), tn, u, u0, pai1 = pr[6], pai2 = pr[7], w1 = pr[8], w2 = pr[9], w3 = pr[10];
|
|
2393
|
+
double Et[2],mag;
|
|
2394
|
+
|
|
2395
|
+
ComputeParallax(t, t0, Et);
|
|
2396
|
+
|
|
2397
|
+
tn = (t - t01) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
2398
|
+
u0 = u1 + pai1*Et[1] - pai2*Et[0];
|
|
2399
|
+
u = tn*tn + u0*u0;
|
|
2400
|
+
|
|
2401
|
+
y_1 = -tn;
|
|
2402
|
+
y_2 = -u0;
|
|
2403
|
+
mag = (u + 2) / sqrt(u*(u + 4));
|
|
2404
|
+
|
|
2405
|
+
tn = (t - t02) * tE_inv + pai1*Et[0] + pai2*Et[1];
|
|
2406
|
+
u0 = u2 + pai1*Et[1] - pai2*Et[0];
|
|
2407
|
+
u = tn*tn + u0*u0;
|
|
2408
|
+
|
|
2409
|
+
mag += FR*(u + 2) / sqrt(u*(u + 4));
|
|
2410
|
+
mag /= (1 + FR);
|
|
2411
|
+
|
|
2412
|
+
return mag;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
double VBBinaryLensing::BinSourceLightCurveXallarap(double *pr, double t) {
|
|
2417
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), tn, u, u0, pai1 = pr[6], pai2 = pr[7], q = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11];
|
|
2418
|
+
double th, Cth, Sth;
|
|
2419
|
+
double Et[2],mag;
|
|
2420
|
+
double s, s_true, w, phi0, inc, phi, Cinc, Sinc, Cphi, Sphi, Cphi0, Sphi0, COm, SOm;
|
|
2421
|
+
double w13, w123, den, den0, du0, dt0;
|
|
2422
|
+
|
|
2423
|
+
s = sqrt((u1 - u2)*(u1 - u2) + (t01 - t02)*(t01 - t02) * (tE_inv*tE_inv));
|
|
2424
|
+
th = atan2((u1 - u2), (tE_inv*(t01 - t02)));
|
|
2425
|
+
Cth = cos(th);
|
|
2426
|
+
Sth = sin(th);
|
|
2427
|
+
u0 = (u1 + u2*q) / (1 + q);
|
|
2428
|
+
t0 = (t01 + t02*q) / (1 + q);
|
|
2429
|
+
|
|
2430
|
+
w13 = w1*w1 + w3*w3;
|
|
2431
|
+
w123 = sqrt(w13 + w2*w2);
|
|
2432
|
+
w13 = sqrt(w13);
|
|
2433
|
+
if (w13>1.e-8) {
|
|
2434
|
+
w3 = (w3>1.e-8) ? w3 : 1.e-8;
|
|
2435
|
+
w = w3*w123 / w13;
|
|
2436
|
+
inc = acos(w2*w3 / w13 / w123);
|
|
2437
|
+
phi0 = atan2(-w1*w123, w3*w13);
|
|
2438
|
+
}
|
|
2439
|
+
else {
|
|
2440
|
+
w = w2;
|
|
2441
|
+
inc = 0.;
|
|
2442
|
+
phi0 = 0.;
|
|
2443
|
+
}
|
|
2444
|
+
Cphi0 = cos(phi0);
|
|
2445
|
+
Sphi0 = sin(phi0);
|
|
2446
|
+
Cinc = cos(inc);
|
|
2447
|
+
Sinc = sin(inc);
|
|
2448
|
+
den0 = sqrt(Cphi0*Cphi0 + Cinc*Cinc*Sphi0*Sphi0);
|
|
2449
|
+
s_true = s / den0;
|
|
2450
|
+
COm = (Cphi0*Cth + Cinc*Sth*Sphi0) / den0;
|
|
2451
|
+
SOm = (Cphi0*Sth - Cinc*Cth*Sphi0) / den0;
|
|
2452
|
+
|
|
2453
|
+
ComputeParallax(t, t0, Et);
|
|
2454
|
+
|
|
2455
|
+
phi = (t - t0_par)*w + phi0;
|
|
2456
|
+
Cphi = cos(phi);
|
|
2457
|
+
Sphi = sin(phi);
|
|
2458
|
+
den = sqrt(Cphi*Cphi + Cinc*Cinc*Sphi*Sphi);
|
|
2459
|
+
av = s_true*den;
|
|
2460
|
+
|
|
2461
|
+
dt0 = s_true*(COm*Cphi - Cinc*SOm*Sphi) / (1 + q)*q; //Position of the primary component with respect to center of mass
|
|
2462
|
+
du0 = s_true*(SOm*Cphi + Cinc*COm*Sphi) / (1 + q)*q;
|
|
2463
|
+
|
|
2464
|
+
tn = -((t - t0_par) * tE_inv - dt0 + pai1*Et[0] + pai2*Et[1]);
|
|
2465
|
+
u = -(u0 + du0 + pai1*Et[1] - pai2*Et[0]);
|
|
2466
|
+
y_1 = tn;
|
|
2467
|
+
y_2 = u;
|
|
2468
|
+
u = tn*tn + u*u;
|
|
2469
|
+
|
|
2470
|
+
mag = (u + 2) / sqrt(u*(u + 4));
|
|
2471
|
+
|
|
2472
|
+
tn = -((t - t0_par) * tE_inv + dt0 / q + pai1*Et[0] + pai2*Et[1]); // Position of the secondary component
|
|
2473
|
+
u = -(u0 - du0 / q + pai1*Et[1] - pai2*Et[0]);
|
|
2474
|
+
u = tn*tn + u*u;
|
|
2475
|
+
|
|
2476
|
+
mag += FR*(u + 2) / sqrt(u*(u + 4));
|
|
2477
|
+
mag /= (1 + FR);
|
|
2478
|
+
|
|
2479
|
+
return mag;
|
|
2480
|
+
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
|
|
2484
|
+
double VBBinaryLensing::BinSourceExtLightCurve(double* pr, double t) {
|
|
2485
|
+
double u1 = pr[2], u2 = pr[3], t01 = pr[4], t02 = pr[5], tE_inv = exp(-pr[0]), FR = exp(pr[1]), rho = exp(pr[6]), rho2, tn, u, mag;
|
|
2486
|
+
|
|
2487
|
+
tn = (t - t01) * tE_inv;
|
|
2488
|
+
u = tn * tn + u1 * u1;
|
|
2489
|
+
|
|
2490
|
+
y_1 = -tn;
|
|
2491
|
+
y_2 = -u1;
|
|
2492
|
+
mag = ESPLMag2(sqrt(u), rho);
|
|
2493
|
+
|
|
2494
|
+
tn = (t - t02) * tE_inv;
|
|
2495
|
+
u = tn * tn + u2 * u2;
|
|
2496
|
+
rho2 = rho * pow(FR, mass_radius_exponent / mass_luminosity_exponent);
|
|
2497
|
+
|
|
2498
|
+
mag += FR * ESPLMag2(sqrt(u), rho2);
|
|
2499
|
+
mag /= (1 + FR);
|
|
2500
|
+
|
|
2501
|
+
return mag;
|
|
2502
|
+
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
|
|
2506
|
+
double VBBinaryLensing::BinSourceBinLensXallarap(double* pr, double t) {
|
|
2507
|
+
|
|
2508
|
+
double s = exp(pr[0]), q = exp(pr[1]), rho = exp(pr[4]), tn, tE_inv = exp(-pr[5]), u0;
|
|
2509
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]), xi1 = pr[7], xi2 = pr[8], omega = pr[9], inc = pr[10], phi = pr[11], qs = exp(pr[12]);
|
|
2510
|
+
|
|
2511
|
+
double Xal[2], phit, disp[2], Xal2[2], disp2[2];
|
|
2512
|
+
double Mag, Mag2, u02, rho2, tn2, y1s2, y2s2, y1s, y2s, mags, qs4;
|
|
2513
|
+
|
|
2514
|
+
|
|
2515
|
+
|
|
2516
|
+
if (t0_par_fixed == 0) t0_par = pr[6];
|
|
2517
|
+
|
|
2518
|
+
|
|
2519
|
+
|
|
2520
|
+
|
|
2521
|
+
phit = omega * (t - t0_par);
|
|
2522
|
+
|
|
2523
|
+
disp[0] = cos(inc) * (-cos(phi) + cos(phi + phit) + phit * sin(phi));
|
|
2524
|
+
|
|
2525
|
+
disp[1] = -phit * cos(phi) - sin(phi) + sin(phi + phit);
|
|
2526
|
+
|
|
2527
|
+
Xal[0] = xi1 * disp[0] + xi2 * disp[1];
|
|
2528
|
+
Xal[1] = xi2 * disp[0] - xi1 * disp[1];
|
|
2529
|
+
tn = (t - pr[6]) * tE_inv + Xal[0];
|
|
2530
|
+
u0 = pr[2] + Xal[1];
|
|
2531
|
+
y1s = u0 * salpha - tn * calpha;
|
|
2532
|
+
y2s = -u0 * calpha - tn * salpha;
|
|
2533
|
+
Mag = BinaryMag2(s, q, y1s, y2s, rho);
|
|
2534
|
+
|
|
2535
|
+
disp2[0] = -cos(inc) * (cos(phi) + cos(phi + phit) / qs - phit * sin(phi));
|
|
2536
|
+
|
|
2537
|
+
disp2[1] = phit * cos(phi) + sin(phi) + sin(phi + phit) / qs;
|
|
2538
|
+
|
|
2539
|
+
Xal2[0] = xi1 * disp2[0] - xi2 * disp2[1];
|
|
2540
|
+
Xal2[1] = xi2 * disp2[0] + xi1 * disp2[1];
|
|
2541
|
+
tn2 = (t - pr[6]) * tE_inv + Xal2[0];
|
|
2542
|
+
u02 = pr[2] + Xal2[1];
|
|
2543
|
+
y1s2 = u02 * salpha - tn2 * calpha;
|
|
2544
|
+
y2s2 = -u02 * calpha - tn2 * salpha;
|
|
2545
|
+
rho2 = rho * pow(qs, mass_radius_exponent);
|
|
2546
|
+
Mag2 = BinaryMag2(s, q, y1s2, y2s2, rho2);
|
|
2547
|
+
qs4 = pow(qs, mass_luminosity_exponent);
|
|
2548
|
+
mags = (Mag + qs4*Mag2) / (1 + qs4);
|
|
2549
|
+
|
|
2550
|
+
return mags;
|
|
2551
|
+
|
|
2552
|
+
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
double VBBinaryLensing::BinSourceSingleLensXallarap(double* pr, double t) {
|
|
2556
|
+
|
|
2557
|
+
double t0 = pr[1], rho = exp(pr[3]), tn, tE_inv = exp(-pr[2]), u0;
|
|
2558
|
+
double xi1 = pr[4], xi2 = pr[5], omega = pr[6], inc = pr[7], phi = pr[8], qs = exp(pr[9]);
|
|
2559
|
+
|
|
2560
|
+
double Xal[2], phit, disp[2], Xal2[2], disp2[2];
|
|
2561
|
+
double Mag, Mag2, u02, rho2, tn2, y1s2, y2s2, qs4, u, y1s, y2s, mags, u2;
|
|
2562
|
+
|
|
2563
|
+
|
|
2564
|
+
|
|
2565
|
+
t0_par = pr[1];
|
|
2566
|
+
|
|
2567
|
+
phit = omega * (t - t0_par);
|
|
2568
|
+
|
|
2569
|
+
disp[0] = cos(inc) * (-cos(phi) + cos(phi + phit) + phit * sin(phi));
|
|
2570
|
+
|
|
2571
|
+
disp[1] = -phit * cos(phi) - sin(phi) + sin(phi + phit);
|
|
2572
|
+
|
|
2573
|
+
Xal[0] = xi1 * disp[0] + xi2 * disp[1];
|
|
2574
|
+
Xal[1] = xi2 * disp[0] - xi1 * disp[1];
|
|
2575
|
+
tn = (t - pr[1]) * tE_inv + Xal[0];
|
|
2576
|
+
u0 = pr[0] + Xal[1];
|
|
2577
|
+
u = sqrt(tn * tn + u0 * u0);
|
|
2578
|
+
|
|
2579
|
+
y1s = -tn;
|
|
2580
|
+
y2s = -u0;
|
|
2581
|
+
Mag = ESPLMag2(u, rho); /*If you want only the second source put =0, otherwise replace ESPLMag2(u, rho);*/
|
|
2582
|
+
|
|
2583
|
+
|
|
2584
|
+
disp2[0] = -cos(inc) * (cos(phi) + cos(phi + phit) / qs - phit * sin(phi));
|
|
2585
|
+
|
|
2586
|
+
disp2[1] = phit * cos(phi) + sin(phi) + sin(phi + phit) / qs;
|
|
2587
|
+
|
|
2588
|
+
Xal2[0] = xi1 * disp2[0] - xi2 * disp2[1];
|
|
2589
|
+
Xal2[1] = xi2 * disp2[0] + xi1 * disp2[1];
|
|
2590
|
+
tn2 = (t - pr[1]) * tE_inv + Xal2[0];
|
|
2591
|
+
u02 = pr[0] + Xal2[1];
|
|
2592
|
+
u2 = sqrt(tn2 * tn2 + u02 * u02);
|
|
2593
|
+
y1s2 = -tn2;
|
|
2594
|
+
y2s2 = -u02;
|
|
2595
|
+
rho2 = rho * pow(qs, mass_radius_exponent);
|
|
2596
|
+
Mag2 = ESPLMag2(u2, rho2); /*If you want only the second source put =0, otherwise replace ESPLMag2(u2, rho2);*/
|
|
2597
|
+
qs4 = pow(qs, mass_luminosity_exponent);
|
|
2598
|
+
mags = (Mag + qs4 * Mag2) / (1 + qs4);
|
|
2599
|
+
return mags;
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
double VBBinaryLensing::BinSourceBinLensPOX(double* pr, double t) {
|
|
2603
|
+
double s = exp(pr[0]), q = exp(pr[1]), u0 = pr[2], rho = exp(pr[4]), tE_inv = exp(-pr[5]), t0 = pr[6];
|
|
2604
|
+
double pai1 = pr[7], pai2 = pr[8], w1 = pr[9], w2 = pr[10], w3 = pr[11];
|
|
2605
|
+
double salpha = sin(pr[3]), calpha = cos(pr[3]);
|
|
2606
|
+
double Et[2];
|
|
2607
|
+
double tn, w, phi0, phil, incl, Cinc, Sinc, Cphi, Sphi, Cphi0, Sphi0, COm, SOm, s_true;
|
|
2608
|
+
double w13, w123, den, den0, u;
|
|
2609
|
+
|
|
2610
|
+
double xi1 = pr[12], xi2 = pr[13], omega = pr[14], inc = pr[15], phi = pr[16], qs = exp(pr[17]);
|
|
2611
|
+
double Xal[2], phit, disp[2], Xal2[2], disp2[2];
|
|
2612
|
+
double Mag, Mag2, u01, u02, rho2, tn1, tn2, mags, qs4;
|
|
2613
|
+
|
|
2614
|
+
w13 = w1 * w1 + w3 * w3;
|
|
2615
|
+
w123 = sqrt(w13 + w2 * w2);
|
|
2616
|
+
w13 = sqrt(w13);
|
|
2617
|
+
if (w13 > 1.e-8) {
|
|
2618
|
+
w3 = (w3 > 1.e-8) ? w3 : 1.e-8;
|
|
2619
|
+
w = w3 * w123 / w13;
|
|
2620
|
+
incl = acos(w2 * w3 / w13 / w123);
|
|
2621
|
+
phi0 = atan2(-w1 * w123, w3 * w13);
|
|
2622
|
+
}
|
|
2623
|
+
else {
|
|
2624
|
+
w = w2;
|
|
2625
|
+
incl = 0.;
|
|
2626
|
+
phi0 = 0.;
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
Cphi0 = cos(phi0);
|
|
2630
|
+
Sphi0 = sin(phi0);
|
|
2631
|
+
Cinc = cos(incl);
|
|
2632
|
+
Sinc = sin(incl);
|
|
2633
|
+
den0 = sqrt(Cphi0 * Cphi0 + Cinc * Cinc * Sphi0 * Sphi0);
|
|
2634
|
+
s_true = s / den0;
|
|
2635
|
+
COm = (Cphi0 * calpha + Cinc * salpha * Sphi0) / den0;
|
|
2636
|
+
SOm = (Cphi0 * salpha - Cinc * calpha * Sphi0) / den0;
|
|
2637
|
+
|
|
2638
|
+
ComputeParallax(t, t0, Et);
|
|
2639
|
+
|
|
2640
|
+
phil = (t - t0_par) * w + phi0;
|
|
2641
|
+
Cphi = cos(phil);
|
|
2642
|
+
Sphi = sin(phil);
|
|
2643
|
+
den = sqrt(Cphi * Cphi + Cinc * Cinc * Sphi * Sphi);
|
|
2644
|
+
av = s_true * den;
|
|
2645
|
+
u = u0 + pai1 * Et[1] - pai2 * Et[0];
|
|
2646
|
+
tn = (t-t0)*tE_inv + pai1 * Et[0] + pai2 * Et[1];
|
|
2647
|
+
|
|
2648
|
+
phit = omega * (t - t0_par);
|
|
2649
|
+
|
|
2650
|
+
disp[0] = sin(inc) * (-cos(phi) + cos(phi + phit) + phit * sin(phi));
|
|
2651
|
+
disp[1] = -phit * cos(phi) - sin(phi) + sin(phi + phit);
|
|
2652
|
+
disp2[0] = -sin(inc) * (cos(phi) + cos(phi + phit) / qs - phit * sin(phi));
|
|
2653
|
+
disp2[1] = phit * cos(phi) + sin(phi) + sin(phi + phit) / qs;
|
|
2654
|
+
|
|
2655
|
+
Xal[0] = xi1 * disp[0] + xi2 * disp[1];
|
|
2656
|
+
Xal[1] = xi2 * disp[0] - xi1 * disp[1];
|
|
2657
|
+
Xal2[0] = xi1 * disp2[0] - xi2 * disp2[1];
|
|
2658
|
+
Xal2[1] = xi2 * disp2[0] + xi1 * disp2[1];
|
|
2659
|
+
|
|
2660
|
+
tn1 = tn + Xal[0];
|
|
2661
|
+
u01 = u + Xal[1];
|
|
2662
|
+
tn2 = tn + Xal2[0];
|
|
2663
|
+
u02 = u + Xal2[1];
|
|
2664
|
+
rho2 = rho * pow(qs, mass_radius_exponent);
|
|
2665
|
+
qs4 = pow(qs, mass_luminosity_exponent);
|
|
2666
|
+
|
|
2667
|
+
|
|
2668
|
+
/* y1s = u01 * salpha - tn1 * calpha;
|
|
2669
|
+
y2s = -u01 * calpha - tn1 * salpha;
|
|
2670
|
+
y1s2 = u02 * salpha - tn2 * calpha;
|
|
2671
|
+
y2s2 = -u02 * calpha - tn2 * salpha;*/
|
|
2672
|
+
|
|
2673
|
+
y_1 = (Cphi * (u02 * SOm - tn2 * COm) + Cinc * Sphi * (u02 * COm + tn2 * SOm)) / den;
|
|
2674
|
+
y_2 = (-Cphi * (u02 * COm + tn2 * SOm) - Cinc * Sphi * (tn2 * COm - u02 * SOm)) / den;
|
|
2675
|
+
Mag2 = BinaryMag2(av, q, y_1, y_2, rho2);
|
|
2676
|
+
|
|
2677
|
+
y_1 = (Cphi * (u01 * SOm - tn1 * COm) + Cinc * Sphi * (u01 * COm + tn1 * SOm)) / den;
|
|
2678
|
+
y_2 = (-Cphi * (u01 * COm + tn1 * SOm) - Cinc * Sphi * (tn1 * COm - u01 * SOm)) / den;
|
|
2679
|
+
Mag = BinaryMag2(av, q, y_1, y_2, rho);
|
|
2680
|
+
|
|
2681
|
+
mags = (Mag + qs4 * Mag2) / (1 + qs4);
|
|
2682
|
+
|
|
2683
|
+
return mags;
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
///////////////////////////////////////////////
|
|
2687
|
+
///////////////////////////////////////////////
|
|
2688
|
+
////////// Internal private functions
|
|
2689
|
+
///////////////////////////////////////////////
|
|
2690
|
+
///////////////////////////////////////////////
|
|
2691
|
+
|
|
2692
|
+
#define _Jacobians1 \
|
|
2693
|
+
z=zr[i];\
|
|
2694
|
+
dza=z-coefs[20];\
|
|
2695
|
+
za2 = dza*dza;\
|
|
2696
|
+
zb2=z*z;\
|
|
2697
|
+
J1= coefs[21]/za2+coefs[22]/zb2;\
|
|
2698
|
+
J1c=conj(J1);\
|
|
2699
|
+
dJ=1-J1*J1c;\
|
|
2700
|
+
J2=-2.*(coefs[21]/(za2*dza)+coefs[22]/(zb2*z));
|
|
2701
|
+
|
|
2702
|
+
#define _Jacobians2\
|
|
2703
|
+
dy = complex(-sin(theta->th), cos(theta->th))*coefs[23];\
|
|
2704
|
+
dz = (dy - J1c*conj(dy)) / dJ.re;\
|
|
2705
|
+
Prov->last->x1 -= coefs[11].re;\
|
|
2706
|
+
Prov->last->dJ = dJ.re;\
|
|
2707
|
+
Prov->last->d = dz;\
|
|
2708
|
+
Prov->last->J2 = J2;\
|
|
2709
|
+
Prov->last->ds = (imag(dy*dz*dz*J2) + coefs[23].re*coefs[23].re) / dJ.re;
|
|
2710
|
+
|
|
2711
|
+
|
|
2712
|
+
#define _Jacobians3\
|
|
2713
|
+
Prov->last->dJ = dJ.re;\
|
|
2714
|
+
J3=6.*(coefs[21]/(za2*za2)+coefs[22]/(zb2*zb2));\
|
|
2715
|
+
dJ2=dJ.re*dJ.re;\
|
|
2716
|
+
za2=J1c*J1c;\
|
|
2717
|
+
J3=J3*za2;\
|
|
2718
|
+
ob2=(J2.re*J2.re+J2.im*J2.im)*(6-6*dJ.re+dJ2);\
|
|
2719
|
+
J2=J2*J2*za2*J1c;\
|
|
2720
|
+
cq= 0.5*(fabs(ob2-6.*J2.re-2.*J3.re*dJ.re)+3*fabs(J2.im))/fabs(dJ.re*dJ2*dJ2);
|
|
2721
|
+
|
|
2722
|
+
#define _Jacobians4\
|
|
2723
|
+
zaltc=yc+coefs[21]/dza+coefs[22]/z;\
|
|
2724
|
+
za2=(zaltc-coefs[20]);\
|
|
2725
|
+
Jaltc=coefs[21]/(za2*za2)+coefs[22]/(zaltc*zaltc);\
|
|
2726
|
+
Jalt = conj(Jaltc);\
|
|
2727
|
+
JJalt2=(1-J1c*Jalt);\
|
|
2728
|
+
J3=J2*J1c*JJalt2;\
|
|
2729
|
+
J3=(J3-conj(J3)*Jalt)/(JJalt2*JJalt2*dJ.re);\
|
|
2730
|
+
cq=(dJ.re<-100)? 0.0 : (J3.re*J3.re+J3.im*J3.im);
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
_curve* VBBinaryLensing::NewImages(complex yi, complex* coefs, _theta* theta) {
|
|
2734
|
+
static complex y, yc, z, zc, J1, J1c, dy, dz, dJ, J2, J3, dza, za2, zb2, zaltc, Jalt, Jaltc, JJalt2;
|
|
2735
|
+
static complex zr[5] = { 0.,0.,0.,0.,0. };
|
|
2736
|
+
static double dlmin = 1.0e-4, dlmax = 1.0e-3, good[5], dJ2, ob2, cq;
|
|
2737
|
+
static int worst1, worst2, worst3, bad, f1, checkJac;
|
|
2738
|
+
static double av = 0.0, m1v = 0.0, disim, disisso;
|
|
2739
|
+
static _curve* Prov;
|
|
2740
|
+
static _point* scan, * prin, * fifth, * left, * right, * center;
|
|
2741
|
+
|
|
2742
|
+
#ifdef _PRINT_TIMES
|
|
2743
|
+
static double tim0, tim1;
|
|
2744
|
+
#endif
|
|
2745
|
+
|
|
2746
|
+
y = yi + coefs[11];
|
|
2747
|
+
yc = conj(y);
|
|
2748
|
+
|
|
2749
|
+
// coefs[6]=a*a; coefs[7]=a*a*a; coefs[8]=m2*m2; coefs[9]=a*a*m2*m2; coefs[10]=a*m2; coefs[11]=a*m1; coefs[20]=a; coefs[21]=m1; coefs[22]=m2;
|
|
2750
|
+
|
|
2751
|
+
coefs[0] = coefs[9] * y;
|
|
2752
|
+
coefs[1] = coefs[10] * (coefs[20] * (coefs[21] + y * (2 * yc - coefs[20])) - 2 * y);
|
|
2753
|
+
coefs[2] = y * (1 - coefs[7] * yc) - coefs[20] * (coefs[21] + 2 * y * yc * (1 + coefs[22])) + coefs[6] * (yc * (coefs[21] - coefs[22]) + y * (1 + coefs[22] + yc * yc));
|
|
2754
|
+
coefs[3] = 2 * y * yc + coefs[7] * yc + coefs[6] * (yc * (2 * y - yc) - coefs[21]) - coefs[20] * (y + 2 * yc * (yc * y - coefs[22]));
|
|
2755
|
+
coefs[4] = yc * (2 * coefs[20] + y);
|
|
2756
|
+
coefs[4] = yc * (coefs[4] - 1) - coefs[20] * (coefs[4] - coefs[21]);
|
|
2757
|
+
coefs[5] = yc * (coefs[20] - yc);
|
|
2758
|
+
|
|
2759
|
+
bad = 1;
|
|
2760
|
+
disim = -1.;
|
|
2761
|
+
f1 = 0;
|
|
2762
|
+
|
|
2763
|
+
#ifdef _PRINT_TIMES
|
|
2764
|
+
tim0 = Environment::TickCount;
|
|
2765
|
+
#endif
|
|
2766
|
+
cmplx_roots_gen(zr, coefs, 5, true, true);
|
|
2767
|
+
|
|
2768
|
+
#ifdef _PRINT_TIMES
|
|
2769
|
+
tim1 = Environment::TickCount;
|
|
2770
|
+
inc += tim1 - tim0;
|
|
2771
|
+
#endif
|
|
2772
|
+
// apply lens equation to check if it is really solved
|
|
2773
|
+
for (int i = 0; i < 5; i++) {
|
|
2774
|
+
z = zr[i];
|
|
2775
|
+
zc = conj(z);
|
|
2776
|
+
good[i] = abs(_LL); // Lens equation check
|
|
2777
|
+
switch (i) {
|
|
2778
|
+
case 0:
|
|
2779
|
+
worst1 = i;
|
|
2780
|
+
break;
|
|
2781
|
+
case 1:
|
|
2782
|
+
if (good[i] > good[worst1]) {
|
|
2783
|
+
worst2 = worst1;
|
|
2784
|
+
worst1 = i;
|
|
2785
|
+
}
|
|
2786
|
+
else worst2 = i;
|
|
2787
|
+
break;
|
|
2788
|
+
case 2:
|
|
2789
|
+
if (good[i] > good[worst1]) {
|
|
2790
|
+
worst3 = worst2;
|
|
2791
|
+
worst2 = worst1;
|
|
2792
|
+
worst1 = i;
|
|
2793
|
+
}
|
|
2794
|
+
else if (good[i] > good[worst2]) {
|
|
2795
|
+
worst3 = worst2;
|
|
2796
|
+
worst2 = i;
|
|
2797
|
+
}
|
|
2798
|
+
else worst3 = i;
|
|
2799
|
+
break;
|
|
2800
|
+
default:
|
|
2801
|
+
if (good[i] > good[worst1]) {
|
|
2802
|
+
worst3 = worst2;
|
|
2803
|
+
worst2 = worst1;
|
|
2804
|
+
worst1 = i;
|
|
2805
|
+
}
|
|
2806
|
+
else if (good[i] > good[worst2]) {
|
|
2807
|
+
worst3 = worst2;
|
|
2808
|
+
worst2 = i;
|
|
2809
|
+
}
|
|
2810
|
+
else if (good[i] > good[worst3]) {
|
|
2811
|
+
worst3 = i;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
Prov = new _curve;
|
|
2816
|
+
checkJac = 0;
|
|
2817
|
+
// if (!((good[worst3] < dlmin) && ((good[worst1] < dlmin) || (good[worst2] > dlmax)))) { // old check for unacceptable roots
|
|
2818
|
+
|
|
2819
|
+
// 3 good roots
|
|
2820
|
+
if (good[worst2] * dlmin > good[worst3]+1.e-12 ) {
|
|
2821
|
+
for (int i = 0; i < 5; i++) {
|
|
2822
|
+
if ((i != worst1) && (i != worst2)) {
|
|
2823
|
+
//if((i==worst3)&&(good[i]>dlmax)&&(good[worst2]>1.e2*good[worst3])){
|
|
2824
|
+
// zr[i]=(coefs[21].re<coefs[22].re)? 0.5*coefs[20]+coefs[21]/(0.5*coefs[20]-yc-coefs[22]/coefs[20]) : -0.5*coefs[20]+coefs[22]/(-0.5*coefs[20]-yc+coefs[21]/coefs[20]);
|
|
2825
|
+
//}
|
|
2826
|
+
Prov->append(zr[i].re, zr[i].im);
|
|
2827
|
+
|
|
2828
|
+
_Jacobians1
|
|
2829
|
+
if (theta->th >= 0) {
|
|
2830
|
+
_Jacobians2
|
|
2831
|
+
}
|
|
2832
|
+
else {
|
|
2833
|
+
_Jacobians3
|
|
2834
|
+
corrquad += cq;
|
|
2835
|
+
}
|
|
2836
|
+
checkJac += (fabs(Prov->last->dJ) > 1.e-7) ? _sign(Prov->last->dJ) : 10;
|
|
2837
|
+
Prov->last->theta = theta;
|
|
2838
|
+
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
if (theta->th < 0) {
|
|
2842
|
+
dz = zr[worst2] - zr[worst1];
|
|
2843
|
+
|
|
2844
|
+
int i = worst1;
|
|
2845
|
+
_Jacobians1
|
|
2846
|
+
_Jacobians4
|
|
2847
|
+
corrquad2 = cq;
|
|
2848
|
+
|
|
2849
|
+
i = worst2;
|
|
2850
|
+
_Jacobians1
|
|
2851
|
+
_Jacobians4
|
|
2852
|
+
if (cq > corrquad2) corrquad2 = cq;
|
|
2853
|
+
//_Jacobians3
|
|
2854
|
+
//corrquad2 += 1/cq;
|
|
2855
|
+
|
|
2856
|
+
}
|
|
2857
|
+
else {
|
|
2858
|
+
theta->errworst = abs(zr[worst1] - zr[worst2]);
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
}
|
|
2862
|
+
else {
|
|
2863
|
+
if (good[worst2]*dlmax > good[worst3] + 1.e-12 && theta->th>=0) { // Dubious cases. Better exclude them
|
|
2864
|
+
return Prov;
|
|
2865
|
+
}
|
|
2866
|
+
else { // 5 good roots
|
|
2867
|
+
f1 = 0;
|
|
2868
|
+
for (int i = 0; i < 5; i++) {
|
|
2869
|
+
Prov->append(zr[i].re, zr[i].im);
|
|
2870
|
+
|
|
2871
|
+
_Jacobians1
|
|
2872
|
+
if (theta->th >= 0) {
|
|
2873
|
+
_Jacobians2
|
|
2874
|
+
}
|
|
2875
|
+
else {
|
|
2876
|
+
_Jacobians3
|
|
2877
|
+
corrquad += cq;
|
|
2878
|
+
}
|
|
2879
|
+
checkJac += (fabs(Prov->last->dJ) > 1.e-7) ? _sign(Prov->last->dJ) : 10;
|
|
2880
|
+
Prov->last->theta = theta;
|
|
2881
|
+
|
|
2882
|
+
if (fabs(dJ.re) < 1.e-5) f1 = 1;
|
|
2883
|
+
}
|
|
2884
|
+
theta->errworst = -1.e100;
|
|
2885
|
+
// check Jacobians in ambiguous cases
|
|
2886
|
+
if (f1) {
|
|
2887
|
+
left = right = center = fifth = 0;
|
|
2888
|
+
dJ.re = 0;
|
|
2889
|
+
for (scan = Prov->first; scan; scan = scan->next) {
|
|
2890
|
+
if (_sign(scan->x2) == _sign(y.im)) {
|
|
2891
|
+
prin = scan;
|
|
2892
|
+
}
|
|
2893
|
+
else {
|
|
2894
|
+
dz.re = fabs(scan->dJ);
|
|
2895
|
+
if (dz.re > dJ.re) {
|
|
2896
|
+
fifth = scan;
|
|
2897
|
+
dJ.re = dz.re;
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
for (scan = Prov->first; scan; scan = scan->next) {
|
|
2902
|
+
if ((scan != prin) && (scan != fifth)) {
|
|
2903
|
+
if (left) {
|
|
2904
|
+
if (scan->x1 < left->x1) {
|
|
2905
|
+
if (left != right) {
|
|
2906
|
+
center = left;
|
|
2907
|
+
}
|
|
2908
|
+
left = scan;
|
|
2909
|
+
}
|
|
2910
|
+
else {
|
|
2911
|
+
if (scan->x1 > right->x1) {
|
|
2912
|
+
if (left != right) {
|
|
2913
|
+
center = right;
|
|
2914
|
+
}
|
|
2915
|
+
right = scan;
|
|
2916
|
+
}
|
|
2917
|
+
else {
|
|
2918
|
+
center = scan;
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
else {
|
|
2923
|
+
left = right = center = scan;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
if (left->dJ > 0) left->dJ = -left->dJ;
|
|
2928
|
+
if (center->dJ < 0) center->dJ = -center->dJ;
|
|
2929
|
+
if (right->dJ > 0) right->dJ = -right->dJ;
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
if (checkJac != -1) {
|
|
2934
|
+
// printf("\ncheckJac!");
|
|
2935
|
+
if (theta->th < 0) {
|
|
2936
|
+
dJ = 0;
|
|
2937
|
+
for (scan = Prov->first; scan; scan = scan->next) {
|
|
2938
|
+
dJ = dJ+ 1 / fabs(scan->dJ);
|
|
2939
|
+
}
|
|
2940
|
+
if (fabs(dJ.re - 1) < Tol) {
|
|
2941
|
+
checkJac = -1;
|
|
2942
|
+
corrquad = 0;
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
if(checkJac!=-1){
|
|
2946
|
+
_point* scan2;
|
|
2947
|
+
for (scan = Prov->first; scan; scan = scan2) {
|
|
2948
|
+
scan2 = scan->next;
|
|
2949
|
+
Prov->drop(scan);
|
|
2950
|
+
delete scan;
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
return Prov;
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
void VBBinaryLensing::OrderImages(_sols *Sols, _curve *Newpts) {
|
|
2958
|
+
static double A[5][5];
|
|
2959
|
+
static _curve *cprec[5];
|
|
2960
|
+
static _curve *cpres[5];
|
|
2961
|
+
static _curve *cfoll[5];
|
|
2962
|
+
static _point *scan, *scan2, *scan3, *isso[2];
|
|
2963
|
+
static _curve *scurve, *scurve2;
|
|
2964
|
+
|
|
2965
|
+
_theta *theta;
|
|
2966
|
+
static double th, mi, cmp, cmp2,cmp_2,dx2,avgx2,avgx1,avg2x1,pref,d2x2,dx1,d2x1,avgwedgex1,avgwedgex2,parab1,parab2;
|
|
2967
|
+
|
|
2968
|
+
int nprec = 0, npres, nfoll = 0, issoc[2], ij;
|
|
2969
|
+
|
|
2970
|
+
theta = Newpts->first->theta;
|
|
2971
|
+
th = theta->th;
|
|
2972
|
+
theta->Mag = theta->prev->Mag = theta->maxerr = theta->prev->maxerr = 0;
|
|
2973
|
+
theta->astrox1 = theta->prev->astrox1 = theta->astrox2 = theta->prev->astrox2 = 0;
|
|
2974
|
+
if (Newpts->length == 3) {
|
|
2975
|
+
mi = theta->next->errworst - theta->errworst;
|
|
2976
|
+
if ((mi>theta->errworst) && (theta->prev->errworst>0.)) {
|
|
2977
|
+
theta->prev->maxerr = mi*mi;
|
|
2978
|
+
}
|
|
2979
|
+
mi = theta->prev->errworst - theta->errworst;
|
|
2980
|
+
if ((mi>theta->errworst) && (theta->next->errworst>0.)) {
|
|
2981
|
+
theta->maxerr = mi*mi;
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
// Per ciascuna immagine troviamo il punto in cui inserire i nuovi punti
|
|
2986
|
+
scurve = Sols->first;
|
|
2987
|
+
for (int i = 0; i<Sols->length; i++) {
|
|
2988
|
+
if (th<scurve->first->theta->th) {
|
|
2989
|
+
if (th>scurve->first->theta->prev->prev->th) {
|
|
2990
|
+
cfoll[nfoll] = scurve; // immagine coinvolta all'inizio
|
|
2991
|
+
nfoll++;
|
|
2992
|
+
scurve2 = scurve->next;
|
|
2993
|
+
Sols->drop(scurve);
|
|
2994
|
+
i--;
|
|
2995
|
+
scurve = scurve2;
|
|
2996
|
+
}
|
|
2997
|
+
else {
|
|
2998
|
+
scurve = scurve->next;
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
else {
|
|
3002
|
+
if (th>scurve->last->theta->th) {
|
|
3003
|
+
if (th<scurve->last->theta->next->next->th) {
|
|
3004
|
+
cprec[nprec] = scurve; // immagine coinvolta alla fine
|
|
3005
|
+
nprec++;
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
else {
|
|
3009
|
+
// immagine coinvolta al centro
|
|
3010
|
+
scan = scurve->last;
|
|
3011
|
+
while (scan->theta->th>th) {
|
|
3012
|
+
scan = scan->prev;
|
|
3013
|
+
}
|
|
3014
|
+
cfoll[nfoll] = scurve->divide(scan);
|
|
3015
|
+
nfoll++;
|
|
3016
|
+
cprec[nprec] = scurve;
|
|
3017
|
+
nprec++;
|
|
3018
|
+
}
|
|
3019
|
+
scurve = scurve->next;
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
npres = Newpts->length;
|
|
3023
|
+
|
|
3024
|
+
//if((theta->th>4.7116917419)&&(theta->th<4.711691759)){
|
|
3025
|
+
// theta->th=theta->th;
|
|
3026
|
+
//}
|
|
3027
|
+
//if((theta->prev->th>4.7116917419)&&(theta->prev->th<4.711691759)){
|
|
3028
|
+
// theta->th=theta->th;
|
|
3029
|
+
//}
|
|
3030
|
+
|
|
3031
|
+
|
|
3032
|
+
// Caso di creazione nuove immagini//
|
|
3033
|
+
|
|
3034
|
+
if (nprec<npres) {
|
|
3035
|
+
mi = 1.e100;
|
|
3036
|
+
scan = Newpts->first;
|
|
3037
|
+
for (int i = 0; i<Newpts->length - 1; i++) {
|
|
3038
|
+
scan2 = scan->next;
|
|
3039
|
+
for (int j = i + 1; j<Newpts->length; j++) {
|
|
3040
|
+
cmp = (*scan2) - (*scan);
|
|
3041
|
+
if (cmp<mi) {
|
|
3042
|
+
mi = cmp;
|
|
3043
|
+
isso[0] = scan;
|
|
3044
|
+
isso[1] = scan2;
|
|
3045
|
+
}
|
|
3046
|
+
scan2 = scan2->next;
|
|
3047
|
+
}
|
|
3048
|
+
scan = scan->next;
|
|
3049
|
+
}
|
|
3050
|
+
Newpts->drop(isso[0]);
|
|
3051
|
+
Newpts->drop(isso[1]);
|
|
3052
|
+
scurve = new _curve(isso[0]);
|
|
3053
|
+
isso[0]->prev = isso[0]->next = 0;
|
|
3054
|
+
scurve2 = new _curve(isso[1]);
|
|
3055
|
+
isso[1]->prev = isso[1]->next = 0;
|
|
3056
|
+
scurve->partneratstart = scurve2;
|
|
3057
|
+
scurve2->partneratstart = scurve;
|
|
3058
|
+
Sols->append(scurve);
|
|
3059
|
+
Sols->append(scurve2);
|
|
3060
|
+
cpres[3] = scurve;
|
|
3061
|
+
cpres[4] = scurve2;
|
|
3062
|
+
scan = isso[0];
|
|
3063
|
+
scan2 = isso[1];
|
|
3064
|
+
|
|
3065
|
+
cmp2 = fabs(scan->d.re*scan2->d.re + scan->d.im*scan2->d.im);
|
|
3066
|
+
cmp = sqrt(mi / cmp2); // Delta theta tilde
|
|
3067
|
+
|
|
3068
|
+
cmp_2 = cmp*cmp;
|
|
3069
|
+
mi = cmp_2*cmp*0.04166666667;
|
|
3070
|
+
parab1 = -(-scan->ds + scan2->ds)*mi;
|
|
3071
|
+
parab2=-0.0833333333 * ((scan2->x1 - scan->x1) * (scan2->d.im + scan->d.im) - (scan2->x2 - scan->x2) * (scan2->d.re + scan->d.re)) * cmp;
|
|
3072
|
+
scurve->parabstart = 0.5 * (parab1 + parab2);
|
|
3073
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////astro: created image:
|
|
3074
|
+
if(astrometry){
|
|
3075
|
+
avgwedgex1=-(-scan->x1*scan->ds + scan2->x1*scan2->ds)*mi;
|
|
3076
|
+
avgwedgex2=-(-scan->x2*scan->ds + scan2->x2*scan2->ds)*mi;
|
|
3077
|
+
dx2=-(-scan->d.im+scan2->d.im);
|
|
3078
|
+
d2x2=dx2*dx2;
|
|
3079
|
+
dx1=-(-scan->d.re+scan2->d.re);
|
|
3080
|
+
d2x1=dx1*dx1;
|
|
3081
|
+
scurve->parabastrox1 =-0.125*d2x1*dx2*mi-avgwedgex1;
|
|
3082
|
+
scurve->parabastrox2 =-0.125*d2x2*dx1*mi+avgwedgex2;
|
|
3083
|
+
}
|
|
3084
|
+
#ifdef _PRINT_ERRORS
|
|
3085
|
+
printf("\n%le %le %le %le %le %le %le %le", scan->x1, scan->x2, scan->dJ, (scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2, scurve->parabstart, (scan->ds + scan2->ds)*mi / 2, fabs(scurve->parabstart)*(cmp*cmp) / 10, 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) - 2 * cmp*cmp2)*cmp);
|
|
3086
|
+
#endif
|
|
3087
|
+
|
|
3088
|
+
mi = fabs((parab1-parab2)*0.5) + fabs(scurve->parabstart)*(cmp_2 *0.1) + 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) - 2 * cmp*cmp2)*cmp;
|
|
3089
|
+
#ifdef _noparab
|
|
3090
|
+
mi = fabs(scurve->parabstart) * 2 + 0 * fabs((scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2 * cmp*cmp / 6);
|
|
3091
|
+
scurve->parabstart = 0.;
|
|
3092
|
+
#endif
|
|
3093
|
+
|
|
3094
|
+
#ifdef _selectimage
|
|
3095
|
+
if (_selectionimage)
|
|
3096
|
+
#endif
|
|
3097
|
+
pref=(scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) *0.5;
|
|
3098
|
+
theta->prev->Mag -= ((scan->dJ>0) ? -1 : 1)*(pref + scurve->parabstart);
|
|
3099
|
+
theta->prev->maxerr += mi;
|
|
3100
|
+
|
|
3101
|
+
#ifdef _ERRORS_ANALYTIC
|
|
3102
|
+
char filnam[32];
|
|
3103
|
+
sprintf(filnam, "%02dprev.txt", NPS);
|
|
3104
|
+
FILE* f = fopen(filnam, "a+");
|
|
3105
|
+
fprintf(f, "%.15le %.15le %.15le\n", -((scan->dJ > 0) ? -1 : 1)* (pref), -((scan->dJ > 0) ? -1 : 1)* (scurve->parabstart), mi);
|
|
3106
|
+
fclose(f);
|
|
3107
|
+
#endif
|
|
3108
|
+
scurve2->parabstart = -scurve->parabstart;
|
|
3109
|
+
|
|
3110
|
+
if(astrometry){
|
|
3111
|
+
dx2=scan2->x2 - scan->x2;
|
|
3112
|
+
avgx1=scan->x1 + scan2->x1;
|
|
3113
|
+
avg2x1=avgx1*avgx1;
|
|
3114
|
+
avgx2=scan->x2 + scan2->x2;
|
|
3115
|
+
theta->prev->astrox1 += ((scan->dJ>0) ? -1 : 1)*(avg2x1*dx2*0.125+scurve->parabastrox1);
|
|
3116
|
+
theta->prev->astrox2 -= ((scan->dJ>0) ? -1 : 1)*(pref*avgx2*0.25+scurve->parabastrox2);
|
|
3117
|
+
scurve2->parabastrox2=-scurve->parabastrox2;
|
|
3118
|
+
scurve2->parabastrox1=-scurve->parabastrox1;
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
|
|
3122
|
+
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
// Caso di distruzione immagini//
|
|
3126
|
+
if (nprec>npres) {
|
|
3127
|
+
mi = 1.e100;
|
|
3128
|
+
for (int i = 0; i<nprec - 1; i++) {
|
|
3129
|
+
for (int j = i + 1; j<nprec; j++) {
|
|
3130
|
+
cmp = *(cprec[i]->last) - *(cprec[j]->last);
|
|
3131
|
+
if (cmp<mi) {
|
|
3132
|
+
mi = cmp;
|
|
3133
|
+
issoc[0] = i;
|
|
3134
|
+
issoc[1] = j;
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
cprec[issoc[0]]->partneratend = cprec[issoc[1]];
|
|
3139
|
+
cprec[issoc[1]]->partneratend = cprec[issoc[0]];
|
|
3140
|
+
|
|
3141
|
+
scan = cprec[issoc[0]]->last;
|
|
3142
|
+
scan2 = cprec[issoc[1]]->last;
|
|
3143
|
+
|
|
3144
|
+
cmp2 = fabs(scan->d.re*scan2->d.re + scan->d.im*scan2->d.im);
|
|
3145
|
+
cmp = sqrt(mi / cmp2);
|
|
3146
|
+
cmp_2 = cmp*cmp;
|
|
3147
|
+
mi = cmp_2*cmp *0.04166666666667;
|
|
3148
|
+
parab1 = -(scan->ds - scan2->ds)*mi;
|
|
3149
|
+
parab2 = 0.0833333333 * ((scan2->x1 - scan->x1) * (scan2->d.im + scan->d.im) - (scan2->x2 - scan->x2) * (scan2->d.re + scan->d.re)) * cmp;
|
|
3150
|
+
scan->parab = 0.5 * (parab1 + parab2);
|
|
3151
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////astro: destructed image:
|
|
3152
|
+
if(astrometry){
|
|
3153
|
+
avgwedgex1=-(scan->x1*scan->ds - scan2->x1*scan2->ds)*mi;
|
|
3154
|
+
avgwedgex2=-(scan->x2*scan->ds - scan2->x2*scan2->ds)*mi;
|
|
3155
|
+
dx2=-(scan->d.im-scan2->d.im);
|
|
3156
|
+
d2x2=dx2*dx2;
|
|
3157
|
+
dx1=-(scan->d.re-scan2->d.re);
|
|
3158
|
+
d2x1=dx1*dx1;
|
|
3159
|
+
scan->parabastrox1 =-0.125*d2x1*dx2*mi-avgwedgex1;
|
|
3160
|
+
scan->parabastrox2 =-0.125*d2x2*dx1*mi+avgwedgex2;
|
|
3161
|
+
|
|
3162
|
+
}
|
|
3163
|
+
#ifdef _PRINT_ERRORS
|
|
3164
|
+
printf("\n%le %le %le %le %le %le %le %le", scan->x1, scan->x2, scan->dJ, (scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2, scan->parab, (scan->ds + scan2->ds)*mi / 2, fabs(scan->parab)*(cmp*cmp) / 10, 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) + 2 * cmp*cmp2)*cmp);
|
|
3165
|
+
#endif
|
|
3166
|
+
|
|
3167
|
+
mi = fabs((parab1-parab2)*0.5) + fabs(scan->parab)*(cmp*cmp *0.1) + 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) + 2.0 * cmp*cmp2)*cmp;
|
|
3168
|
+
#ifdef _noparab
|
|
3169
|
+
mi = fabs(scan->parab) * 2 + 0 * fabs((scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2 * cmp*cmp / 6);
|
|
3170
|
+
scan->parab = 0.;
|
|
3171
|
+
#endif
|
|
3172
|
+
#ifdef _selectimage
|
|
3173
|
+
if (_selectionimage)
|
|
3174
|
+
#endif
|
|
3175
|
+
pref=(scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) *0.5;
|
|
3176
|
+
theta->prev->Mag += ((scan->dJ>0) ? -1 : 1)*(pref+ scan->parab);
|
|
3177
|
+
#ifdef _ERRORS_ANALYTIC
|
|
3178
|
+
char filnam[32];
|
|
3179
|
+
sprintf(filnam, "%02dprev.txt", NPS);
|
|
3180
|
+
FILE* f = fopen(filnam, "a+");
|
|
3181
|
+
fprintf(f, "%.15le %.15le %.15le\n", ((scan->dJ > 0) ? -1 : 1)* (pref), ((scan->dJ > 0) ? -1 : 1)* (scan->parab), mi);
|
|
3182
|
+
fclose(f);
|
|
3183
|
+
#endif
|
|
3184
|
+
if(astrometry){
|
|
3185
|
+
dx2=scan2->x2 - scan->x2;
|
|
3186
|
+
avgx1=scan->x1 + scan2->x1;
|
|
3187
|
+
avg2x1=avgx1*avgx1;
|
|
3188
|
+
avgx2=scan->x2 + scan2->x2;
|
|
3189
|
+
theta->prev->astrox1 -= ((scan->dJ>0) ? -1 : 1)*(avg2x1*dx2*0.125+scan->parabastrox1);
|
|
3190
|
+
theta->prev->astrox2 += ((scan->dJ>0) ? -1 : 1)*(pref*avgx2*0.25+scan->parabastrox2);
|
|
3191
|
+
}
|
|
3192
|
+
theta->prev->maxerr += mi;
|
|
3193
|
+
scan2->parab = -scan->parab;
|
|
3194
|
+
if(astrometry){
|
|
3195
|
+
scan2->parabastrox2 =-scan->parabastrox2;
|
|
3196
|
+
scan2->parabastrox1 =-scan->parabastrox1;
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3199
|
+
|
|
3200
|
+
nprec -= 2;
|
|
3201
|
+
ij = 0;
|
|
3202
|
+
for (int i = 0; i<nprec; i++) {
|
|
3203
|
+
if (i == issoc[0]) ij++;
|
|
3204
|
+
if (i == issoc[1] - 1) ij++;
|
|
3205
|
+
cprec[i] = cprec[i + ij];
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
// Costruzione matrice distanze con immagini precedenti//
|
|
3210
|
+
mi = 1.e100;
|
|
3211
|
+
for (int i = 0; i<nprec; i++) {
|
|
3212
|
+
cpres[i] = cprec[i];
|
|
3213
|
+
scan = Newpts->first;
|
|
3214
|
+
for (int j = 0; j<nprec; j++) {
|
|
3215
|
+
A[i][j] = (signbit(cprec[i]->last->dJ) == signbit(scan->dJ))? *(cprec[i]->last) - *scan : 100;
|
|
3216
|
+
if (A[i][j]<mi) {
|
|
3217
|
+
mi = A[i][j];
|
|
3218
|
+
issoc[0] = i;
|
|
3219
|
+
issoc[1] = j;
|
|
3220
|
+
isso[1] = scan;
|
|
3221
|
+
}
|
|
3222
|
+
scan = scan->next;
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
// Associazione con le immagini che precedono//
|
|
3227
|
+
while (nprec) {
|
|
3228
|
+
scan = cprec[issoc[0]]->last;
|
|
3229
|
+
scan2 = isso[1];
|
|
3230
|
+
|
|
3231
|
+
cmp2 = mi / fabs(scan->d.re*scan2->d.re + scan->d.im*scan2->d.im);
|
|
3232
|
+
cmp = (scan->theta->th - scan2->theta->th);
|
|
3233
|
+
cmp_2 = cmp*cmp;
|
|
3234
|
+
mi = cmp_2*cmp *0.0416666666666667; ////// (1/24 cube(delta Teta))
|
|
3235
|
+
parab1 = (scan->ds + scan2->ds)*mi; // Vecchia Correzione parabolica
|
|
3236
|
+
// Nuova correzione parabolica
|
|
3237
|
+
parab2 = 0.0833333333 * ((scan2->x1 - scan->x1) * (scan2->d.im - scan->d.im) - (scan2->x2 - scan->x2) * (scan2->d.re - scan->d.re)) * cmp;
|
|
3238
|
+
scan->parab = 0.5*(parab1+parab2);
|
|
3239
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////astro: ordinary image:
|
|
3240
|
+
if(astrometry){
|
|
3241
|
+
avgwedgex1=(scan->x1*scan->ds + scan2->x1*scan2->ds)*mi;
|
|
3242
|
+
avgwedgex2=(scan->x2*scan->ds + scan2->x2*scan2->ds)*mi;
|
|
3243
|
+
dx2=scan->d.im+scan2->d.im;
|
|
3244
|
+
d2x2=dx2*dx2;
|
|
3245
|
+
dx1=scan->d.re+scan2->d.re;
|
|
3246
|
+
d2x1=dx1*dx1;
|
|
3247
|
+
scan->parabastrox1 =-0.125*d2x1*dx2*mi-avgwedgex1;
|
|
3248
|
+
scan->parabastrox2 =-0.125*d2x2*dx1*mi+avgwedgex2;
|
|
3249
|
+
}
|
|
3250
|
+
#ifdef _PRINT_ERRORS
|
|
3251
|
+
printf("\n%le %le %le %le %le %le %le %le", scan->x1, scan->x2, scan->dJ, (scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2, scan->parab, (scan->ds - scan2->ds)*mi / 2, fabs(scan->parab)*(cmp2) / 10, fabs(scan->parab)*(1.5*fabs(cmp2 / (cmp*cmp) - 1)));
|
|
3252
|
+
#endif
|
|
3253
|
+
|
|
3254
|
+
mi = fabs((parab1 - parab2) *0.5) + fabs(scan->parab*(cmp2 *0.1 + 1.5*fabs(cmp2 / (cmp_2) - 1)));
|
|
3255
|
+
#ifdef _noparab
|
|
3256
|
+
mi = fabs(scan->parab) * 2 + 0 * fabs((scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2 * cmp*cmp / 6);
|
|
3257
|
+
scan->parab = 0.;
|
|
3258
|
+
#endif
|
|
3259
|
+
#ifdef _selectimage
|
|
3260
|
+
if (_selectionimage)
|
|
3261
|
+
#endif
|
|
3262
|
+
pref=(scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) *0.5;
|
|
3263
|
+
theta->prev->Mag += ((scan->dJ>0) ? -1 : 1)*( pref+ scan->parab);
|
|
3264
|
+
#ifdef _ERRORS_ANALYTIC
|
|
3265
|
+
char filnam[32];
|
|
3266
|
+
sprintf(filnam, "%02dprev.txt", NPS);
|
|
3267
|
+
FILE* f = fopen(filnam, "a+");
|
|
3268
|
+
fprintf(f, "%.15le %.15le %.15le\n", ((scan->dJ > 0) ? -1 : 1)* (pref), ((scan->dJ > 0) ? -1 : 1)* (scan->parab),mi);
|
|
3269
|
+
fclose(f);
|
|
3270
|
+
#endif
|
|
3271
|
+
if(astrometry){
|
|
3272
|
+
dx2=scan2->x2 - scan->x2;
|
|
3273
|
+
avgx1=scan->x1 + scan2->x1;
|
|
3274
|
+
avg2x1=avgx1*avgx1;
|
|
3275
|
+
avgx2=scan->x2 + scan2->x2;
|
|
3276
|
+
theta->prev->astrox1 -= ((scan->dJ>0) ? -1 : 1)*(avg2x1*dx2*0.125+scan->parabastrox1);
|
|
3277
|
+
theta->prev->astrox2 += ((scan->dJ>0) ? -1 : 1)*(pref*avgx2*0.25+scan->parabastrox2);
|
|
3278
|
+
}
|
|
3279
|
+
theta->prev->maxerr += mi;
|
|
3280
|
+
|
|
3281
|
+
|
|
3282
|
+
|
|
3283
|
+
Newpts->drop(isso[1]);
|
|
3284
|
+
cprec[issoc[0]]->append(isso[1]);
|
|
3285
|
+
cprec[issoc[0]]->partneratend = 0;
|
|
3286
|
+
|
|
3287
|
+
nprec--;
|
|
3288
|
+
for (int i = issoc[0]; i<nprec; i++) {
|
|
3289
|
+
cprec[i] = cprec[i + 1];
|
|
3290
|
+
for (int j = 0; j<nprec + 1; j++) {
|
|
3291
|
+
A[i][j] = A[i + 1][j];
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
for (int j = issoc[1]; j<nprec; j++) {
|
|
3295
|
+
for (int i = 0; i<nprec; i++) {
|
|
3296
|
+
A[i][j] = A[i][j + 1];
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
mi = 1.e100;
|
|
3300
|
+
for (int i = 0; i<nprec; i++) {
|
|
3301
|
+
scan = Newpts->first;
|
|
3302
|
+
for (int j = 0; j<nprec; j++) {
|
|
3303
|
+
if (A[i][j]<mi) {
|
|
3304
|
+
mi = A[i][j];
|
|
3305
|
+
issoc[0] = i;
|
|
3306
|
+
issoc[1] = j;
|
|
3307
|
+
isso[1] = scan;
|
|
3308
|
+
}
|
|
3309
|
+
scan = scan->next;
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
delete Newpts;
|
|
3314
|
+
|
|
3315
|
+
#ifdef _PRINT_ERRORS
|
|
3316
|
+
printf("\nN");
|
|
3317
|
+
#endif
|
|
3318
|
+
|
|
3319
|
+
// immagini seguenti//
|
|
3320
|
+
if (nfoll) {
|
|
3321
|
+
// Caso di creazione nuove immagini
|
|
3322
|
+
|
|
3323
|
+
if (npres<nfoll) {
|
|
3324
|
+
mi = 1.e100;
|
|
3325
|
+
for (int i = 0; i<nfoll - 1; i++) {
|
|
3326
|
+
for (int j = i + 1; j<nfoll; j++) {
|
|
3327
|
+
cmp = *(cfoll[i]->first) - *(cfoll[j]->first);
|
|
3328
|
+
if (cmp<mi) {
|
|
3329
|
+
mi = cmp;
|
|
3330
|
+
issoc[0] = i;
|
|
3331
|
+
issoc[1] = j;
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
cfoll[issoc[0]]->partneratstart = cfoll[issoc[1]];
|
|
3336
|
+
cfoll[issoc[1]]->partneratstart = cfoll[issoc[0]];
|
|
3337
|
+
|
|
3338
|
+
scan = cfoll[issoc[0]]->first;
|
|
3339
|
+
scan2 = cfoll[issoc[1]]->first;
|
|
3340
|
+
|
|
3341
|
+
cmp2 = fabs(scan->d.re*scan2->d.re + scan->d.im*scan2->d.im);
|
|
3342
|
+
cmp = sqrt(mi / cmp2);
|
|
3343
|
+
cmp_2 = cmp*cmp;
|
|
3344
|
+
mi = cmp_2*cmp *0.04166666666666667;
|
|
3345
|
+
parab1 = (scan->ds - scan2->ds)*mi;
|
|
3346
|
+
parab2 = -0.0833333333 * ((scan2->x1 - scan->x1) * (scan2->d.im + scan->d.im) - (scan2->x2 - scan->x2) * (scan2->d.re + scan->d.re)) * cmp;
|
|
3347
|
+
cfoll[issoc[0]]->parabstart = 0.5 * (parab1 + parab2);
|
|
3348
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////astro: created image:
|
|
3349
|
+
if(astrometry){
|
|
3350
|
+
avgwedgex1=(scan->x1*scan->ds - scan2->x1*scan2->ds)*mi;
|
|
3351
|
+
avgwedgex2=(scan->x2*scan->ds - scan2->x2*scan2->ds)*mi;
|
|
3352
|
+
dx2=-(-scan->d.im+scan2->d.im);
|
|
3353
|
+
d2x2=dx2*dx2;
|
|
3354
|
+
dx1=-(-scan->d.re+scan2->d.re);
|
|
3355
|
+
d2x1=dx1*dx1;
|
|
3356
|
+
cfoll[issoc[0]]->parabastrox1 =-0.125*d2x1*dx2*mi-avgwedgex1;
|
|
3357
|
+
cfoll[issoc[0]]->parabastrox2 =-0.125*d2x2*dx1*mi+avgwedgex2;
|
|
3358
|
+
}
|
|
3359
|
+
#ifdef _PRINT_ERRORS
|
|
3360
|
+
printf("\n%le %le %le %le %le %le %le %le", scan->x1, scan->x2, scan->dJ, (scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2, cfoll[issoc[0]]->parabstart, (scan->ds + scan2->ds)*mi / 2, fabs(cfoll[issoc[0]]->parabstart)*(cmp*cmp) / 10, 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) - 2 * cmp*cmp2)*cmp);
|
|
3361
|
+
#endif
|
|
3362
|
+
mi = fabs((parab1-parab2) *0.5) + fabs(cfoll[issoc[0]]->parabstart)*(cmp*cmp *0.1) + 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) - 2.0 * cmp*cmp2)*cmp;
|
|
3363
|
+
#ifdef _noparab
|
|
3364
|
+
mi = fabs(cfoll[issoc[0]]->parabstart) * 2 + 0 * fabs((scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2 * cmp*cmp / 6);
|
|
3365
|
+
cfoll[issoc[0]]->parabstart = 0.;
|
|
3366
|
+
#endif
|
|
3367
|
+
#ifdef _selectimage
|
|
3368
|
+
if (_selectionimage)
|
|
3369
|
+
#endif
|
|
3370
|
+
pref=(scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) *0.5;
|
|
3371
|
+
theta->Mag -= ((scan->dJ>0) ? -1 : 1)*(pref + cfoll[issoc[0]]->parabstart);
|
|
3372
|
+
#ifdef _ERRORS_ANALYTIC
|
|
3373
|
+
char filnam[32];
|
|
3374
|
+
sprintf(filnam, "%02dfoll.txt", NPS);
|
|
3375
|
+
FILE* f = fopen(filnam, "a+");
|
|
3376
|
+
fprintf(f, "%.15le %.15le %.15le\n", -((scan->dJ > 0) ? -1 : 1)* (pref), -((scan->dJ > 0) ? -1 : 1)* (cfoll[issoc[0]]->parabstart), mi);
|
|
3377
|
+
fclose(f);
|
|
3378
|
+
#endif
|
|
3379
|
+
if(astrometry){
|
|
3380
|
+
dx2=scan2->x2 - scan->x2;
|
|
3381
|
+
avgx1=scan->x1 + scan2->x1;
|
|
3382
|
+
avg2x1=avgx1*avgx1;
|
|
3383
|
+
avgx2=scan->x2 + scan2->x2;
|
|
3384
|
+
theta->astrox1 += ((scan->dJ>0) ? -1 : 1)*(avg2x1*dx2*0.125+cfoll[issoc[0]]->parabastrox1);
|
|
3385
|
+
theta->astrox2 -= ((scan->dJ>0) ? -1 : 1)*(pref*avgx2*0.25+cfoll[issoc[0]]->parabastrox2);
|
|
3386
|
+
}
|
|
3387
|
+
theta->maxerr += mi;
|
|
3388
|
+
|
|
3389
|
+
cfoll[issoc[1]]->parabstart = -cfoll[issoc[0]]->parabstart;
|
|
3390
|
+
if(astrometry){
|
|
3391
|
+
cfoll[issoc[1]]->parabastrox2=-cfoll[issoc[0]]->parabastrox2;
|
|
3392
|
+
cfoll[issoc[1]]->parabastrox1=-cfoll[issoc[0]]->parabastrox1;
|
|
3393
|
+
}
|
|
3394
|
+
Sols->append(cfoll[issoc[0]]);
|
|
3395
|
+
Sols->append(cfoll[issoc[1]]);
|
|
3396
|
+
nfoll -= 2;
|
|
3397
|
+
ij = 0;
|
|
3398
|
+
for (int i = 0; i<nfoll; i++) {
|
|
3399
|
+
if (i == issoc[0]) ij++;
|
|
3400
|
+
if (i == issoc[1] - 1) ij++;
|
|
3401
|
+
cfoll[i] = cfoll[i + ij];
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
|
|
3406
|
+
// Caso di distruzione immagini
|
|
3407
|
+
if (npres>nfoll) {
|
|
3408
|
+
mi = 1.e100;
|
|
3409
|
+
for (int i = 0; i<npres - 1; i++) {
|
|
3410
|
+
for (int j = i + 1; j<npres; j++) {
|
|
3411
|
+
cmp = *(cpres[i]->last) - *(cpres[j]->last);
|
|
3412
|
+
if (cmp<mi) {
|
|
3413
|
+
mi = cmp;
|
|
3414
|
+
issoc[0] = i;
|
|
3415
|
+
issoc[1] = j;
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
cpres[issoc[0]]->partneratend = cpres[issoc[1]];
|
|
3420
|
+
cpres[issoc[1]]->partneratend = cpres[issoc[0]];
|
|
3421
|
+
|
|
3422
|
+
scan = cpres[issoc[0]]->last;
|
|
3423
|
+
scan2 = cpres[issoc[1]]->last;
|
|
3424
|
+
|
|
3425
|
+
cmp2 = fabs(scan->d.re*scan2->d.re + scan->d.im*scan2->d.im);
|
|
3426
|
+
cmp = sqrt(mi / cmp2);
|
|
3427
|
+
cmp_2 = cmp*cmp;
|
|
3428
|
+
mi = cmp_2*cmp *0.0416666666667;
|
|
3429
|
+
parab1 = -(scan->ds - scan2->ds)*mi;
|
|
3430
|
+
parab2 = 0.0833333333 * ((scan2->x1 - scan->x1) * (scan2->d.im + scan->d.im) - (scan2->x2 - scan->x2) * (scan2->d.re + scan->d.re)) * cmp;
|
|
3431
|
+
scan->parab = 0.5 * (parab1 + parab2);
|
|
3432
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////astro: destructed image:
|
|
3433
|
+
if(astrometry){
|
|
3434
|
+
avgwedgex1=-(scan->x1*scan->ds - scan2->x1*scan2->ds)*mi;
|
|
3435
|
+
avgwedgex2=-(scan->x2*scan->ds - scan2->x2*scan2->ds)*mi;
|
|
3436
|
+
dx2=-(scan->d.im-scan2->d.im);
|
|
3437
|
+
d2x2=dx2*dx2;
|
|
3438
|
+
dx1=-(scan->d.re-scan2->d.re);
|
|
3439
|
+
d2x1=dx1*dx1;
|
|
3440
|
+
scan->parabastrox1 =-0.125*d2x1*dx2*mi-avgwedgex1;
|
|
3441
|
+
scan->parabastrox2 =-0.125*d2x2*dx1*mi+avgwedgex2;
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
#ifdef _PRINT_ERRORS
|
|
3445
|
+
printf("\n%le %le %le %le %le %le %le %le", scan->x1, scan->x2, scan->dJ, (scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2, scan->parab, (scan->ds + scan2->ds)*mi / 2, fabs(scan->parab)*(cmp*cmp) / 10, 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) + 2 * cmp*cmp2)*cmp);
|
|
3446
|
+
#endif
|
|
3447
|
+
|
|
3448
|
+
mi = fabs((parab1-parab2) *0.5) + fabs(scan->parab)*(cmp*cmp *0.1) + 1.5*fabs(((scan->d.re - scan2->d.re)*(scan->x1 - scan2->x1) + (scan->d.im - scan2->d.im)*(scan->x2 - scan2->x2)) + 2.0 * cmp*cmp2)*cmp;
|
|
3449
|
+
#ifdef _noparab
|
|
3450
|
+
mi = fabs(scan->parab) * 2 + 0 * fabs((scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2 * cmp*cmp / 6);
|
|
3451
|
+
scan->parab = 0.;
|
|
3452
|
+
#endif
|
|
3453
|
+
#ifdef _selectimage
|
|
3454
|
+
if (_selectionimage)
|
|
3455
|
+
#endif
|
|
3456
|
+
pref=(scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) *0.5;
|
|
3457
|
+
theta->Mag += ((scan->dJ>0) ? -1 : 1)*( pref + scan->parab);
|
|
3458
|
+
#ifdef _ERRORS_ANALYTIC
|
|
3459
|
+
char filnam[32];
|
|
3460
|
+
sprintf(filnam, "%02dfoll.txt", NPS);
|
|
3461
|
+
FILE* f = fopen(filnam, "a+");
|
|
3462
|
+
fprintf(f, "%.15le %.15le %.15le\n", ((scan->dJ > 0) ? -1 : 1)* (pref), ((scan->dJ > 0) ? -1 : 1)* (scan->parab), mi);
|
|
3463
|
+
fclose(f);
|
|
3464
|
+
#endif
|
|
3465
|
+
if(astrometry){
|
|
3466
|
+
dx2=scan2->x2 - scan->x2;
|
|
3467
|
+
avgx1=scan->x1 + scan2->x1;
|
|
3468
|
+
avg2x1=avgx1*avgx1;
|
|
3469
|
+
avgx2=scan->x2 + scan2->x2;
|
|
3470
|
+
theta->astrox1 -= ((scan->dJ>0) ? -1 : 1)*(avg2x1*dx2*0.125+scan->parabastrox1);
|
|
3471
|
+
theta->astrox2 += ((scan->dJ>0) ? -1 : 1)*(pref*avgx2*0.25+scan->parabastrox2);
|
|
3472
|
+
}
|
|
3473
|
+
theta->maxerr += mi;
|
|
3474
|
+
scan2->parab = -scan->parab;
|
|
3475
|
+
if(astrometry){
|
|
3476
|
+
scan2->parabastrox2=-scan->parabastrox2;
|
|
3477
|
+
scan2->parabastrox1=-scan->parabastrox1;
|
|
3478
|
+
}
|
|
3479
|
+
npres -= 2;
|
|
3480
|
+
ij = 0;
|
|
3481
|
+
for (int i = 0; i<npres; i++) {
|
|
3482
|
+
if (i == issoc[0]) ij++;
|
|
3483
|
+
if (i == issoc[1] - 1) ij++;
|
|
3484
|
+
cpres[i] = cpres[i + ij];
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
// Costruzione matrice distanze con immagini seguenti
|
|
3489
|
+
|
|
3490
|
+
mi = 1.e100;
|
|
3491
|
+
for (int i = 0; i<npres; i++) {
|
|
3492
|
+
for (int j = 0; j<npres; j++) {
|
|
3493
|
+
A[i][j] = signbit(cpres[i]->last->dJ) == signbit(cfoll[j]->first->dJ)? *(cpres[i]->last) - *(cfoll[j]->first) : 100;
|
|
3494
|
+
if (A[i][j]<mi) {
|
|
3495
|
+
mi = A[i][j];
|
|
3496
|
+
issoc[0] = i;
|
|
3497
|
+
issoc[1] = j;
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
|
|
3502
|
+
|
|
3503
|
+
// Associazione con le immagini che seguono//
|
|
3504
|
+
while (npres) {
|
|
3505
|
+
scan = cpres[issoc[0]]->last;
|
|
3506
|
+
scan2 = cfoll[issoc[1]]->first;
|
|
3507
|
+
cmp2 = mi / fabs(scan->d.re*scan2->d.re + scan->d.im*scan2->d.im);
|
|
3508
|
+
cmp = (scan->theta->th - scan2->theta->th);
|
|
3509
|
+
cmp_2 = cmp*cmp;
|
|
3510
|
+
mi = cmp_2*cmp *0.041666666667;
|
|
3511
|
+
parab1 = (scan->ds + scan2->ds)*mi; // Vecchia Correzione parabolica
|
|
3512
|
+
// Nuova correzione parabolica
|
|
3513
|
+
parab2 = 0.0833333333 * ((scan2->x1 - scan->x1) * (scan2->d.im - scan->d.im) - (scan2->x2 - scan->x2) * (scan2->d.re - scan->d.re)) * cmp;
|
|
3514
|
+
scan->parab = 0.5*(parab1+parab2);
|
|
3515
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////astro: ordinary image:
|
|
3516
|
+
if(astrometry){
|
|
3517
|
+
avgwedgex1=(scan->x1*scan->ds + scan2->x1*scan2->ds)*mi;
|
|
3518
|
+
avgwedgex2=(scan->x2*scan->ds + scan2->x2*scan2->ds)*mi;
|
|
3519
|
+
dx2=scan->d.im+scan2->d.im;
|
|
3520
|
+
d2x2=dx2*dx2;
|
|
3521
|
+
dx1=scan->d.re+scan2->d.re;
|
|
3522
|
+
d2x1=dx1*dx1;
|
|
3523
|
+
scan->parabastrox1 =-0.125*d2x1*dx2*mi-avgwedgex1;
|
|
3524
|
+
scan->parabastrox2 =-0.125*d2x2*dx1*mi+avgwedgex2;
|
|
3525
|
+
}
|
|
3526
|
+
|
|
3527
|
+
#ifdef _PRINT_ERRORS
|
|
3528
|
+
printf("\n%le %le %le %le %le %le %le %le", scan->x1, scan->x2, scan->dJ, (scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2, scan->parab, (scan->ds - scan2->ds)*mi / 2, fabs(scan->parab)*(cmp2) / 10, fabs(scan->parab)*(1.5*fabs(cmp2 / (cmp*cmp) - 1)));
|
|
3529
|
+
#endif
|
|
3530
|
+
|
|
3531
|
+
mi = fabs((parab1-parab2) *0.5) + fabs(scan->parab*(cmp2 *0.1 + 1.5*fabs(cmp2 / (cmp_2) - 1)));
|
|
3532
|
+
#ifdef _noparab
|
|
3533
|
+
mi = fabs(scan->parab) * 2 + 0 * fabs((scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) / 2 * cmp*cmp / 6);
|
|
3534
|
+
scan->parab = 0.;
|
|
3535
|
+
#endif
|
|
3536
|
+
#ifdef _selectimage
|
|
3537
|
+
if (_selectionimage)
|
|
3538
|
+
#endif
|
|
3539
|
+
pref=(scan->x2 + scan2->x2)*(scan2->x1 - scan->x1) *0.5;
|
|
3540
|
+
theta->Mag += ((scan->dJ>0) ? -1 : 1)*(pref + scan->parab);
|
|
3541
|
+
if(astrometry){
|
|
3542
|
+
dx2=scan2->x2 - scan->x2;
|
|
3543
|
+
avgx1=scan->x1 + scan2->x1;
|
|
3544
|
+
avg2x1 = avgx1 * avgx1;
|
|
3545
|
+
avgx2=scan->x2 + scan2->x2;
|
|
3546
|
+
theta->astrox1 -= ((scan->dJ>0) ? -1 : 1)*(avg2x1*dx2*0.125+scan->parabastrox1);
|
|
3547
|
+
theta->astrox2 += ((scan->dJ>0) ? -1 : 1)*(pref*avgx2*0.25+scan->parabastrox2);
|
|
3548
|
+
}
|
|
3549
|
+
theta->maxerr += mi;
|
|
3550
|
+
#ifdef _ERRORS_ANALYTIC
|
|
3551
|
+
char filnam[32];
|
|
3552
|
+
sprintf(filnam, "%02dfoll.txt", NPS);
|
|
3553
|
+
FILE* f = fopen(filnam, "a+");
|
|
3554
|
+
fprintf(f, "%.15le %.15le %.15le\n", ((scan->dJ > 0) ? -1 : 1)* (pref), ((scan->dJ > 0) ? -1 : 1)* (scan->parab), mi);
|
|
3555
|
+
fclose(f);
|
|
3556
|
+
#endif
|
|
3557
|
+
cpres[issoc[0]]->join(cfoll[issoc[1]]);
|
|
3558
|
+
|
|
3559
|
+
npres--;
|
|
3560
|
+
for (int i = issoc[0]; i<npres; i++) {
|
|
3561
|
+
cpres[i] = cpres[i + 1];
|
|
3562
|
+
for (int j = 0; j<npres + 1; j++) {
|
|
3563
|
+
A[i][j] = A[i + 1][j];
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
for (int j = issoc[1]; j<npres; j++) {
|
|
3567
|
+
cfoll[j] = cfoll[j + 1];
|
|
3568
|
+
for (int i = 0; i<npres; i++) {
|
|
3569
|
+
A[i][j] = A[i][j + 1];
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
mi = 1.e100;
|
|
3573
|
+
for (int i = 0; i<npres; i++) {
|
|
3574
|
+
for (int j = 0; j<npres; j++) {
|
|
3575
|
+
if (A[i][j]<mi) {
|
|
3576
|
+
mi = A[i][j];
|
|
3577
|
+
issoc[0] = i;
|
|
3578
|
+
issoc[1] = j;
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
3584
|
+
|
|
3585
|
+
}
|
|
3586
|
+
|
|
3587
|
+
//////////////////////////////
|
|
3588
|
+
//////////////////////////////
|
|
3589
|
+
////////_point methods
|
|
3590
|
+
//////////////////////////////
|
|
3591
|
+
//////////////////////////////
|
|
3592
|
+
|
|
3593
|
+
|
|
3594
|
+
_point::_point(double x, double y, _theta *theta1) {
|
|
3595
|
+
x1 = x;
|
|
3596
|
+
x2 = y;
|
|
3597
|
+
theta = theta1;
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3600
|
+
double _point::operator-(_point p2) {
|
|
3601
|
+
return (x1 - p2.x1)*(x1 - p2.x1) + (x2 - p2.x2)*(x2 - p2.x2);
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3604
|
+
//////////////////////////////
|
|
3605
|
+
//////////////////////////////
|
|
3606
|
+
////////_curve methods
|
|
3607
|
+
//////////////////////////////
|
|
3608
|
+
//////////////////////////////
|
|
3609
|
+
|
|
3610
|
+
_curve::_curve(void) {
|
|
3611
|
+
length = 0;
|
|
3612
|
+
first = last = 0;
|
|
3613
|
+
partneratstart = partneratend = 0;
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3616
|
+
_curve::_curve(_point *p1) {
|
|
3617
|
+
length = 1;
|
|
3618
|
+
first = last = p1;
|
|
3619
|
+
p1->prev = p1->next = 0;
|
|
3620
|
+
partneratstart = partneratend = 0;
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
_curve::~_curve(void) {
|
|
3624
|
+
_point *scan1, *scan2;
|
|
3625
|
+
scan1 = first;
|
|
3626
|
+
for (int i = 0; i<length; i++) {
|
|
3627
|
+
scan2 = scan1->next;
|
|
3628
|
+
delete scan1;
|
|
3629
|
+
scan1 = scan2;
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
_curve *_curve::divide(_point *ref) {
|
|
3634
|
+
_point *scan;
|
|
3635
|
+
_curve *nc;
|
|
3636
|
+
int l1;
|
|
3637
|
+
|
|
3638
|
+
l1 = 1;
|
|
3639
|
+
for (scan = first; scan != ref; scan = scan->next) l1++;
|
|
3640
|
+
nc = new _curve();
|
|
3641
|
+
nc->first = ref->next;
|
|
3642
|
+
nc->first->prev = 0;
|
|
3643
|
+
nc->last = last;
|
|
3644
|
+
nc->length = length - l1;
|
|
3645
|
+
nc->partneratend = partneratend;
|
|
3646
|
+
if (partneratend) partneratend->partneratend = nc;
|
|
3647
|
+
|
|
3648
|
+
length = l1;
|
|
3649
|
+
last = ref;
|
|
3650
|
+
ref->next = 0;
|
|
3651
|
+
partneratend = 0;
|
|
3652
|
+
return nc;
|
|
3653
|
+
}
|
|
3654
|
+
|
|
3655
|
+
|
|
3656
|
+
void _curve::append(double x1, double x2) {
|
|
3657
|
+
_point *pp;
|
|
3658
|
+
pp = new _point(x1, x2, 0);
|
|
3659
|
+
if (length == 0) {
|
|
3660
|
+
first = pp;
|
|
3661
|
+
last = pp;
|
|
3662
|
+
pp->prev = 0;
|
|
3663
|
+
}
|
|
3664
|
+
else {
|
|
3665
|
+
last->next = pp;
|
|
3666
|
+
pp->prev = last;
|
|
3667
|
+
last = pp;
|
|
3668
|
+
}
|
|
3669
|
+
pp->next = 0;
|
|
3670
|
+
length++;
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
void _curve::append(_point *pp) {
|
|
3674
|
+
|
|
3675
|
+
pp->next = last->next;
|
|
3676
|
+
pp->prev = last;
|
|
3677
|
+
last->next = pp;
|
|
3678
|
+
last = pp;
|
|
3679
|
+
length++;
|
|
3680
|
+
}
|
|
3681
|
+
|
|
3682
|
+
void _curve::prepend(double x1, double x2) {
|
|
3683
|
+
_point *pp;
|
|
3684
|
+
pp = new _point(x1, x2, 0);
|
|
3685
|
+
if (length == 0) {
|
|
3686
|
+
first = pp;
|
|
3687
|
+
last = pp;
|
|
3688
|
+
pp->next = 0;
|
|
3689
|
+
}
|
|
3690
|
+
else {
|
|
3691
|
+
first->prev = pp;
|
|
3692
|
+
pp->next = first;
|
|
3693
|
+
first = pp;
|
|
3694
|
+
}
|
|
3695
|
+
pp->prev = 0;
|
|
3696
|
+
length++;
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3699
|
+
_curve *_curve::join(_curve *nc) {
|
|
3700
|
+
if (length>0) {
|
|
3701
|
+
last->next = nc->first;
|
|
3702
|
+
}
|
|
3703
|
+
else {
|
|
3704
|
+
first = nc->first;
|
|
3705
|
+
};
|
|
3706
|
+
if (nc->length>0) {
|
|
3707
|
+
nc->first->prev = last;
|
|
3708
|
+
last = nc->last;
|
|
3709
|
+
}
|
|
3710
|
+
length += nc->length;
|
|
3711
|
+
partneratend = nc->partneratend;
|
|
3712
|
+
if (partneratend) partneratend->partneratend = this;
|
|
3713
|
+
nc->first = 0;
|
|
3714
|
+
nc->last = 0;
|
|
3715
|
+
nc->length = 0;
|
|
3716
|
+
delete nc;
|
|
3717
|
+
return this;
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
_curve *_curve::joinbefore(_curve *nc) {
|
|
3721
|
+
if (length>0) {
|
|
3722
|
+
first->prev = nc->last;
|
|
3723
|
+
}
|
|
3724
|
+
else {
|
|
3725
|
+
last = nc->last;
|
|
3726
|
+
};
|
|
3727
|
+
if (nc->length>0) {
|
|
3728
|
+
nc->last->next = first;
|
|
3729
|
+
first = nc->first;
|
|
3730
|
+
}
|
|
3731
|
+
length += nc->length;
|
|
3732
|
+
nc->first = 0;
|
|
3733
|
+
nc->last = 0;
|
|
3734
|
+
nc->length = 0;
|
|
3735
|
+
delete nc;
|
|
3736
|
+
return this;
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
_curve *_curve::reverse(void) {
|
|
3740
|
+
_point *scan1, *scan2, *scambio;
|
|
3741
|
+
if (length>1) {
|
|
3742
|
+
scan1 = first;
|
|
3743
|
+
while (scan1) {
|
|
3744
|
+
scan2 = scan1->next;
|
|
3745
|
+
scambio = scan1->next;
|
|
3746
|
+
scan1->next = scan1->prev;
|
|
3747
|
+
scan1->prev = scambio;
|
|
3748
|
+
scan1 = scan2;
|
|
3749
|
+
}
|
|
3750
|
+
scambio = first;
|
|
3751
|
+
first = last;
|
|
3752
|
+
last = scambio;
|
|
3753
|
+
}
|
|
3754
|
+
return this;
|
|
3755
|
+
}
|
|
3756
|
+
|
|
3757
|
+
void _curve::drop(_point *ref) {
|
|
3758
|
+
_point *scan;
|
|
3759
|
+
if (length) {
|
|
3760
|
+
for (scan = last; scan && (scan != ref); scan = scan->prev);
|
|
3761
|
+
if (scan) {
|
|
3762
|
+
if (length == 1) {
|
|
3763
|
+
first = last = 0;
|
|
3764
|
+
}
|
|
3765
|
+
else {
|
|
3766
|
+
if (ref->prev) {
|
|
3767
|
+
ref->prev->next = ref->next;
|
|
3768
|
+
if (ref == last) {
|
|
3769
|
+
last = ref->prev;
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
if (ref->next) {
|
|
3773
|
+
ref->next->prev = ref->prev;
|
|
3774
|
+
if (ref == first) {
|
|
3775
|
+
first = ref->next;
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
length--;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3784
|
+
double _curve::closest2(_point *ref, _point **clos2) {
|
|
3785
|
+
double mi = 1.e100, mi2 = 1.e100, FP;
|
|
3786
|
+
_point *scan, *clos;
|
|
3787
|
+
if (length>1) {
|
|
3788
|
+
clos = *clos2 = first;
|
|
3789
|
+
for (scan = first; scan != 0; scan = scan->next) {
|
|
3790
|
+
FP = *scan - *ref;
|
|
3791
|
+
if (FP<mi) {
|
|
3792
|
+
mi2 = mi;
|
|
3793
|
+
mi = FP;
|
|
3794
|
+
*clos2 = clos;
|
|
3795
|
+
clos = scan;
|
|
3796
|
+
}
|
|
3797
|
+
else if (FP<mi2) {
|
|
3798
|
+
mi2 = FP;
|
|
3799
|
+
*clos2 = scan;
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
else {
|
|
3804
|
+
*clos2 = 0;
|
|
3805
|
+
}
|
|
3806
|
+
return (**clos2 - *ref);
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3809
|
+
double _curve::closest(_point *ref, _point **clos) {
|
|
3810
|
+
double mi = 1.e100, FP;
|
|
3811
|
+
_point *scan;
|
|
3812
|
+
for (scan = first; scan != 0; scan = scan->next) {
|
|
3813
|
+
FP = *scan - *ref;
|
|
3814
|
+
if (FP<mi) {
|
|
3815
|
+
mi = FP;
|
|
3816
|
+
*clos = scan;
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
return mi;
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
void _curve::complement(_point **sott, int lensott, _point **res, int lenres) {
|
|
3823
|
+
int flag, i;
|
|
3824
|
+
_point *scan;
|
|
3825
|
+
i = 0;
|
|
3826
|
+
for (scan = first; scan != 0; scan = scan->next) {
|
|
3827
|
+
flag = 0;
|
|
3828
|
+
for (int j = 0; (j<lensott) && (!flag); j++) {
|
|
3829
|
+
if (scan == sott[j]) {
|
|
3830
|
+
flag = 1;
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
if ((!flag) && (i<lenres)) {
|
|
3834
|
+
res[i] = scan;
|
|
3835
|
+
i++;
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
|
|
3840
|
+
//////////////////////////////
|
|
3841
|
+
//////////////////////////////
|
|
3842
|
+
////////_sols methods
|
|
3843
|
+
//////////////////////////////
|
|
3844
|
+
//////////////////////////////
|
|
3845
|
+
|
|
3846
|
+
|
|
3847
|
+
_sols::_sols(void) {
|
|
3848
|
+
length = 0;
|
|
3849
|
+
first = last = 0;
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
_sols::~_sols(void) {
|
|
3853
|
+
_curve *scan1, *scan2;
|
|
3854
|
+
scan1 = first;
|
|
3855
|
+
while (scan1) {
|
|
3856
|
+
scan2 = scan1->next;
|
|
3857
|
+
delete scan1;
|
|
3858
|
+
scan1 = scan2;
|
|
3859
|
+
}
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
void _sols::append(_curve *cc) {
|
|
3863
|
+
if (length == 0) {
|
|
3864
|
+
first = cc;
|
|
3865
|
+
last = cc;
|
|
3866
|
+
cc->prev = 0;
|
|
3867
|
+
}
|
|
3868
|
+
else {
|
|
3869
|
+
last->next = cc;
|
|
3870
|
+
cc->prev = last;
|
|
3871
|
+
last = cc;
|
|
3872
|
+
}
|
|
3873
|
+
cc->next = 0;
|
|
3874
|
+
length++;
|
|
3875
|
+
}
|
|
3876
|
+
|
|
3877
|
+
void _sols::prepend(_curve *cc) {
|
|
3878
|
+
if (length == 0) {
|
|
3879
|
+
first = cc;
|
|
3880
|
+
last = cc;
|
|
3881
|
+
cc->next = 0;
|
|
3882
|
+
}
|
|
3883
|
+
else {
|
|
3884
|
+
first->prev = cc;
|
|
3885
|
+
cc->next = first;
|
|
3886
|
+
first = cc;
|
|
3887
|
+
}
|
|
3888
|
+
cc->prev = 0;
|
|
3889
|
+
length++;
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
void _sols::drop(_curve *ref) {
|
|
3893
|
+
_curve *scan;
|
|
3894
|
+
if (length) {
|
|
3895
|
+
for (scan = last; scan && (scan != ref); scan = scan->prev);
|
|
3896
|
+
if (scan) {
|
|
3897
|
+
if (length == 1) {
|
|
3898
|
+
first = last = 0;
|
|
3899
|
+
}
|
|
3900
|
+
else {
|
|
3901
|
+
if (ref->prev) {
|
|
3902
|
+
ref->prev->next = ref->next;
|
|
3903
|
+
if (ref == last) {
|
|
3904
|
+
last = ref->prev;
|
|
3905
|
+
}
|
|
3906
|
+
}
|
|
3907
|
+
if (ref->next) {
|
|
3908
|
+
ref->next->prev = ref->prev;
|
|
3909
|
+
if (ref == first) {
|
|
3910
|
+
first = ref->next;
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
length--;
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
|
|
3919
|
+
void _sols::join(_sols *nc) {
|
|
3920
|
+
if (length>0) {
|
|
3921
|
+
last->next = nc->first;
|
|
3922
|
+
}
|
|
3923
|
+
else {
|
|
3924
|
+
first = nc->first;
|
|
3925
|
+
};
|
|
3926
|
+
if (nc->length>0) {
|
|
3927
|
+
nc->first->prev = last;
|
|
3928
|
+
last = nc->last;
|
|
3929
|
+
}
|
|
3930
|
+
length += nc->length;
|
|
3931
|
+
nc->first = 0;
|
|
3932
|
+
nc->last = 0;
|
|
3933
|
+
nc->length = 0;
|
|
3934
|
+
delete nc;
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
//////////////////////////////
|
|
3938
|
+
//////////////////////////////
|
|
3939
|
+
////////_theta methods
|
|
3940
|
+
//////////////////////////////
|
|
3941
|
+
//////////////////////////////
|
|
3942
|
+
|
|
3943
|
+
_theta::_theta(double th1) {
|
|
3944
|
+
th = th1;
|
|
3945
|
+
}
|
|
3946
|
+
_thetas::_thetas(void) {
|
|
3947
|
+
length = 0;
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3950
|
+
_thetas::~_thetas(void) {
|
|
3951
|
+
_theta *scan, *scan2;
|
|
3952
|
+
scan = first;
|
|
3953
|
+
while (scan) {
|
|
3954
|
+
scan2 = scan->next;
|
|
3955
|
+
delete scan;
|
|
3956
|
+
scan = scan2;
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3960
|
+
_theta *_thetas::insert(double th) {
|
|
3961
|
+
_theta *scan, *scan2;
|
|
3962
|
+
|
|
3963
|
+
scan2 = new _theta(th);
|
|
3964
|
+
if (length) {
|
|
3965
|
+
if (th<first->th) {
|
|
3966
|
+
first->prev = scan2;
|
|
3967
|
+
scan2->next = first;
|
|
3968
|
+
scan2->prev = 0;
|
|
3969
|
+
first = scan2;
|
|
3970
|
+
}
|
|
3971
|
+
else {
|
|
3972
|
+
if (th>last->th) {
|
|
3973
|
+
last->next = scan2;
|
|
3974
|
+
scan2->prev = last;
|
|
3975
|
+
scan2->next = 0;
|
|
3976
|
+
last = scan2;
|
|
3977
|
+
}
|
|
3978
|
+
else {
|
|
3979
|
+
scan = first;
|
|
3980
|
+
while (scan->th<th) scan = scan->next;
|
|
3981
|
+
scan2->next = scan;
|
|
3982
|
+
scan2->prev = scan->prev;
|
|
3983
|
+
scan->prev->next = scan2;
|
|
3984
|
+
scan->prev = scan2;
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
else {
|
|
3989
|
+
first = scan2;
|
|
3990
|
+
last = scan2;
|
|
3991
|
+
scan2->next = 0;
|
|
3992
|
+
scan2->prev = 0;
|
|
3993
|
+
}
|
|
3994
|
+
length++;
|
|
3995
|
+
// scan2->maxerr=0.;
|
|
3996
|
+
return scan2;
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3999
|
+
void _thetas::remove(_theta* stheta) {
|
|
4000
|
+
_theta *scan;
|
|
4001
|
+
scan = first;
|
|
4002
|
+
while (scan!=0) {
|
|
4003
|
+
if (scan == stheta) {
|
|
4004
|
+
if(scan!=first) scan->prev->next = stheta->next;
|
|
4005
|
+
if (scan != last) scan->next->prev = stheta->prev;
|
|
4006
|
+
delete stheta;
|
|
4007
|
+
length--;
|
|
4008
|
+
break;
|
|
4009
|
+
}
|
|
4010
|
+
scan = scan->next;
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
//////////////////////////////
|
|
4015
|
+
//////////////////////////////
|
|
4016
|
+
////////complex methods and operators
|
|
4017
|
+
//////////////////////////////
|
|
4018
|
+
//////////////////////////////
|
|
4019
|
+
|
|
4020
|
+
|
|
4021
|
+
complex::complex(double a, double b) {
|
|
4022
|
+
re = a;
|
|
4023
|
+
im = b;
|
|
4024
|
+
}
|
|
4025
|
+
|
|
4026
|
+
complex::complex(double a) {
|
|
4027
|
+
re = a;
|
|
4028
|
+
im = 0;
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
complex::complex(void) {
|
|
4032
|
+
re = 0;
|
|
4033
|
+
im = 0;
|
|
4034
|
+
}
|
|
4035
|
+
|
|
4036
|
+
double abs(complex z) {
|
|
4037
|
+
return sqrt(z.re*z.re + z.im*z.im);
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
complex conj(complex z) {
|
|
4041
|
+
return complex(z.re, -z.im);
|
|
4042
|
+
}
|
|
4043
|
+
|
|
4044
|
+
complex sqrt(complex z) {
|
|
4045
|
+
double md = sqrt(z.re*z.re + z.im*z.im);
|
|
4046
|
+
return (md>0) ? complex((sqrt((md + z.re) / 2)*((z.im>0) ? 1 : -1)), sqrt((md - z.re) / 2)) : 0.0;
|
|
4047
|
+
}
|
|
4048
|
+
|
|
4049
|
+
double real(complex z) {
|
|
4050
|
+
return z.re;
|
|
4051
|
+
}
|
|
4052
|
+
|
|
4053
|
+
double imag(complex z) {
|
|
4054
|
+
return z.im;
|
|
4055
|
+
}
|
|
4056
|
+
|
|
4057
|
+
complex operator+(complex p1, complex p2) {
|
|
4058
|
+
return complex(p1.re + p2.re, p1.im + p2.im);
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
complex operator-(complex p1, complex p2) {
|
|
4062
|
+
return complex(p1.re - p2.re, p1.im - p2.im);
|
|
4063
|
+
}
|
|
4064
|
+
|
|
4065
|
+
complex operator*(complex p1, complex p2) {
|
|
4066
|
+
return complex(p1.re*p2.re - p1.im*p2.im, p1.re*p2.im + p1.im*p2.re);
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
complex operator/(complex p1, complex p2) {
|
|
4070
|
+
double md = p2.re*p2.re + p2.im*p2.im;
|
|
4071
|
+
return complex((p1.re*p2.re + p1.im*p2.im) / md, (p1.im*p2.re - p1.re*p2.im) / md);
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
complex operator+(complex z, double a) {
|
|
4075
|
+
return complex(z.re + a, z.im);
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4078
|
+
complex operator-(complex z, double a) {
|
|
4079
|
+
return complex(z.re - a, z.im);
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
complex operator*(complex z, double a) {
|
|
4083
|
+
return complex(z.re*a, z.im*a);
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
complex operator/(complex z, double a) {
|
|
4087
|
+
return complex(z.re / a, z.im / a);
|
|
4088
|
+
}
|
|
4089
|
+
|
|
4090
|
+
complex operator+(double a, complex z) {
|
|
4091
|
+
return complex(z.re + a, z.im);
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4094
|
+
complex operator-(double a, complex z) {
|
|
4095
|
+
return complex(a - z.re, -z.im);
|
|
4096
|
+
}
|
|
4097
|
+
|
|
4098
|
+
complex operator*(double a, complex z) {
|
|
4099
|
+
return complex(a*z.re, a*z.im);
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4102
|
+
complex operator/(double a, complex z) {
|
|
4103
|
+
double md = z.re*z.re + z.im*z.im;
|
|
4104
|
+
return complex(a*z.re / md, -a*z.im / md);
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4107
|
+
|
|
4108
|
+
complex operator+(complex z, int a) {
|
|
4109
|
+
return complex(z.re + a, z.im);
|
|
4110
|
+
}
|
|
4111
|
+
|
|
4112
|
+
complex operator-(complex z, int a) {
|
|
4113
|
+
return complex(z.re - a, z.im);
|
|
4114
|
+
}
|
|
4115
|
+
|
|
4116
|
+
complex operator*(complex z, int a) {
|
|
4117
|
+
return complex(z.re*a, z.im*a);
|
|
4118
|
+
}
|
|
4119
|
+
|
|
4120
|
+
complex operator/(complex z, int a) {
|
|
4121
|
+
return complex(z.re / a, z.im / a);
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
complex operator+(int a, complex z) {
|
|
4125
|
+
return complex(z.re + a, z.im);
|
|
4126
|
+
}
|
|
4127
|
+
|
|
4128
|
+
complex operator-(int a, complex z) {
|
|
4129
|
+
return complex(a - z.re, -z.im);
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4132
|
+
complex operator*(int a, complex z) {
|
|
4133
|
+
return complex(a*z.re, a*z.im);
|
|
4134
|
+
}
|
|
4135
|
+
|
|
4136
|
+
complex operator/(int a, complex z) {
|
|
4137
|
+
double md = z.re*z.re + z.im*z.im;
|
|
4138
|
+
return complex(a*z.re / md, -a*z.im / md);
|
|
4139
|
+
}
|
|
4140
|
+
|
|
4141
|
+
complex operator-(complex z) {
|
|
4142
|
+
return complex(-z.re, -z.im);
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
bool operator==(complex p1, complex p2) {
|
|
4146
|
+
if (p1.re == p2.re && p1.im == p2.im) return true;
|
|
4147
|
+
return false;
|
|
4148
|
+
}
|
|
4149
|
+
|
|
4150
|
+
bool operator!=(complex p1, complex p2) {
|
|
4151
|
+
if (p1.re == p2.re && p1.im == p2.im) return false;
|
|
4152
|
+
return true;
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4155
|
+
complex expcmplx(complex p1) {
|
|
4156
|
+
double r = exp(p1.re);
|
|
4157
|
+
double theta = atan2(p1.im, p1.re);
|
|
4158
|
+
return complex(r*cos(theta), r*sin(theta));
|
|
4159
|
+
}
|
|
4160
|
+
|
|
4161
|
+
complex cbrt(complex z) {
|
|
4162
|
+
complex zout;
|
|
4163
|
+
double r, r_cube, theta, theta_cube;
|
|
4164
|
+
r = abs(z);
|
|
4165
|
+
r_cube = pow(r, 0.333333333333);
|
|
4166
|
+
theta = atan2(z.im, z.re);
|
|
4167
|
+
theta_cube = theta / 3.;
|
|
4168
|
+
return complex(r_cube*cos(theta_cube), r_cube*sin(theta_cube));
|
|
4169
|
+
}
|
|
4170
|
+
|
|
4171
|
+
//////////////////////////////
|
|
4172
|
+
//////////////////////////////
|
|
4173
|
+
////////_Skowron & Gould functions, translated by Tyler M. Heintz and Ava R. Hoag
|
|
4174
|
+
//////////////////////////////
|
|
4175
|
+
//////////////////////////////
|
|
4176
|
+
// See copyright notice for these functions
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
void VBBinaryLensing::cmplx_roots_gen(complex *roots, complex *poly, int degree, bool polish_roots_after, bool use_roots_as_starting_points) {
|
|
4180
|
+
//roots - array which will hold all roots that had been found.
|
|
4181
|
+
//If the flag 'use_roots_as_starting_points' is set to
|
|
4182
|
+
//.true., then instead of point(0, 0) we use value from
|
|
4183
|
+
//this array as starting point for cmplx_laguerre
|
|
4184
|
+
|
|
4185
|
+
//poly - is an array of polynomial cooefs, length = degree + 1,
|
|
4186
|
+
//poly[0] x ^ 0 + poly[1] x ^ 1 + poly[2] x ^ 2 + ...
|
|
4187
|
+
|
|
4188
|
+
//degree - degree of the polynomial and size of 'roots' array
|
|
4189
|
+
|
|
4190
|
+
//polish_roots_after - after all roots have been found by dividing
|
|
4191
|
+
//original polynomial by each root found,
|
|
4192
|
+
//you can opt in to polish all roots using full
|
|
4193
|
+
//polynomial
|
|
4194
|
+
|
|
4195
|
+
//use_roots_as_starting_points - usually we start Laguerre's
|
|
4196
|
+
//method from point(0, 0), but you can decide to use the
|
|
4197
|
+
//values of 'roots' array as starting point for each new
|
|
4198
|
+
//root that is searched for.This is useful if you have
|
|
4199
|
+
//very rough idea where some of the roots can be.
|
|
4200
|
+
//
|
|
4201
|
+
|
|
4202
|
+
complex poly2[MAXM];
|
|
4203
|
+
static int i, j, n, iter;
|
|
4204
|
+
bool success;
|
|
4205
|
+
complex coef, prev;
|
|
4206
|
+
|
|
4207
|
+
if (!use_roots_as_starting_points) {
|
|
4208
|
+
for (int jj = 0; jj < degree; jj++) {
|
|
4209
|
+
roots[jj] = complex(0, 0);
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
for (j = 0; j <= degree; j++) poly2[j] = poly[j];
|
|
4214
|
+
|
|
4215
|
+
// Don't do Laguerre's for small degree polynomials
|
|
4216
|
+
if (degree <= 1) {
|
|
4217
|
+
if (degree == 1) roots[0] = -poly[0] / poly[1];
|
|
4218
|
+
return;
|
|
4219
|
+
}
|
|
4220
|
+
|
|
4221
|
+
for (n = degree; n >= 3; n--) {
|
|
4222
|
+
cmplx_laguerre2newton(poly2, n, &roots[n - 1], iter, success, 2);
|
|
4223
|
+
if (!success) {
|
|
4224
|
+
roots[n - 1] = complex(0, 0);
|
|
4225
|
+
cmplx_laguerre(poly2, n, &roots[n - 1], iter, success);
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
// Divide by root
|
|
4229
|
+
coef = poly2[n];
|
|
4230
|
+
for (i = n - 1; i >= 0; i--) {
|
|
4231
|
+
prev = poly2[i];
|
|
4232
|
+
poly2[i] = coef;
|
|
4233
|
+
coef = prev + roots[n - 1] * coef;
|
|
4234
|
+
}
|
|
4235
|
+
}
|
|
4236
|
+
|
|
4237
|
+
|
|
4238
|
+
//Find the to last 2 roots
|
|
4239
|
+
solve_quadratic_eq(roots[1], roots[0], poly2);
|
|
4240
|
+
//cmplx_laguerre2newton(poly2, 2, &roots[1], iter, success, 2);
|
|
4241
|
+
//if (!success) {
|
|
4242
|
+
// solve_quadratic_eq(roots[1], roots[0], poly2);
|
|
4243
|
+
//}
|
|
4244
|
+
//else {
|
|
4245
|
+
// roots[0] = -(roots[1] + poly2[1] / poly2[2]); // Viete's Formula for the last root
|
|
4246
|
+
//}
|
|
4247
|
+
|
|
4248
|
+
|
|
4249
|
+
|
|
4250
|
+
if (polish_roots_after) {
|
|
4251
|
+
for (n = 0; n < degree; n++) {
|
|
4252
|
+
cmplx_newton_spec(poly, degree, &roots[n], iter, success); // Polish roots with full polynomial
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
|
|
4256
|
+
return;
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
void VBBinaryLensing::solve_quadratic_eq(complex &x0, complex &x1, complex *poly) {
|
|
4260
|
+
complex a, b, c, b2, delta;
|
|
4261
|
+
a = poly[2];
|
|
4262
|
+
b = poly[1];
|
|
4263
|
+
c = poly[0];
|
|
4264
|
+
b2 = b*b;
|
|
4265
|
+
delta = sqrt(b2 - 4 * a*c);
|
|
4266
|
+
if (real(conj(b)*delta) >= 0) {
|
|
4267
|
+
x0 = -0.5*(b + delta);
|
|
4268
|
+
}
|
|
4269
|
+
else {
|
|
4270
|
+
x0 = -0.5*(b - delta);
|
|
4271
|
+
}
|
|
4272
|
+
if (x0 == complex(0., 0.)) {
|
|
4273
|
+
x1 = complex(0., 0.);
|
|
4274
|
+
}
|
|
4275
|
+
else { //Viete's formula
|
|
4276
|
+
x1 = c / x0;
|
|
4277
|
+
x0 = x0 / a;
|
|
4278
|
+
}
|
|
4279
|
+
return;
|
|
4280
|
+
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4283
|
+
void VBBinaryLensing::solve_cubic_eq(complex &x0, complex &x1, complex &x2, complex *poly) {
|
|
4284
|
+
//Cubic equation solver for comples polynomial (degree=3)
|
|
4285
|
+
//http://en.wikipedia.org/wiki/Cubic_function Lagrange's method
|
|
4286
|
+
// poly is an array of polynomial cooefs, length = degree+1, poly[0] is constant
|
|
4287
|
+
// 0 1 2 3
|
|
4288
|
+
//poly[0] x^0 + poly[1] x^1 + poly[2] x^2 + poly[3] x^3
|
|
4289
|
+
complex zeta = complex(-0.5, 0.8660254037844386);
|
|
4290
|
+
complex zeta2 = complex(-0.5, -0.8660254037844386);
|
|
4291
|
+
double third = 0.3333333333333333;
|
|
4292
|
+
complex s0, s1, s2;
|
|
4293
|
+
complex E1; //x0+x1+x2
|
|
4294
|
+
complex E2; //x0*x1+x1*x2+x2*x0
|
|
4295
|
+
complex E3; //x0*x1*x2
|
|
4296
|
+
complex A, B, a_1, E12, delta, A2;
|
|
4297
|
+
|
|
4298
|
+
complex val, x;
|
|
4299
|
+
a_1 = 1 / poly[3];
|
|
4300
|
+
E1 = -poly[2] * a_1;
|
|
4301
|
+
E2 = poly[1] * a_1;
|
|
4302
|
+
E3 = -poly[0] * a_1;
|
|
4303
|
+
|
|
4304
|
+
s0 = E1;
|
|
4305
|
+
E12 = E1*E1;
|
|
4306
|
+
A = 2.0 * E1 * E12 - 9.0 * E1 * E2 + 27.0 * E3;
|
|
4307
|
+
B = E12 - 3.0 * E2;
|
|
4308
|
+
//quadratic equation z^2 - A * z + B^3 where roots are equal to s1^3 and s2^3
|
|
4309
|
+
A2 = A * A;
|
|
4310
|
+
delta = sqrt(A2 - 4.0 * (B * B * B));
|
|
4311
|
+
if (real(conj(A) * delta) >= 0.0) { // scalar product to decide the sign yielding bigger magnitude
|
|
4312
|
+
s1 = cbrt(0.5 * (A + delta));
|
|
4313
|
+
}
|
|
4314
|
+
else
|
|
4315
|
+
{
|
|
4316
|
+
s1 = cbrt(0.5 * (A - delta));
|
|
4317
|
+
}
|
|
4318
|
+
if (s1.re == 0.0 && s1.im == 0.0) {
|
|
4319
|
+
s2 = complex(0, 0);
|
|
4320
|
+
}
|
|
4321
|
+
else {
|
|
4322
|
+
s2 = B / s1;
|
|
4323
|
+
}
|
|
4324
|
+
|
|
4325
|
+
x0 = third * (s0 + s1 + s2);
|
|
4326
|
+
x1 = third * (s0 + s1 * zeta2 + s2 * zeta);
|
|
4327
|
+
x2 = third * (s0 + s1 * zeta + s2 * zeta2);
|
|
4328
|
+
|
|
4329
|
+
return;
|
|
4330
|
+
|
|
4331
|
+
}
|
|
4332
|
+
|
|
4333
|
+
void VBBinaryLensing::cmplx_laguerre(complex *poly, int degree, complex *root, int &iter, bool &success) {
|
|
4334
|
+
//Subroutine finds one root of a complex polynomial using
|
|
4335
|
+
//Laguerre's method. In every loop it calculates simplified
|
|
4336
|
+
//Adams' stopping criterion for the value of the polynomial.
|
|
4337
|
+
//
|
|
4338
|
+
//Uses 'root' value as a starting point(!!!!!)
|
|
4339
|
+
//Remember to initialize 'root' to some initial guess or to
|
|
4340
|
+
//point(0, 0) if you have no prior knowledge.
|
|
4341
|
+
//
|
|
4342
|
+
//poly - is an array of polynomial cooefs
|
|
4343
|
+
//
|
|
4344
|
+
//length = degree + 1, poly(1) is constant
|
|
4345
|
+
// 1 2 3
|
|
4346
|
+
//poly(1) x ^ 0 + poly(2) x ^ 1 + poly(3) x ^ 2 + ...
|
|
4347
|
+
//
|
|
4348
|
+
//degree - a degree of the polynomial
|
|
4349
|
+
//
|
|
4350
|
+
//root - input: guess for the value of a root
|
|
4351
|
+
//output : a root of the polynomial
|
|
4352
|
+
//iter - number of iterations performed(the number of polynomial
|
|
4353
|
+
//evaluations and stopping criterion evaluation)
|
|
4354
|
+
//
|
|
4355
|
+
//success - is false if routine reaches maximum number of iterations
|
|
4356
|
+
//
|
|
4357
|
+
//For a summary of the method go to :
|
|
4358
|
+
//http://en.wikipedia.org/wiki/Laguerre's_method
|
|
4359
|
+
//
|
|
4360
|
+
static int FRAC_JUMP_EVERY = 10;
|
|
4361
|
+
const int FRAC_JUMP_LEN = 10;
|
|
4362
|
+
double FRAC_JUMPS[FRAC_JUMP_LEN] = { 0.64109297,
|
|
4363
|
+
0.91577881, 0.25921289, 0.50487203,
|
|
4364
|
+
0.08177045, 0.13653241, 0.306162,
|
|
4365
|
+
0.37794326, 0.04618805, 0.75132137 }; // some random numbers
|
|
4366
|
+
|
|
4367
|
+
double faq; //jump length
|
|
4368
|
+
double FRAC_ERR = 2.0e-15; //Fractional Error for double precision
|
|
4369
|
+
complex p, dp, d2p_half; //value of polynomial, 1st derivative, and 2nd derivative
|
|
4370
|
+
static int i, j, k;
|
|
4371
|
+
bool good_to_go;
|
|
4372
|
+
complex denom, denom_sqrt, dx, newroot;
|
|
4373
|
+
double ek, absroot, abs2p;
|
|
4374
|
+
complex fac_newton, fac_extra, F_half, c_one_nth;
|
|
4375
|
+
double one_nth, n_1_nth, two_n_div_n_1;
|
|
4376
|
+
complex c_one = complex(1, 0);
|
|
4377
|
+
complex zero = complex(0, 0);
|
|
4378
|
+
double stopping_crit2;
|
|
4379
|
+
|
|
4380
|
+
//--------------------------------------------------------------------------------------------
|
|
4381
|
+
|
|
4382
|
+
//EXTREME FAILSAFE! not usually needed but kept here just to be on the safe side. Takes care of first coefficient being 0
|
|
4383
|
+
if (false) {
|
|
4384
|
+
if (degree < 0) {
|
|
4385
|
+
printf("Error: cmplx_laguerre: degree<0");
|
|
4386
|
+
return;
|
|
4387
|
+
}
|
|
4388
|
+
if (poly[degree] == complex(0, 0)) {
|
|
4389
|
+
if (degree == 0) return;
|
|
4390
|
+
cmplx_laguerre(poly, degree - 1, root, iter, success);
|
|
4391
|
+
}
|
|
4392
|
+
if (degree <= 1) {
|
|
4393
|
+
if (degree == 0) {
|
|
4394
|
+
success = false; // we just checked if poly[0] is zero and it isnt
|
|
4395
|
+
printf("Warning: cmplx_laguerre: degree = 0 and poly[0] does not equal zero, no roots");
|
|
4396
|
+
return;
|
|
4397
|
+
}
|
|
4398
|
+
else {
|
|
4399
|
+
*root = -poly[0] / poly[1];
|
|
4400
|
+
return;
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
} // End of EXTREME failsafe
|
|
4404
|
+
|
|
4405
|
+
good_to_go = false;
|
|
4406
|
+
one_nth = 1.0 / degree;
|
|
4407
|
+
n_1_nth = (degree - 1.0)*one_nth;
|
|
4408
|
+
two_n_div_n_1 = 2.0 / n_1_nth;
|
|
4409
|
+
c_one_nth = complex(one_nth, 0.0);
|
|
4410
|
+
for (i = 1; i <= MAXIT; i++) {
|
|
4411
|
+
ek = abs(poly[degree]); // Preparing stopping criterion
|
|
4412
|
+
absroot = abs(*root);
|
|
4413
|
+
// Calculate the values of polynomial and its first and second derivatives
|
|
4414
|
+
p = poly[degree];
|
|
4415
|
+
dp = zero;
|
|
4416
|
+
d2p_half = zero;
|
|
4417
|
+
for (k = degree - 1; k >= 0; k--) {
|
|
4418
|
+
d2p_half = dp + d2p_half*(*root);
|
|
4419
|
+
dp = p + dp * *root;
|
|
4420
|
+
p = poly[k] + p*(*root); // b_k
|
|
4421
|
+
//Adams, Duane A., 1967, "A stopping criterion for polynomial root finding",
|
|
4422
|
+
//Communications of the ACM, Volume 10 Issue 10, Oct. 1967, p. 655
|
|
4423
|
+
//ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/67/55/CS-TR-67-55.pdf
|
|
4424
|
+
//Eq 8.
|
|
4425
|
+
ek = absroot*ek + abs(p);
|
|
4426
|
+
}
|
|
4427
|
+
iter += 1;
|
|
4428
|
+
|
|
4429
|
+
abs2p = real(conj(p)*p);
|
|
4430
|
+
if (abs2p == 0) return;
|
|
4431
|
+
stopping_crit2 = pow(FRAC_ERR*ek, 2.0);
|
|
4432
|
+
if (abs2p < stopping_crit2) {
|
|
4433
|
+
//(simplified a little Eq. 10 of Adams 1967)
|
|
4434
|
+
//do additional iteration if we are less than 10x from stopping criterion
|
|
4435
|
+
if (abs2p < 0.01*stopping_crit2) {
|
|
4436
|
+
return; // we are at a good place!
|
|
4437
|
+
}
|
|
4438
|
+
else {
|
|
4439
|
+
good_to_go = true;
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
else {
|
|
4443
|
+
good_to_go = false;
|
|
4444
|
+
}
|
|
4445
|
+
|
|
4446
|
+
faq = 1.0;
|
|
4447
|
+
denom = zero;
|
|
4448
|
+
if (dp != zero) {
|
|
4449
|
+
fac_newton = p / dp;
|
|
4450
|
+
fac_extra = d2p_half / dp;
|
|
4451
|
+
F_half = fac_newton*fac_extra;
|
|
4452
|
+
denom_sqrt = sqrt(c_one - two_n_div_n_1*F_half);
|
|
4453
|
+
|
|
4454
|
+
//NEXT LINE PROBABLY CAN BE COMMENTED OUT. Check if compiler outputs positive real
|
|
4455
|
+
if (real(denom_sqrt) >= 0.0) {
|
|
4456
|
+
denom = c_one_nth + n_1_nth*denom_sqrt;
|
|
4457
|
+
}
|
|
4458
|
+
else {
|
|
4459
|
+
denom = c_one_nth - n_1_nth*denom_sqrt;
|
|
4460
|
+
}
|
|
4461
|
+
}
|
|
4462
|
+
|
|
4463
|
+
if (denom == 0) {
|
|
4464
|
+
dx = (absroot + 1.0)*expcmplx(complex(0.0, FRAC_JUMPS[i % FRAC_JUMP_LEN] * 2 * M_PI));
|
|
4465
|
+
}
|
|
4466
|
+
else {
|
|
4467
|
+
dx = fac_newton / denom;
|
|
4468
|
+
}
|
|
4469
|
+
|
|
4470
|
+
|
|
4471
|
+
newroot = *root - dx;
|
|
4472
|
+
if (newroot == *root) return; //nothing changes so return
|
|
4473
|
+
if (good_to_go) {
|
|
4474
|
+
*root = newroot;
|
|
4475
|
+
return;
|
|
4476
|
+
}
|
|
4477
|
+
if (i % FRAC_JUMP_EVERY == 0) { //decide whether to do a jump of modified length (to break cycles)
|
|
4478
|
+
faq = FRAC_JUMPS[(i / FRAC_JUMP_EVERY - 1) % FRAC_JUMP_LEN];
|
|
4479
|
+
newroot = *root - faq*dx; // do jump of semi-random length
|
|
4480
|
+
}
|
|
4481
|
+
*root = newroot;
|
|
4482
|
+
}
|
|
4483
|
+
success = false; // too many iterations here
|
|
4484
|
+
return;
|
|
4485
|
+
}
|
|
4486
|
+
|
|
4487
|
+
void VBBinaryLensing::cmplx_newton_spec(complex *poly, int degree, complex *root, int &iter, bool &success) {
|
|
4488
|
+
//Subroutine finds one root of a complex polynomial
|
|
4489
|
+
//Newton's method. It calculates simplified Adams' stopping
|
|
4490
|
+
//criterion for the value of the polynomial once per 10 iterations (!),
|
|
4491
|
+
//after initial iteration. This is done to speed up calculations
|
|
4492
|
+
//when polishing roots that are known preety well, and stopping
|
|
4493
|
+
// criterion does significantly change in their neighborhood.
|
|
4494
|
+
|
|
4495
|
+
//Uses 'root' value as a starting point (!!!!!)
|
|
4496
|
+
//Remember to initialize 'root' to some initial guess.
|
|
4497
|
+
//Do not initilize 'root' to point (0,0) if the polynomial
|
|
4498
|
+
//coefficients are strictly real, because it will make going
|
|
4499
|
+
//to imaginary roots impossible.
|
|
4500
|
+
|
|
4501
|
+
// poly - is an array of polynomial cooefs
|
|
4502
|
+
// length = degree+1, poly(1) is constant
|
|
4503
|
+
//0 1 2
|
|
4504
|
+
//poly[0] x^0 + poly[1] x^1 + poly[2] x^2 + ...
|
|
4505
|
+
//degree - a degree of the polynomial
|
|
4506
|
+
// root - input: guess for the value of a root
|
|
4507
|
+
// output: a root of the polynomial
|
|
4508
|
+
//iter - number of iterations performed (the number of polynomial evaluations)
|
|
4509
|
+
//success - is false if routine reaches maximum number of iterations
|
|
4510
|
+
|
|
4511
|
+
//For a summary of the method go to:
|
|
4512
|
+
//http://en.wikipedia.org/wiki/Newton's_method
|
|
4513
|
+
|
|
4514
|
+
int FRAC_JUMP_EVERY = 10;
|
|
4515
|
+
const int FRAC_JUMP_LEN = 10;
|
|
4516
|
+
double FRAC_JUMPS[FRAC_JUMP_LEN] = { 0.64109297, 0.91577881, 0.25921289, 0.50487203, 0.08177045, 0.13653241, 0.306162, 0.37794326, 0.04618805, 0.75132137 }; //some random numbers
|
|
4517
|
+
double faq; //jump length
|
|
4518
|
+
double FRAC_ERR = 2e-15;
|
|
4519
|
+
complex p; //value of polynomial
|
|
4520
|
+
complex dp; //value of 1st derivative
|
|
4521
|
+
int i, k;
|
|
4522
|
+
bool good_to_go;
|
|
4523
|
+
complex dx, newroot;
|
|
4524
|
+
double ek, absroot, abs2p;
|
|
4525
|
+
complex zero = complex(0, 0);
|
|
4526
|
+
double stopping_crit2;
|
|
4527
|
+
|
|
4528
|
+
iter = 0;
|
|
4529
|
+
success = true;
|
|
4530
|
+
|
|
4531
|
+
//the next if block is an EXTREME failsafe, not usually needed, and thus turned off in this version
|
|
4532
|
+
if (false) { //change false to true if you would like to use caustion about haveing first coefficient == 0
|
|
4533
|
+
if (degree < 0) {
|
|
4534
|
+
printf("Error: cmplx_newton_spec: degree<0");
|
|
4535
|
+
return;
|
|
4536
|
+
}
|
|
4537
|
+
if (poly[degree] == zero) {
|
|
4538
|
+
if (degree == 0) return;
|
|
4539
|
+
cmplx_newton_spec(poly, degree, root, iter, success);
|
|
4540
|
+
return;
|
|
4541
|
+
}
|
|
4542
|
+
if (degree <= 1) {
|
|
4543
|
+
if (degree == 0) {
|
|
4544
|
+
success = false;
|
|
4545
|
+
printf("Warning: cmplx_newton_spec: degree=0 and poly[0]!=0, no roots");
|
|
4546
|
+
return;
|
|
4547
|
+
}
|
|
4548
|
+
else {
|
|
4549
|
+
*root = -poly[0] / poly[1];
|
|
4550
|
+
return;
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
//end EXTREME Failsafe
|
|
4555
|
+
good_to_go = false;
|
|
4556
|
+
|
|
4557
|
+
stopping_crit2 = 0.0; //value not important, will be initialized anyway on the first loop
|
|
4558
|
+
for (i = 1; i <= MAXIT; i++) {
|
|
4559
|
+
faq = 1.0;
|
|
4560
|
+
//prepare stoping criterion
|
|
4561
|
+
//calculate value of polynomial and its first two derivatives
|
|
4562
|
+
p = poly[degree];
|
|
4563
|
+
dp = zero;
|
|
4564
|
+
if (i % 10 == 1) { //calculate stopping criterion every tenth iteration
|
|
4565
|
+
ek = abs(poly[degree]);
|
|
4566
|
+
absroot = abs(*root);
|
|
4567
|
+
for (k = degree - 1; k >= 0; k--) {
|
|
4568
|
+
dp = p + dp * (*root);
|
|
4569
|
+
p = poly[k] + p * (*root); //b_k
|
|
4570
|
+
//Adams, Duane A., 1967, "A stopping criterion for polynomial root finding",
|
|
4571
|
+
//Communications of ACM, Volume 10 Issue 10, Oct. 1967, p. 655
|
|
4572
|
+
//ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/67/55/CS-TR-67-55.pdf
|
|
4573
|
+
//Eq. 8
|
|
4574
|
+
ek = absroot * ek + abs(p);
|
|
4575
|
+
}
|
|
4576
|
+
stopping_crit2 = pow(FRAC_ERR * ek, 2);
|
|
4577
|
+
}
|
|
4578
|
+
else { // calculate just the value and derivative
|
|
4579
|
+
for (k = degree - 1; k >= 0; k--) { //Horner Scheme, see for eg. Numerical Recipes Sec. 5.3 how to evaluate polynomials and derivatives
|
|
4580
|
+
dp = p + dp * (*root);
|
|
4581
|
+
p = poly[k] + p * (*root);
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
iter = iter + 1;
|
|
4586
|
+
|
|
4587
|
+
abs2p = real(conj(p) * p);
|
|
4588
|
+
if (abs2p == 0.0) return;
|
|
4589
|
+
if (abs2p < stopping_crit2) { //simplified a little Eq. 10 of Adams 1967
|
|
4590
|
+
if (dp == zero) return; //if we have problem with zero, but we are close to the root, just accept
|
|
4591
|
+
//do additional iteration if we are less than 10x from stopping criterion
|
|
4592
|
+
if (abs2p < 0.01 * stopping_crit2) return; //return immediatley because we are at very good place
|
|
4593
|
+
else {
|
|
4594
|
+
good_to_go = true; //do one iteration more
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4598
|
+
else {
|
|
4599
|
+
good_to_go = false; //reset if we are outside the zone of the root
|
|
4600
|
+
}
|
|
4601
|
+
if (dp == zero) {
|
|
4602
|
+
//problem with zero
|
|
4603
|
+
dx = (abs(*root) + 1.0) * expcmplx(complex(0.0, FRAC_JUMPS[i% FRAC_JUMP_LEN] * 2 * M_PI));
|
|
4604
|
+
}
|
|
4605
|
+
else {
|
|
4606
|
+
dx = p / dp; // Newton method, see http://en.wikipedia.org/wiki/Newton's_method
|
|
4607
|
+
}
|
|
4608
|
+
newroot = *root - dx;
|
|
4609
|
+
if (newroot == *root) return; //nothing changes -> return
|
|
4610
|
+
if (good_to_go) {//this was jump already after stopping criterion was met
|
|
4611
|
+
*root = newroot;
|
|
4612
|
+
return;
|
|
4613
|
+
}
|
|
4614
|
+
if (i % FRAC_JUMP_EVERY == 0) { // decide whether to do a jump of modified length (to break cycles)
|
|
4615
|
+
faq = FRAC_JUMPS[(i / FRAC_JUMP_EVERY - 1) % FRAC_JUMP_LEN];
|
|
4616
|
+
newroot = *root - faq * dx;
|
|
4617
|
+
}
|
|
4618
|
+
*root = newroot;
|
|
4619
|
+
}
|
|
4620
|
+
success = false;
|
|
4621
|
+
return;
|
|
4622
|
+
//too many iterations here
|
|
4623
|
+
}
|
|
4624
|
+
|
|
4625
|
+
void VBBinaryLensing::cmplx_laguerre2newton(complex *poly, int degree, complex *root, int &iter, bool &success, int starting_mode) {
|
|
4626
|
+
//Subroutine finds one root of a complex polynomial using
|
|
4627
|
+
//Laguerre's method, Second-order General method and Newton's
|
|
4628
|
+
//method - depending on the value of function F, which is a
|
|
4629
|
+
//combination of second derivative, first derivative and
|
|
4630
|
+
//value of polynomial [F=-(p"*p)/(p'p')].
|
|
4631
|
+
|
|
4632
|
+
//Subroutine has 3 modes of operation. It starts with mode=2
|
|
4633
|
+
//which is the Laguerre's method, and continues until F
|
|
4634
|
+
//becames F<0.50, at which point, it switches to mode=1,
|
|
4635
|
+
//i.e., SG method (see paper). While in the first two
|
|
4636
|
+
//modes, routine calculates stopping criterion once per every
|
|
4637
|
+
//iteration. Switch to the last mode, Newton's method, (mode=0)
|
|
4638
|
+
//happens when becomes F<0.05. In this mode, routine calculates
|
|
4639
|
+
//stopping criterion only once, at the beginning, under an
|
|
4640
|
+
//assumption that we are already very close to the root.
|
|
4641
|
+
//If there are more than 10 iterations in Newton's mode,
|
|
4642
|
+
//it means that in fact we were far from the root, and
|
|
4643
|
+
//routine goes back to Laguerre's method (mode=2).
|
|
4644
|
+
|
|
4645
|
+
//Uses 'root' value as a starting point (!!!!!)
|
|
4646
|
+
//Remember to initialize 'root' to some initial guess or to
|
|
4647
|
+
//point (0,0) if you have no prior knowledge.
|
|
4648
|
+
|
|
4649
|
+
//poly - is an array of polynomial cooefs
|
|
4650
|
+
// 0 1 2
|
|
4651
|
+
// poly[0] x^0 + poly[1] x^1 + poly[2] x^2
|
|
4652
|
+
//degree - a degree of the polynomial
|
|
4653
|
+
//root - input: guess for the value of a root
|
|
4654
|
+
// output: a root of the polynomial
|
|
4655
|
+
//iter - number of iterations performed (the number of polynomial
|
|
4656
|
+
// evaluations and stopping criterion evaluation)
|
|
4657
|
+
//success - is false if routine reaches maximum number of iterations
|
|
4658
|
+
//starting_mode - this should be by default = 2. However if you
|
|
4659
|
+
// choose to start with SG method put 1 instead.
|
|
4660
|
+
// Zero will cause the routine to
|
|
4661
|
+
// start with Newton for first 10 iterations, and
|
|
4662
|
+
// then go back to mode 2.
|
|
4663
|
+
|
|
4664
|
+
//For a summary of the method see the paper: Skowron & Gould (2012)
|
|
4665
|
+
|
|
4666
|
+
int FRAC_JUMP_EVERY = 10;
|
|
4667
|
+
const int FRAC_JUMP_LEN = 10;
|
|
4668
|
+
double FRAC_JUMPS[FRAC_JUMP_LEN] = { 0.64109297, 0.91577881, 0.25921289, 0.50487203, 0.08177045, 0.13653241, 0.306162, 0.37794326, 0.04618805, 0.75132137 }; //some random numbers
|
|
4669
|
+
|
|
4670
|
+
double faq; //jump length
|
|
4671
|
+
double FRAC_ERR = 2.0e-15;
|
|
4672
|
+
|
|
4673
|
+
complex p; //value of polynomial
|
|
4674
|
+
complex dp; //value of 1st derivative
|
|
4675
|
+
complex d2p_half; //value of 2nd derivative
|
|
4676
|
+
int i, j, k;
|
|
4677
|
+
bool good_to_go;
|
|
4678
|
+
//complex G, H, G2;
|
|
4679
|
+
complex denom, denom_sqrt, dx, newroot;
|
|
4680
|
+
double ek, absroot, abs2p, abs2_F_half;
|
|
4681
|
+
complex fac_netwon, fac_extra, F_half, c_one_nth;
|
|
4682
|
+
double one_nth, n_1_nth, two_n_div_n_1;
|
|
4683
|
+
int mode;
|
|
4684
|
+
complex c_one = complex(1, 0);
|
|
4685
|
+
complex zero = complex(0, 0);
|
|
4686
|
+
double stopping_crit2;
|
|
4687
|
+
|
|
4688
|
+
iter = 0;
|
|
4689
|
+
success = true;
|
|
4690
|
+
stopping_crit2 = 0; //value not important, will be initialized anyway on the first loop
|
|
4691
|
+
|
|
4692
|
+
//next if block is an EXTREME failsafe, not usually needed, and thus turned off in this version.
|
|
4693
|
+
if (false) {//change false to true if you would like to use caution about having first coefficent == 0
|
|
4694
|
+
if (degree < 0) {
|
|
4695
|
+
printf("Error: cmplx_laguerre2newton: degree < 0");
|
|
4696
|
+
return;
|
|
4697
|
+
}
|
|
4698
|
+
if (poly[degree] == zero) {
|
|
4699
|
+
if (degree == 0) return;
|
|
4700
|
+
cmplx_laguerre2newton(poly, degree, root, iter, success, starting_mode);
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
if (degree <= 1) {
|
|
4704
|
+
if (degree == 0) {//// we know from previous check that poly[0] not equal zero
|
|
4705
|
+
success = false;
|
|
4706
|
+
printf("Warning: cmplx_laguerre2newton: degree = 0 and poly[0] = 0, no roots");
|
|
4707
|
+
return;
|
|
4708
|
+
}
|
|
4709
|
+
else {
|
|
4710
|
+
*root = -poly[0] / poly[1];
|
|
4711
|
+
return;
|
|
4712
|
+
}
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4715
|
+
//end EXTREME failsafe
|
|
4716
|
+
|
|
4717
|
+
j = 1;
|
|
4718
|
+
good_to_go = false;
|
|
4719
|
+
|
|
4720
|
+
mode = starting_mode; // mode = 2 full laguerre, mode = 1 SG, mode = 0 newton
|
|
4721
|
+
|
|
4722
|
+
for (;;) { //infinite loop, just to be able to come back from newton, if more than 10 iteration there
|
|
4723
|
+
|
|
4724
|
+
////////////
|
|
4725
|
+
///mode 2///
|
|
4726
|
+
////////////
|
|
4727
|
+
|
|
4728
|
+
if (mode >= 2) {//Laguerre's method
|
|
4729
|
+
one_nth = 1.0 / (degree); ///
|
|
4730
|
+
n_1_nth = (degree - 1) * one_nth; ////
|
|
4731
|
+
two_n_div_n_1 = 2.0 / n_1_nth;
|
|
4732
|
+
c_one_nth = complex(one_nth, 0.0);
|
|
4733
|
+
|
|
4734
|
+
for (i = 1; i <= MAXIT; i++) {
|
|
4735
|
+
faq = 1.0;
|
|
4736
|
+
|
|
4737
|
+
//prepare stoping criterion
|
|
4738
|
+
ek = abs(poly[degree]);
|
|
4739
|
+
absroot = abs(*root);
|
|
4740
|
+
//calculate value of polynomial and its first two derivative
|
|
4741
|
+
p = poly[degree];
|
|
4742
|
+
dp = zero;
|
|
4743
|
+
d2p_half = zero;
|
|
4744
|
+
for (k = degree; k >= 1; k--) {//Horner Scheme, see for eg. Numerical Recipes Sec. 5.3 how to evaluate polynomials and derivatives
|
|
4745
|
+
d2p_half = dp + d2p_half * (*root);
|
|
4746
|
+
dp = p + dp * (*root);
|
|
4747
|
+
p = poly[k - 1] + p * (*root); // b_k
|
|
4748
|
+
//Adams, Duane A., 1967, "A stopping criterion for polynomial root finding",
|
|
4749
|
+
//Communications of the ACM, Volume 10 Issue 10, Oct. 1967, p. 655
|
|
4750
|
+
//ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/67/55/CS-TR-67-55.pdf
|
|
4751
|
+
//Eq 8.
|
|
4752
|
+
ek = absroot * ek + abs(p);
|
|
4753
|
+
}
|
|
4754
|
+
abs2p = real(conj(p) * p); // abs(p)
|
|
4755
|
+
iter = iter + 1;
|
|
4756
|
+
if (abs2p == 0) return;
|
|
4757
|
+
|
|
4758
|
+
stopping_crit2 = pow(FRAC_ERR * ek, 2);
|
|
4759
|
+
if (abs2p < stopping_crit2) {//(simplified a little Eq. 10 of Adams 1967)
|
|
4760
|
+
//do additional iteration if we are less than 10x from stopping criterion
|
|
4761
|
+
if (abs2p < 0.01*stopping_crit2) return; // ten times better than stopping criterion
|
|
4762
|
+
//return immediately, because we are at very good place
|
|
4763
|
+
else {
|
|
4764
|
+
good_to_go = true; //do one iteration more
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
else {
|
|
4768
|
+
good_to_go = false; //reset if we are outside the zone of the root
|
|
4769
|
+
}
|
|
4770
|
+
|
|
4771
|
+
denom = zero;
|
|
4772
|
+
if (dp != zero) {
|
|
4773
|
+
fac_netwon = p / dp;
|
|
4774
|
+
fac_extra = d2p_half / dp;
|
|
4775
|
+
F_half = fac_netwon * fac_extra;
|
|
4776
|
+
|
|
4777
|
+
abs2_F_half = real(conj(F_half) * F_half);
|
|
4778
|
+
if (abs2_F_half <= 0.0625) {//F<0.50, F/2<0.25
|
|
4779
|
+
//go to SG method
|
|
4780
|
+
if (abs2_F_half <= 0.000625) {//F<0.05, F/2<0.02
|
|
4781
|
+
mode = 0; //go to Newton's
|
|
4782
|
+
}
|
|
4783
|
+
else {
|
|
4784
|
+
mode = 1; //go to SG
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4787
|
+
|
|
4788
|
+
denom_sqrt = sqrt(c_one - two_n_div_n_1*F_half);
|
|
4789
|
+
|
|
4790
|
+
//NEXT LINE PROBABLY CAN BE COMMENTED OUT
|
|
4791
|
+
if (real(denom_sqrt) > 0.0) {
|
|
4792
|
+
//real part of a square root is positive for probably all compilers. You can \F9
|
|
4793
|
+
//test this on your compiler and if so, you can omit this check
|
|
4794
|
+
denom = c_one_nth + n_1_nth * denom_sqrt;
|
|
4795
|
+
}
|
|
4796
|
+
else {
|
|
4797
|
+
denom = c_one_nth - n_1_nth * denom_sqrt;
|
|
4798
|
+
}
|
|
4799
|
+
}
|
|
4800
|
+
if (denom == zero) {//test if demoninators are > 0.0 not to divide by zero
|
|
4801
|
+
dx = (abs(*root) + 1.0) + expcmplx(complex(0.0, FRAC_JUMPS[i% FRAC_JUMP_LEN] * 2 * M_PI)); //make some random jump
|
|
4802
|
+
}
|
|
4803
|
+
else {
|
|
4804
|
+
dx = fac_netwon / denom;
|
|
4805
|
+
}
|
|
4806
|
+
newroot = *root - dx;
|
|
4807
|
+
if (newroot == *root) return; // nothing changes -> return
|
|
4808
|
+
if (good_to_go) {//this was jump already after stopping criterion was met
|
|
4809
|
+
*root = newroot;
|
|
4810
|
+
return;
|
|
4811
|
+
}
|
|
4812
|
+
if (mode != 2) {
|
|
4813
|
+
*root = newroot;
|
|
4814
|
+
j = i + 1; //remember iteration index
|
|
4815
|
+
break; //go to Newton's or SG
|
|
4816
|
+
}
|
|
4817
|
+
if ((i% FRAC_JUMP_EVERY) == 0) {//decide whether to do a jump of modified length (to break cycles)
|
|
4818
|
+
faq = FRAC_JUMPS[((i / FRAC_JUMP_EVERY - 1) % FRAC_JUMP_LEN)];
|
|
4819
|
+
newroot = *root - faq * dx; // do jump of some semi-random length (0 < faq < 1)
|
|
4820
|
+
}
|
|
4821
|
+
*root = newroot;
|
|
4822
|
+
} //do mode 2
|
|
4823
|
+
|
|
4824
|
+
if (i >= MAXIT) {
|
|
4825
|
+
success = false;
|
|
4826
|
+
return;
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4830
|
+
////////////
|
|
4831
|
+
///mode 1///
|
|
4832
|
+
////////////
|
|
4833
|
+
|
|
4834
|
+
if (mode == 1) {//SECOND-ORDER GENERAL METHOD (SG)
|
|
4835
|
+
|
|
4836
|
+
for (i = j; i <= MAXIT; i++) {
|
|
4837
|
+
faq = 1.0;
|
|
4838
|
+
//calculate value of polynomial and its first two derivatives
|
|
4839
|
+
p = poly[degree];
|
|
4840
|
+
dp = zero;
|
|
4841
|
+
d2p_half = zero;
|
|
4842
|
+
if ((i - j) % 10 == 0) {
|
|
4843
|
+
//prepare stopping criterion
|
|
4844
|
+
ek = abs(poly[degree]);
|
|
4845
|
+
absroot = abs(*root);
|
|
4846
|
+
for (k = degree; k >= 1; k--) {//Horner Scheme, see for eg. Numerical Recipes Sec. 5.3 how to evaluate polynomials and derivatives
|
|
4847
|
+
d2p_half = dp + d2p_half * (*root);
|
|
4848
|
+
dp = p + dp * (*root);
|
|
4849
|
+
p = poly[k - 1] + p * (*root); //b_k
|
|
4850
|
+
//Adams, Duane A., 1967, "A stopping criterion for polynomial root finding",
|
|
4851
|
+
//Communications of the ACM, Volume 10 Issue 10, Oct. 1967, p. 655
|
|
4852
|
+
//ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/67/55/CS-TR-67-55.pdf
|
|
4853
|
+
//Eq 8.
|
|
4854
|
+
ek = absroot * ek + abs(p);
|
|
4855
|
+
}
|
|
4856
|
+
stopping_crit2 = pow(FRAC_ERR*ek, 2);
|
|
4857
|
+
}
|
|
4858
|
+
else {
|
|
4859
|
+
for (k = degree; k >= 1; k--) {//Horner Scheme, see for eg. Numerical Recipes Sec. 5.3 how to evaluate polynomials and derivatives
|
|
4860
|
+
d2p_half = dp + d2p_half * (*root);
|
|
4861
|
+
dp = p + dp * (*root);
|
|
4862
|
+
p = poly[k - 1] + p * (*root); //b_k
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
abs2p = real(conj(p) * p); //abs(p)**2
|
|
4866
|
+
iter = iter + 1;
|
|
4867
|
+
if (abs2p == 0.0) return;
|
|
4868
|
+
|
|
4869
|
+
if (abs2p < stopping_crit2) {//(simplified a little Eq. 10 of Adams 1967)
|
|
4870
|
+
if (dp == zero) return;
|
|
4871
|
+
//do additional iteration if we are less than 10x from stopping criterion
|
|
4872
|
+
if (abs2p < 0.01*stopping_crit2) return; //ten times better than stopping criterion
|
|
4873
|
+
//ten times better than stopping criterion
|
|
4874
|
+
else {
|
|
4875
|
+
good_to_go = true; //do one iteration more
|
|
4876
|
+
}
|
|
4877
|
+
}
|
|
4878
|
+
else {
|
|
4879
|
+
good_to_go = false; //reset if we are outside the zone of the root
|
|
4880
|
+
}
|
|
4881
|
+
if (dp == zero) {//test if denominators are > 0.0 not to divide by zero
|
|
4882
|
+
dx = (abs(*root) + 1.0) * expcmplx(complex(0.0, FRAC_JUMPS[i% FRAC_JUMP_LEN] * 2 * M_PI)); //make some random jump
|
|
4883
|
+
}
|
|
4884
|
+
else {
|
|
4885
|
+
fac_netwon = p / dp;
|
|
4886
|
+
fac_extra = d2p_half / dp;
|
|
4887
|
+
F_half = fac_netwon * fac_extra;
|
|
4888
|
+
|
|
4889
|
+
abs2_F_half = real(conj(F_half) * F_half);
|
|
4890
|
+
if (abs2_F_half <= 0.000625) {//F<0.05, F/2<0.025
|
|
4891
|
+
mode = 0; //set Newton's, go there after jump
|
|
4892
|
+
}
|
|
4893
|
+
dx = fac_netwon * (c_one + F_half); //SG
|
|
4894
|
+
}
|
|
4895
|
+
newroot = *root - dx;
|
|
4896
|
+
if (newroot == *root) return; //nothing changes -> return
|
|
4897
|
+
if (good_to_go) {
|
|
4898
|
+
*root = newroot; //this was jump already after stopping criterion was met
|
|
4899
|
+
return;
|
|
4900
|
+
}
|
|
4901
|
+
if (mode != 1) {
|
|
4902
|
+
*root = newroot;
|
|
4903
|
+
j = i + 1; //remember iteration number
|
|
4904
|
+
break; //go to Newton's
|
|
4905
|
+
}
|
|
4906
|
+
if ((i% FRAC_JUMP_EVERY) == 0) {// decide whether to do a jump of modified length (to break cycles)
|
|
4907
|
+
faq = FRAC_JUMPS[(i / FRAC_JUMP_EVERY - 1) % FRAC_JUMP_LEN];
|
|
4908
|
+
newroot = *root - faq * dx; //do jump of some semi random lenth (0 < faq < 1)
|
|
4909
|
+
}
|
|
4910
|
+
*root = newroot;
|
|
4911
|
+
}
|
|
4912
|
+
if (i >= MAXIT) {
|
|
4913
|
+
success = false;
|
|
4914
|
+
return;
|
|
4915
|
+
}
|
|
4916
|
+
|
|
4917
|
+
}
|
|
4918
|
+
//------------------------------------------------------------------------------- mode 0
|
|
4919
|
+
if (mode == 0) { // Newton's Method
|
|
4920
|
+
|
|
4921
|
+
for (i = j; i <= j + 10; i++) { // Do only 10 iterations the most then go back to Laguerre
|
|
4922
|
+
faq = 1.0;
|
|
4923
|
+
|
|
4924
|
+
//calc polynomial and first two derivatives
|
|
4925
|
+
p = poly[degree];
|
|
4926
|
+
dp = zero;
|
|
4927
|
+
if (i == j) { // Calculating stopping criterion only at the beginning
|
|
4928
|
+
ek = abs(poly[degree]);
|
|
4929
|
+
absroot = abs(*root);
|
|
4930
|
+
for (k = degree; k >= 1; k--) {
|
|
4931
|
+
dp = p + dp*(*root);
|
|
4932
|
+
p = poly[k - 1] + p*(*root);
|
|
4933
|
+
ek = absroot*ek + abs(p);
|
|
4934
|
+
}
|
|
4935
|
+
stopping_crit2 = pow(FRAC_ERR*ek, 2.0);
|
|
4936
|
+
}
|
|
4937
|
+
else {
|
|
4938
|
+
for (k = degree; k >= 1; k--) {
|
|
4939
|
+
dp = p + dp*(*root);
|
|
4940
|
+
p = poly[k - 1] + p*(*root);
|
|
4941
|
+
}
|
|
4942
|
+
}
|
|
4943
|
+
abs2p = real(conj(p)*p);
|
|
4944
|
+
iter = iter + 1;
|
|
4945
|
+
if (abs2p == 0.0) return;
|
|
4946
|
+
|
|
4947
|
+
if (abs2p < stopping_crit2) {
|
|
4948
|
+
if (dp == zero) return;
|
|
4949
|
+
// do additional iteration if we are less than 10x from stopping criterion
|
|
4950
|
+
if (abs2p < 0.01*stopping_crit2) {
|
|
4951
|
+
return; // return immediately since we are at a good place
|
|
4952
|
+
}
|
|
4953
|
+
else {
|
|
4954
|
+
good_to_go = true; // do one more iteration
|
|
4955
|
+
}
|
|
4956
|
+
}
|
|
4957
|
+
else {
|
|
4958
|
+
good_to_go = false;
|
|
4959
|
+
}
|
|
4960
|
+
|
|
4961
|
+
if (dp == zero) {
|
|
4962
|
+
dx = (abs(*root) + 1.0)*expcmplx(complex(0.0, 2 * M_PI*FRAC_JUMPS[i % FRAC_JUMP_LEN])); // make a random jump
|
|
4963
|
+
}
|
|
4964
|
+
else {
|
|
4965
|
+
dx = p / dp;
|
|
4966
|
+
}
|
|
4967
|
+
|
|
4968
|
+
newroot = *root - dx;
|
|
4969
|
+
if (newroot == *root) return;
|
|
4970
|
+
if (good_to_go) {
|
|
4971
|
+
*root = newroot;
|
|
4972
|
+
return;
|
|
4973
|
+
}
|
|
4974
|
+
*root = newroot;
|
|
4975
|
+
}
|
|
4976
|
+
if (iter >= MAXIT) {
|
|
4977
|
+
//too many iterations
|
|
4978
|
+
success = false;
|
|
4979
|
+
return;
|
|
4980
|
+
}
|
|
4981
|
+
mode = 2; //go back to Laguerre's. Happens when could not converge with 10 steps of Newton
|
|
4982
|
+
}
|
|
4983
|
+
|
|
4984
|
+
}/// end of infinite loop
|
|
4985
|
+
}
|
|
4986
|
+
|