gsl_matrix* ok_periodogram_full(ok_kernel* k, int type, int algo, bool circular, unsigned int sample, const unsigned int samples, const double Pmin, const double Pmax) { k = K_clone(k); K_calculate(k); // Input data for LS periodogram gsl_matrix* data = ok_buf_to_matrix(K_compileData(k), K_getNdata(k), DATA_SIZE); if (type == PS_TYPE_RESIDUALS) { // If residuals periodogram, subtract signal from data for (int i = 0; i < data->size1; i++) MSET(data, i, T_SVAL, MGET(data, i, T_SVAL) - MGET(data, i, T_PRED)); } else if (type == PS_TYPE_DATA) { // If full periodogram, then start with no planets K_removePlanet(k, -1); } // Calculate LS periodogram gsl_matrix* ret = ok_periodogram_ls(data, samples, Pmin, Pmax, 0, T_TIME, T_SVAL, T_ERR, NULL); int np = K_getNplanets(k) + 1; // Number of minimizable offsets int no = 0; for (int i = 0; i < DATA_SETS_SIZE; i++) if (VIGET(k->parFlags, i) & MINIMIZE) { no++; } // Calculate baseline chi^2 (Chi^2_H) double Chi2_H = _kminimize(k, algo); // Normalizing factor for power double nd = 0.5 * (K_getNdata(k) - no); #pragma omp parallel for for (int r = 0; r < samples; r++) { double P = MGET(ret, r, PS_TIME); double K = sqrt(MGET(ret, r, PS_Z)); ok_kernel* k2 = K_clone(k); K_calculate(k2); double args[] = {PER, P, DONE}; K_addPlanet(k2, args); K_setElement(k2, np, SEMIAMP, K); K_setElementFlag(k2, np, PER, ACTIVE); if (circular) { K_setElementFlag(k2, np, ECC, ACTIVE); K_setElementFlag(k2, np, LOP, ACTIVE); } double Chi2_K = _kminimize(k2, algo); double z = nd * (Chi2_H - Chi2_K) / Chi2_H; MSET(ret, r, PS_Z, z); fflush(stdout); } return ret; }
int K_minimize_lm(ok_kernel* k, int maxiter, double params[]) { double min_chi_par = 1e-4; K_calculate(k); double prev_chi2 = k->chi2; bool high_df = false; int max_iter_at_scale = 200; double initial_st = 1.; int max_kt = 1; for (int i = 0; i < k->ndata; i++) if (k->compiled[i][T_FLAG] == T_TIMING) { high_df = true; max_kt = 2; max_iter_at_scale = 500; break; } if (params != NULL) { int i = 0; while (true) { if (params[i] == DONE) break; if (params[i] == OPT_LM_MINCHI_PAR) min_chi_par = params[i+1]; else if (params[i] == OPT_LM_HIGH_DF) high_df = !((int) params[i+1] == 0); else if (params[i] == OPT_LM_MAX_ITER_AT_SCALE) max_iter_at_scale = (int) params[i+1]; else if (params[i] == OPT_LM_INITIAL_SCALE) initial_st = params[i+1]; i+=2; } } unsigned int npars = 0; // Count all the parameters to minimize on for (int i = 1; i < k->system->nplanets + 1; i++) for (int j = 0; j < ELEMENTS_SIZE; j++) npars += (MIGET(k->plFlags, i, j) & MINIMIZE ? 1 : 0); for (int i = 0; i < k->parFlags->size; i++) npars += (VIGET(k->parFlags, i) & MINIMIZE ? 1 : 0); if (npars == 0) return 0; // Create a pointer table (flat array -> matrices) double** pars = (double**) malloc(sizeof(double*) * npars); double prevpars[npars]; double* steps = (double*) malloc(npars * sizeof(double)); double* stepscale = (double*) malloc(npars * sizeof(double)); int* parstype = (int*) malloc(npars * sizeof(int)); gsl_vector* x = gsl_vector_alloc(npars); int idx = 0; for (int i = 1; i < k->system->nplanets + 1; i++) for (int j = 0; j < ELEMENTS_SIZE; j++) if (MIGET(k->plFlags, i, j) & MINIMIZE) { pars[idx] = gsl_matrix_ptr(k->system->elements, i, j); x->data[idx] = MGET(k->system->elements, i, j); prevpars[idx] = x->data[idx]; steps[idx] = stepscale[idx] = MGET(k->plSteps, i, j); parstype[idx] = j; if (steps[idx] < 1e-10) { printf("Warning: step for element %d of planet %d is <= 0\n", j, i); } idx++; } for (int i = 0; i < k->parFlags->size; i++) if (VIGET(k->parFlags, i) & MINIMIZE) { pars[idx] = gsl_vector_ptr(k->params, i); x->data[idx] = VGET(k->params, i); prevpars[idx] = x->data[idx]; steps[idx] = stepscale[idx] = VGET(k->parSteps, i); parstype[idx] = PARTYPE_PAR; if (steps[idx] < 1e-10) printf("Warning: step for parameter %d is <= 0\n", i); idx++; } gsl_multifit_fdfsolver * s = gsl_multifit_fdfsolver_alloc (gsl_multifit_fdfsolver_lmsder, k->ndata, npars); ok_lm_params sp; sp.k = k; sp.pars = pars; sp.best = (double*) malloc(sizeof(double) * npars); sp.stepscale = stepscale; sp.compiled = k->compiled; sp.f0 = (double*) malloc(sizeof(double)*k->ndata); sp.f1 = (double*) malloc(sizeof(double)*k->ndata); sp.f2 = (double*) malloc(sizeof(double)*k->ndata); sp.f3 = (double*) malloc(sizeof(double)*k->ndata); sp.parstype = parstype; sp.ndata = k->ndata; sp.iterations = 0; sp.maxiterations = maxiter; sp.npars = npars; sp.every = (k->intMethod == KEPLER ? 10 : 1); sp.status = PROGRESS_CONTINUE; sp.high_df = high_df; sp.min_chi = k->chi2; sp.st = initial_st; for (int i = 0; i < npars; i++) sp.best[i] = *(pars[i]); gsl_multifit_function_fdf fdf; fdf.f = &K_lm_f; fdf.df = &K_lm_jac; fdf.fdf = &K_lm_fdf; fdf.n = k->ndata; fdf.p = npars; fdf.params = &sp; gsl_multifit_fdfsolver_set (s, &fdf, x); bool improved = true; int status = 0; int kt = 0; int tot_iter = 0; int iter_at_scale = 0; bool last_ditch = false; while (improved || last_ditch) { k->flags |= NEEDS_SETUP; iter_at_scale = 0; while (true) { double chi2 = sp.min_chi; int status = gsl_multifit_fdfsolver_iterate (s); iter_at_scale++; tot_iter++; if (chi2 - sp.min_chi > min_chi_par) iter_at_scale = 0; if (status || iter_at_scale > max_iter_at_scale) { break; } } gsl_multifit_fdfsolver_set (s, &fdf, x); for (int i = 0; i < npars; i++) { *(pars[i]) = sp.best[i]; x->data[i] = sp.best[i]; } k->flags |= NEEDS_SETUP; K_calculate(k); if (fabs(prev_chi2 - sp.min_chi)/fabs(sp.min_chi) > 1e-2 && iter_at_scale > 1) { kt = 0; last_ditch = false; } else { sp.st *= 0.1; } improved = (kt < max_kt || fabs(sp.min_chi - prev_chi2)/fabs(sp.min_chi) > 1e-2); if (last_ditch) break; if (! improved && kt <= 3) { last_ditch = true; sp.st *= 0.1; } kt++; //printf("-> %d %d %d %e %e, last_ditch=%d\n", iter_at_scale, kt, improved, sp.st, sp.min_chi, last_ditch); prev_chi2 = k->chi2; for (int idx = 0; idx < npars; idx++) stepscale[idx] = steps[idx] * sp.st; if (sp.iterations > maxiter || sp.st < 1e-12) break; } for (int i = 0; i < npars; i++) { *(pars[i]) = sp.best[i]; x->data[i] = sp.best[i]; } k->flags |= NEEDS_SETUP; K_calculate(k); free(sp.stepscale); free(sp.f0); free(sp.f1); free(sp.f2); free(sp.f3); free(sp.pars); free(sp.parstype); free(sp.best); if (sp.status == PROGRESS_STOP) return PROGRESS_STOP; else return status; }