void THD_generic_detrend_LSQ( int npt, float *far , int polort, int nort, float **ort , float *fit ) { int ii,jj , nref ; float **ref , *qfit , xmid , xfac , val ; /* check inputs */ if( npt <= 1 || far == NULL ) return ; if( nort > 0 ){ if( ort == NULL ) return ; for( jj=0 ; jj < nort ; jj++ ) if( ort[jj] == NULL ) return ; } if( polort < 0 ) polort = -1 ; if( nort < 0 ) nort = 0 ; nref = polort+1+nort ; if( nref <= 0 || nref >= npt-1 ) return ; /* assemble all reference vectors */ ref = (float **) malloc( sizeof(float *) * nref ) ; xmid = 0.5*(npt-1) ; xfac = 1.0 / xmid ; for( jj=0 ; jj <= polort ; jj++ ){ ref[jj] = (float *) malloc( sizeof(float) * npt ) ; for( ii=0 ; ii < npt ; ii++ ) ref[jj][ii] = (float)Plegendre(xfac*(ii-xmid),jj) ; } for( jj=0 ; jj < nort ; jj++ ) /* user supplied refs */ ref[polort+1+jj] = ort[jj] ; qfit = lsqfit( npt , far , NULL , nref , ref ) ; /* actual fitting */ if( qfit != NULL ){ /* good */ for( ii=0 ; ii < npt ; ii++ ){ val = far[ii] ; for( jj=0 ; jj < nref ; jj++ ) val -= qfit[jj] * ref[jj][ii] ; far[ii] = val ; } if( fit != NULL ){ for( ii=0 ; ii < nref ; ii++ ) fit[ii] = qfit[ii] ; } free(qfit) ; } else { ERROR_message("THD_generic_detrend_LSQ: fit fails - no detrending!") ; if( fit != NULL ) memset(fit,0,sizeof(float)*nref) ; } for( jj=0 ; jj <= polort ; jj++ ) free(ref[jj]) ; free(ref) ; return ; }
void exec( ) throw( general_error ) { size_t i, j, nrows, ncols; // rated output ac double Paco = as_double("inv_cec_cg_paco"); bool kW_units = (as_integer("inv_cec_cg_sample_power_units") == 1); // 6 columns period, tier, max usage, max usage units, buy, sell ssc_number_t *inv_cec_cg_test_samples_in = as_matrix("inv_cec_cg_test_samples", &nrows, &ncols); if (nrows != 18) { std::ostringstream ss; ss << "The samples table must have 18 rows. Number of rows in samples table provided is " << nrows << " rows."; throw exec_error("inv_cec_cg", ss.str()); } if ((ncols % 3) != 0) { std::ostringstream ss; ss << "The samples table must have number of columns divisible by 3. Number of columns in samples table provided is " << ncols << " columns."; throw exec_error("inv_cec_cg", ss.str()); } size_t num_samples = ncols / 3; size_t columns_per_sample = 3; util::matrix_t<float> inv_cec_cg_test_samples(nrows, ncols); inv_cec_cg_test_samples.assign(inv_cec_cg_test_samples_in, nrows, ncols); ssc_number_t vdc = 0, Pout = 0, eff = 0, Pin=0, Pin2=0; // set Pout, Pin=Pout/eff and Pin^2 for least squares fit // 6 is for the required power output percentages at each voltage for each sample util::matrix_t<ssc_number_t> &inv_cec_cg_Vmin = allocate_matrix("inv_cec_cg_Vmin", 6 * num_samples, 3); util::matrix_t<ssc_number_t> &inv_cec_cg_Vnom = allocate_matrix("inv_cec_cg_Vnom", 6 * num_samples, 3); util::matrix_t<ssc_number_t> &inv_cec_cg_Vmax = allocate_matrix("inv_cec_cg_Vmax", 6 * num_samples, 3); ssc_number_t *inv_cec_cg_Vdc = allocate("inv_cec_cg_Vdc", 3); ssc_number_t *inv_cec_cg_Vdc_Vnom = allocate("inv_cec_cg_Vdc_Vnom", 3); ssc_number_t *inv_cec_cg_Pdco = allocate("inv_cec_cg_Pdco", 3); ssc_number_t *inv_cec_cg_Psco = allocate("inv_cec_cg_Psco", 3); ssc_number_t *inv_cec_cg_C0 = allocate("inv_cec_cg_C0", 3); ssc_number_t *inv_cec_cg_C1 = allocate("inv_cec_cg_C1", 2); ssc_number_t *inv_cec_cg_C2 = allocate("inv_cec_cg_C2", 2); ssc_number_t *inv_cec_cg_C3 = allocate("inv_cec_cg_C3", 2); for (i = 0; i < 3; i++) inv_cec_cg_Vdc[i] = 0; for (j = 0; j < num_samples; j++) { for (i = 0; i < inv_cec_cg_test_samples.nrows(); i++) { vdc = inv_cec_cg_test_samples.at(i, j*columns_per_sample + 1); Pout = inv_cec_cg_test_samples.at(i, j*columns_per_sample); if (kW_units) Pout *= 1000; // kW to W eff = inv_cec_cg_test_samples.at(i, j*columns_per_sample+2); Pin = Pout; if (eff != 0.0f) Pin = (ssc_number_t)(100.0*Pout) / eff; Pin2 = Pin*Pin; if (i < 6) // Vmin 0 offset { inv_cec_cg_Vdc[0] += vdc; inv_cec_cg_Vmin.at(j * 6 + i, 0) = Pout; inv_cec_cg_Vmin.at(j * 6 + i, 1) = Pin; inv_cec_cg_Vmin.at(j * 6 + i, 2) = Pin2; } else if (i < 12) // Vnom 6 offset { inv_cec_cg_Vdc[1] += vdc; inv_cec_cg_Vnom.at(j * 6 + i - 6, 0) = Pout; inv_cec_cg_Vnom.at(j * 6 + i-6, 1) = Pin; inv_cec_cg_Vnom.at(j * 6 + i-6, 2) = Pin2; } else // Vmax 12 offset { inv_cec_cg_Vdc[2] += vdc; inv_cec_cg_Vmax.at(j * 6 + i - 12, 0) = Pout; inv_cec_cg_Vmax.at(j * 6 + i - 12, 1) = Pin; inv_cec_cg_Vmax.at(j * 6 + i - 12, 2) = Pin2; } } } ssc_number_t *inv_cec_cg_Vmin_abc = allocate("inv_cec_cg_Vmin_abc", 3); ssc_number_t *inv_cec_cg_Vnom_abc = allocate("inv_cec_cg_Vnom_abc", 3); ssc_number_t *inv_cec_cg_Vmax_abc = allocate("inv_cec_cg_Vmax_abc", 3); std::vector<double> Pout_vec(inv_cec_cg_Vmin.nrows()); std::vector<double> Pin_vec(inv_cec_cg_Vmin.nrows()); int info; double C[3];// initial guesses for lsqfit size_t data_size = 3; // Vmin non-linear for (i = 0; i < inv_cec_cg_Vmin.nrows(); i++) { Pin_vec[i] = inv_cec_cg_Vmin.at(i, 1); Pout_vec[i] = inv_cec_cg_Vmin.at(i, 0); } C[0] = -1e-6; C[1] = 1; C[2] = 1e3; if (!(info=lsqfit(Quadratic_fit_eqn, 0, C, data_size, &Pin_vec[0], &Pout_vec[0], inv_cec_cg_Vmin.nrows()))) { throw exec_error("inv_cec_cg", util::format("error in nonlinear least squares fit, error %d", info)); return; } inv_cec_cg_Vmin_abc[0] = (ssc_number_t)C[0]; inv_cec_cg_Vmin_abc[1] = (ssc_number_t)C[1]; inv_cec_cg_Vmin_abc[2] = (ssc_number_t)C[2]; // Vnom non-linear for (i = 0; i < inv_cec_cg_Vnom.nrows(); i++) { Pin_vec[i] = inv_cec_cg_Vnom.at(i, 1); Pout_vec[i] = inv_cec_cg_Vnom.at(i, 0); } C[0] = -1e-6; C[1] = 1; C[2] = 1e3; if (!(info = lsqfit(Quadratic_fit_eqn, 0, C, data_size, &Pin_vec[0], &Pout_vec[0], inv_cec_cg_Vnom.nrows()))) { throw exec_error("inv_cec_cg", util::format("error in nonlinear least squares fit, error %d", info)); return; } inv_cec_cg_Vnom_abc[0] = (ssc_number_t)C[0]; inv_cec_cg_Vnom_abc[1] = (ssc_number_t)C[1]; inv_cec_cg_Vnom_abc[2] = (ssc_number_t)C[2]; // Vmax non-linear for (i = 0; i < inv_cec_cg_Vmax.nrows(); i++) { Pin_vec[i] = inv_cec_cg_Vmax.at(i, 1); Pout_vec[i] = inv_cec_cg_Vmax.at(i, 0); } C[0] = -1e-6; C[1] = 1; C[2] = 1e3; if (!(info = lsqfit(Quadratic_fit_eqn, 0, C, data_size, &Pin_vec[0], &Pout_vec[0], inv_cec_cg_Vmax.nrows()))) { throw exec_error("inv_cec_cg", util::format("error in nonlinear least squares fit, error %d", info)); return; } inv_cec_cg_Vmax_abc[0] = (ssc_number_t)C[0]; inv_cec_cg_Vmax_abc[1] = (ssc_number_t)C[1]; inv_cec_cg_Vmax_abc[2] = (ssc_number_t)C[2]; // Fill in intermediate values //Vdc (Vmin, Vnom, Vmax) for (i = 0; i < 3;i++) inv_cec_cg_Vdc[i] /= (6 * num_samples); // Vdc-Vnom for (i = 0; i < 3; i++) inv_cec_cg_Vdc_Vnom[i] = inv_cec_cg_Vdc[i] - inv_cec_cg_Vdc[1]; ssc_number_t a, b, c; // Pdco and Psco and C0 a = inv_cec_cg_Vmin_abc[0]; b = inv_cec_cg_Vmin_abc[1]; c = inv_cec_cg_Vmin_abc[2]; inv_cec_cg_Pdco[0] = (ssc_number_t)(-b + sqrt(b*b - 4 * a*(c - Paco))); inv_cec_cg_Psco[0] = (-b + sqrt(b*b - 4 * a*c)); inv_cec_cg_C0[0] = a; if (a != 0) { inv_cec_cg_Pdco[0] /= (ssc_number_t)(2.0*a); inv_cec_cg_Psco[0] /= (ssc_number_t)(2.0*a); } a = inv_cec_cg_Vnom_abc[0]; b = inv_cec_cg_Vnom_abc[1]; c = inv_cec_cg_Vnom_abc[2]; inv_cec_cg_Pdco[1] = (ssc_number_t)(-b + sqrt(b*b - 4 * a*(c - Paco))); inv_cec_cg_Psco[1] = (-b + sqrt(b*b - 4 * a*c)); inv_cec_cg_C0[1] = a; if (a != 0) { inv_cec_cg_Pdco[1] /= (ssc_number_t)(2.0*a); inv_cec_cg_Psco[1] /= (ssc_number_t)(2.0*a); } // TODO - limit Psco max to not be less than zero per note in Workbook a = inv_cec_cg_Vmax_abc[0]; b = inv_cec_cg_Vmax_abc[1]; c = inv_cec_cg_Vmax_abc[2]; inv_cec_cg_Pdco[2] = (ssc_number_t)(-b + sqrt(b*b - 4 * a*(c - Paco))); inv_cec_cg_Psco[2] = (-b + sqrt(b*b - 4 * a*c)); inv_cec_cg_C0[2] = a; if (a != 0) { inv_cec_cg_Pdco[2] /= (ssc_number_t)(2.0*a); inv_cec_cg_Psco[2] /= (ssc_number_t)(2.0*a); } // C1, C2, C3 linear least squares // C1 Y=Pdco, X=Vdc-Vnom std::vector<double> X(3); std::vector<double> Y(3); double slope, intercept; // C1 using linear least squares fit for (i = 0; i < 3; i++) { X[i] = inv_cec_cg_Vdc_Vnom[i]; Y[i] = inv_cec_cg_Pdco[i]; } if ((info = linlsqfit(&slope, &intercept, &X[0], &Y[0], data_size))) { throw exec_error("inv_cec_cg", util::format("error in linear least squares fit, error %d", info)); return; } inv_cec_cg_C1[0] = (ssc_number_t)slope; inv_cec_cg_C1[1] = (ssc_number_t)intercept; // C2 using linear least squares fit for (i = 0; i < 3; i++) { X[i] = inv_cec_cg_Vdc_Vnom[i]; Y[i] = inv_cec_cg_Psco[i]; } if ((info = linlsqfit(&slope, &intercept, &X[0], &Y[0], data_size))) { throw exec_error("inv_cec_cg", util::format("error in linear least squares fit, error %d", info)); return; } inv_cec_cg_C2[0] = (ssc_number_t)slope; inv_cec_cg_C2[1] = (ssc_number_t)intercept; // C2 using linear least squares fit for (i = 0; i < 3; i++) { X[i] = inv_cec_cg_Vdc_Vnom[i]; Y[i] = inv_cec_cg_C0[i]; } if ((info = linlsqfit(&slope, &intercept, &X[0], &Y[0], data_size))) { throw exec_error("inv_cec_cg", util::format("error in linear least squares fit, error %d", info)); return; } inv_cec_cg_C3[0] = (ssc_number_t)slope; inv_cec_cg_C3[1] = (ssc_number_t)intercept; // vdco is the average of Vnom of all samples column 2 and rows 7 through 12 assign("Pdco", (var_data)inv_cec_cg_C1[1]); assign("Vdco", (var_data)inv_cec_cg_Vdc[1]); assign("Pso", (var_data)inv_cec_cg_C2[1]); assign("c0", (var_data)inv_cec_cg_C3[1]); assign("c1", (var_data)(inv_cec_cg_C1[0] / inv_cec_cg_C1[1])); assign("c2", (var_data)(inv_cec_cg_C2[0] / inv_cec_cg_C2[1])); assign("c3", (var_data)(inv_cec_cg_C3[0] / inv_cec_cg_C3[1])); }
float * mri_lsqfit( MRI_IMAGE * fitim , MRI_IMARR * refim , MRI_IMAGE * wtim ) { float *fit = NULL ; /* will be the output */ MRI_IMAGE *ffitim , *tim , *wim ; /* local versions of inputs */ MRI_IMARR *frefim ; int ii , jj , npix,nref ; float **refar , *fitar , *war ; ENTRY("mri_lsqfit") ; /****---- check inputs, convert to float type if needed ----****/ if( fitim == NULL ){ ERROR_message("mri_lsqfit has NULL fitim"); RETURN(NULL); } if( fitim->kind == MRI_float ) ffitim = fitim ; else ffitim = mri_to_float( fitim ) ; npix = ffitim->nvox ; fitar = mri_data_pointer(ffitim) ; if( wtim == NULL ){ wim = NULL ; war = NULL ; } else if( wtim->kind == MRI_float ){ wim = wtim ; war = mri_data_pointer( wim ) ; if( wim->nvox != npix ){ ERROR_message("mri_lsqfit: MISMATCH wtim->nvox=%d npix=%d", wtim->nvox , npix ); RETURN(NULL); } } else { wim = mri_to_float( wtim ) ; war = mri_data_pointer( wim ) ; if( wim->nvox != npix ){ ERROR_message("mri_lsqfit: MISMATCH wtim->nvox=%d npix=%d", wtim->nvox , npix ); RETURN(NULL); } } if( refim == NULL || refim->num < 1 ){ ERROR_message("mri_lsqfit: NULL refim"); RETURN(NULL); } nref = refim->num ; INIT_IMARR(frefim) ; refar = (float **) malloc( sizeof(float *) * nref ) ; if( refar == NULL ){ fprintf(stderr,"** mri_lsqfit: malloc failure for refar"); RETURN(NULL); } for( ii=0 ; ii < nref ; ii++ ){ if( refim->imarr[ii] == NULL ){ ERROR_message("mri_lsqfit: NULL refim[%d]!",ii); RETURN(NULL); } if( refim->imarr[ii]->nvox != npix ){ ERROR_message("mri_lsqfit: MISMATCH refim[%d]!",ii); RETURN(NULL); } if( refim->imarr[ii]->kind == MRI_float ) tim = refim->imarr[ii] ; else tim = mri_to_float(refim->imarr[ii]) ; ADDTO_IMARR(frefim,tim) ; refar[ii] = mri_data_pointer(tim) ; } /****---- get coefficients ----****/ fit = lsqfit( npix , fitar , war , nref , refar ) ; /****---- clean up and exit ----****/ if( ffitim != fitim ) mri_free( ffitim ) ; if( wim != NULL && wim != wtim ) mri_free( wim ) ; for( ii=0 ; ii < nref ; ii++ ){ if( frefim->imarr[ii] != refim->imarr[ii] ) mri_free( frefim->imarr[ii] ) ; } FREE_IMARR(frefim) ; free(refar) ; RETURN(fit) ; }