|
funkalicious 0.1
|
00001 /* 00002 *Gets the potential from a 1D charge density through a number of methods. 00003 00004 Copyright (C) 2010 Joseph Pingenot 00005 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU Affero General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU Affero General Public License for more details. 00015 00016 You should have received a copy of the GNU Affero General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 */ 00020 00021 #include <gsl/gsl_errno.h> 00022 #include <gsl/gsl_interp.h> 00023 #include <gsl/gsl_spline.h> 00024 #include <gsl/gsl_integration.h> 00025 #include <math.h> 00026 #include <libpostproc/potential_1d.h> 00027 #include <libpostproc/unit_conversion.h> 00028 #ifdef OPENMP 00029 #include <omp.h> 00030 #endif 00031 00032 00033 //#define DEBUG_POTENTIAL_1D_C 00034 00035 /*Argument to the GSL integration workspace allocation calls*/ 00036 #define MAX_GSL_INTEGRATION_INTERVALS 4096 00037 00038 #define POTENTIAL_1D_GERROR_DOMAIN 73 00039 00040 struct density_1d* potential_1d_get_potential(double const_efield, double const_background, struct density_1d* charge_density, struct density_1d* epsilon, enum density_1d_potential_calculation_method method, double* max_pot_int_err, double* max_efield_int_err, double relerr, double abserr, GError **err) { 00041 switch(method) { 00042 case INTEGRATION_METHOD_NP: 00043 return potential_1d_get_potential_integrate(const_efield, const_background, charge_density, epsilon, 0, max_pot_int_err, max_efield_int_err, relerr, abserr, err); 00044 break; 00045 case INTEGRATION_METHOD_PN: 00046 return potential_1d_get_potential_integrate(const_efield, const_background, charge_density,epsilon, 1, max_pot_int_err, max_efield_int_err, relerr, abserr, err); 00047 break; 00048 default: 00049 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: no such potential calculation method: %d\n", method); 00050 return NULL; 00051 } 00052 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: Error allocating the new density_1d struct for the potential."); 00053 return NULL; 00054 } 00055 00056 struct potential_integration_method_integrand_params { 00057 gsl_spline* dfield; 00058 gsl_interp_accel* dfield_accel; 00059 gsl_spline* epsilon; 00060 gsl_interp_accel* epsilon_accel; 00061 #ifdef DEBUG_POTENTIAL_1D_C 00062 long int call; 00063 FILE* file; 00064 #endif 00065 }; 00066 00067 static double potential_integration_method_integrand(double x, void* privdat) { 00068 struct potential_integration_method_integrand_params* p = (struct potential_integration_method_integrand_params*)privdat; 00069 /*Need this minus sign; D = \epsilon -\nabla V*/ 00070 double value=-gsl_spline_eval(p->dfield, x, p->dfield_accel)/gsl_spline_eval(p->epsilon, x, p->epsilon_accel); 00071 #ifdef DEBUG_POTENTIAL_1D_C 00072 fprintf(p->file, "%ld\t%g\t%g\n", p->call++, x, value); 00073 #endif 00074 return value; 00075 } 00076 00077 struct dfield_integrand_params { 00078 gsl_spline* charge; 00079 gsl_interp_accel* charge_accel; 00080 #ifdef DEBUG_POTENTIAL_1D_C 00081 long int call; 00082 FILE* file; 00083 #endif 00084 }; 00085 static double dfield_integrand(double x, void* privdat) { 00086 struct dfield_integrand_params* p = (struct dfield_integrand_params*)privdat; 00087 double value= gsl_spline_eval(p->charge, x, p->charge_accel)*oo_epsilon0; 00088 #ifdef DEBUG_POTENTIAL_1D_C 00089 fprintf(p->file, "%ld\t%g\t%g\n", p->call++, x, value); 00090 #endif 00091 return value; 00092 } 00093 00094 00095 struct density_1d* potential_1d_get_dfield_integrate(double const_background,const struct density_1d* charge_density, short int direction_pn, double* max_int_err, double relerr, double abserr, GError **err) { 00096 00097 struct density_1d* Efield = new_density_1d(charge_density->N, charge_density->dx, const_background); 00098 if(Efield == NULL) { 00099 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_efield_integrate: Error allocating the new density_1d struct for the potential."); 00100 return NULL; 00101 } 00102 int n_threads = 1; 00103 #ifdef OPENMP 00104 n_threads = omp_get_max_threads(); 00105 #endif 00106 double* x = (double*)malloc(sizeof(double)*charge_density->N); 00107 for(unsigned i=0; i<charge_density->N; i++) x[i] = i*charge_density->dx; 00108 gsl_interp_accel *charge_accel[n_threads]; 00109 gsl_spline *charge[n_threads]; 00110 struct dfield_integrand_params parms[n_threads]; 00111 gsl_function gsl_func[n_threads]; 00112 for(int i=0; i<n_threads; i++) { 00113 charge_accel[i] = gsl_interp_accel_alloc(); 00114 charge[i] = gsl_spline_alloc(gsl_interp_akima, charge_density->N); 00115 gsl_spline_init(charge[i], x, charge_density->storage, charge_density->N); 00116 parms[i].charge = charge[i]; 00117 parms[i].charge_accel = charge_accel[i]; 00118 #ifdef DEBUG_POTENTIAL_1D_C 00119 parms[i].call = 0; 00120 parms[i].file = NULL; 00121 #endif 00122 gsl_func[i].function = &dfield_integrand; 00123 gsl_func[i].params = &(parms[i]); 00124 } 00125 #ifdef DEBUG_POTENTIAL_1D_C 00126 FILE* foo = fopen("charge_density.pdata", "w"); 00127 fprintf(foo, "#X\tx\tq\tq'\n"); 00128 for(unsigned i=0; i<charge_density->N; i++) fprintf(foo, "%u\t%g\t%g\t%g\n", i, x[i], charge_density->storage[i], gsl_spline_eval(charge[0], x[i], charge_accel[0])); 00129 fclose(foo); 00130 #endif 00131 int errored=0; 00132 gsl_integration_workspace** w = (gsl_integration_workspace**)malloc(sizeof(gsl_integration_workspace*)*n_threads); 00133 if(w == NULL) { 00134 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_efield_integrate: Error allocating the workspaces for the integration."); 00135 return NULL; 00136 } 00137 for(int i=0; i<n_threads; i++) { 00138 w[i] = gsl_integration_workspace_alloc(MAX_GSL_INTEGRATION_INTERVALS); 00139 } 00140 int status; 00141 double abserr_ = abserr; 00142 double max_abs_ierr[n_threads]; 00143 for(int i=0; i<n_threads; i++) max_abs_ierr[i]=-1; 00144 double max_ierr[n_threads]; 00145 double ierr; 00146 if(direction_pn) { 00147 errored=0; 00148 int i; 00149 GString* str; 00150 #ifdef OPENMP 00151 #pragma omp parallel for private(i, status, parms, ierr, str, abserr_) 00152 #endif 00153 for(i=charge_density->N-1; i>=0; i--) { 00154 int thread=1; 00155 #ifdef OPENMP 00156 thread = omp_get_thread_num(); 00157 #endif 00158 abserr_ = abserr; 00159 do { 00160 #ifdef DEBUG_POTENTIAL_1D_C 00161 str = g_string_new("charge_"); 00162 g_string_append_printf(str, "thread=%d_i=%d_abserr=%g.pdata", thread, i, abserr_); 00163 parms[thread].call = 0; 00164 parms[thread].file=fopen(str->str, "w"); 00165 g_string_free(str, TRUE); 00166 #else 00167 str = NULL; 00168 #endif 00169 status = gsl_integration_qag(&(gsl_func[thread]), (charge_density->N-1)*charge_density->dx, i*charge_density->dx, abserr_, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w[thread], &(Efield->storage[i]), &ierr); 00170 #ifdef DEBUG_POTENTIAL_1D_C 00171 fclose(parms[thread].file); 00172 #endif 00173 if(abs(ierr) > max_abs_ierr[thread]) { 00174 max_ierr[thread] = ierr; 00175 max_abs_ierr[thread] = abs(ierr); 00176 } 00177 if(status == GSL_EROUND) abserr_ *= 10; 00178 }while(status == GSL_EROUND); 00179 if(status != 0) { 00180 #ifdef OPENMP 00181 #pragma omp critical 00182 #endif 00183 { 00184 errored = 1; 00185 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_efield_integrate: Got error %d (%s) integrating from 0 to %g (grid site %u).", status, gsl_strerror(status), i*charge_density->dx, i); 00186 } 00187 #ifndef OPENMP 00188 break; 00189 #endif 00190 } 00191 } 00192 *max_int_err = -1; 00193 /*Find the maximum error from all the threads*/ 00194 for(int i=0; i<n_threads; i++) if(max_abs_ierr[i] > abs(*max_int_err)) *max_int_err = max_ierr[i]; 00195 if(errored) { 00196 /**err was set in the loop before calling errored*/ 00197 free_density_1d(Efield); 00198 for(int i=0; i<n_threads; i++) { 00199 gsl_spline_free(charge[i]); 00200 gsl_interp_accel_free(charge_accel[i]); 00201 gsl_integration_workspace_free(w[i]); 00202 } 00203 return NULL; 00204 } 00205 }else{ 00206 errored=0; 00207 int i; 00208 GString* str; 00209 #ifdef OPENMP 00210 #pragma omp parallel for private(i, status, ierr, str, abserr_) 00211 #endif 00212 for(i=0; i<charge_density->N; i++) { 00213 int thread=1; 00214 #ifdef OPENMP 00215 thread = omp_get_thread_num(); 00216 #endif 00217 abserr_ = abserr; 00218 do { 00219 #ifdef DEBUG_POTENTIAL_1D_C 00220 str = g_string_new("charge_"); 00221 g_string_append_printf(str, "thread=%d_i=%d_abserr=%g.pdata", thread, i, abserr_); 00222 parms[thread].call = 0; 00223 parms[thread].file=fopen(str->str, "w"); 00224 g_string_free(str, TRUE); 00225 #else 00226 str = NULL; 00227 #endif 00228 status = gsl_integration_qag(&(gsl_func[thread]), 0, i*charge_density->dx, abserr_, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w[thread], &(Efield->storage[i]), &ierr); 00229 #ifdef DEBUG_POTENTIAL_1D_C 00230 fclose(parms[thread].file); 00231 #endif 00232 if(abs(ierr) > max_abs_ierr[thread]) { 00233 max_ierr[thread] = ierr; 00234 max_abs_ierr[thread] = abs(ierr); 00235 } 00236 if(status == GSL_EROUND) abserr_ *= 10; 00237 }while(status == GSL_EROUND); 00238 if(status != 0) { 00239 #ifdef OPENMP 00240 #pragma omp critical 00241 #endif 00242 { 00243 errored = 1; 00244 if(*err == NULL) { 00245 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_efield_integrate: Got error %d (%s) integrating from 0 to %g (grid site %u) (abserr_ is %g).", status, gsl_strerror(status), i*charge_density->dx, i, abserr_); 00246 }else{ 00247 GError *e = NULL; 00248 g_propagate_prefixed_error(&e, *err, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_efield_integrate: Got error %d (%s) integrating from 0 to %g (grid site %u) (abserr_ is %g).\n", status, gsl_strerror(status), i*charge_density->dx, i, abserr_); 00249 *err = e; 00250 } 00251 } 00252 #ifndef OPENMP 00253 break; 00254 #endif 00255 } 00256 } 00257 *max_int_err = -1; 00258 /*Find the maximum error from all the threads*/ 00259 for(int i=0; i<n_threads; i++) if(max_abs_ierr[i] > abs(*max_int_err)) *max_int_err = max_ierr[i]; 00260 if(errored) { 00261 /**err was set in the loop before calling errored*/ 00262 free_density_1d(Efield); 00263 for(int i=0; i<n_threads; i++) { 00264 gsl_spline_free(charge[i]); 00265 gsl_interp_accel_free(charge_accel[i]); 00266 gsl_integration_workspace_free(w[i]); 00267 } 00268 return NULL; 00269 } 00270 } 00271 for(int i=0; i<n_threads; i++) { 00272 gsl_spline_free(charge[i]); 00273 gsl_interp_accel_free(charge_accel[i]); 00274 gsl_integration_workspace_free(w[i]); 00275 } 00276 free(x); 00277 return Efield; 00278 } 00279 00280 struct density_1d* potential_1d_get_potential_integrate(double dfield_background, double pot_background, const struct density_1d* charge_density, const struct density_1d* epsilon, short int direction_pn, double* max_pot_int_err, double* max_dfield_int_error, double relerr, double abserr, GError **err) { 00281 GError *e = NULL; 00282 struct density_1d* Dfield = potential_1d_get_dfield_integrate(dfield_background, charge_density, direction_pn, max_dfield_int_error, relerr, abserr, &e); 00283 if((Dfield == NULL) || (e != NULL)) { 00284 if(e == NULL) { 00285 e = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 3, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: Error getting displacement field in the structure (got NULL, but no error was reported)."); 00286 } 00287 g_propagate_prefixed_error(err, e, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: Error getting displacement field in the structure:"); 00288 return NULL; 00289 } 00290 /*Add the half the difference between the left- and right-hand sides to even out the calculation 00291 * in case of residual charge imbalance 00292 */ 00293 #ifdef DEBUG_POTENTIAL_1D_C 00294 fprintf(stderr, "Dfield difference between positive and negative sides: %g-%g=%g ->", Dfield->storage[Dfield->N-1], Dfield->storage[0], Dfield->storage[Dfield->N-1] + Dfield->storage[0]); 00295 #endif 00296 density_1d_add_const(Dfield, -(Dfield->storage[Dfield->N-1] + Dfield->storage[0])/2.0); 00297 #ifdef DEBUG_POTENTIAL_1D_C 00298 fprintf(stderr, " %g-%g=%g\n", Dfield->storage[Dfield->N-1], Dfield->storage[0], Dfield->storage[Dfield->N-1] + Dfield->storage[0]); 00299 #endif 00300 struct density_1d* phi = potential_1d_get_potential_from_dfield(pot_background, Dfield, epsilon, direction_pn, max_pot_int_err, relerr, abserr, err); 00301 /*Free the dfield before returning; we don't care about it if the caller used this function*/ 00302 free_density_1d(Dfield); 00303 return phi; 00304 } 00305 00306 struct density_1d* potential_1d_get_potential_from_dfield(double background, const struct density_1d* Dfield, const struct density_1d* epsilon, short int direction_pn, double* max_int_err, double relerr, double abserr, GError **err) { 00307 struct density_1d* phi = new_density_1d(Dfield->N, Dfield->dx, background); 00308 if(phi == NULL) { 00309 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: Error allocating the new density_1d struct for the potential."); 00310 return NULL; 00311 } 00312 int n_threads = 1; 00313 #ifdef OPENMP 00314 n_threads = omp_get_max_threads(); 00315 #endif 00316 double* x = (double*)malloc(sizeof(double)*Dfield->N); 00317 for(unsigned i=0; i<Dfield->N; i++) x[i] = i*Dfield->dx; 00318 gsl_interp_accel *dfield_accel[n_threads]; 00319 gsl_spline *dfield[n_threads]; 00320 gsl_interp_accel *eps_accel[n_threads]; 00321 gsl_spline *eps[n_threads]; 00322 struct potential_integration_method_integrand_params parms[n_threads]; 00323 gsl_function gsl_func[n_threads]; 00324 for (int i=0; i<n_threads; i++) { 00325 dfield_accel[i] = gsl_interp_accel_alloc(); 00326 dfield[i] = gsl_spline_alloc(gsl_interp_akima, Dfield->N); 00327 gsl_spline_init(dfield[i], x, Dfield->storage, Dfield->N); 00328 eps_accel[i] = gsl_interp_accel_alloc(); 00329 eps[i] = gsl_spline_alloc(gsl_interp_akima, Dfield->N); 00330 gsl_spline_init(eps[i], x, epsilon->storage, epsilon->N); 00331 parms[i].dfield = dfield[i]; 00332 parms[i].dfield_accel = dfield_accel[i]; 00333 parms[i].epsilon = eps[i]; 00334 parms[i].epsilon_accel = eps_accel[i]; 00335 #ifdef DEBUG_POTENTIAL_1D_C 00336 parms[i].call = 0; 00337 parms[i].file = NULL; 00338 #endif 00339 gsl_func[i].function = &potential_integration_method_integrand; 00340 gsl_func[i].params = &(parms[i]); 00341 }; 00342 #ifdef DEBUG_POTENTIAL_1D_C 00343 FILE* foo = fopen("dfield.pdata", "w"); 00344 fprintf(foo, "#X\tx\tq\tq'\teps\teps'\tq/eps\tq'/eps'\n"); 00345 for(unsigned i=0; i<Dfield->N; i++) fprintf(foo, "%u\t%g\t%g\t%g\t%g\t%g\t%g\t%g\n", i, x[i], Dfield->storage[i], gsl_spline_eval(dfield[0], x[i], dfield_accel[0]), epsilon->storage[i], gsl_spline_eval(eps[0], x[i], eps_accel[0]), Dfield->storage[i]/epsilon->storage[i], gsl_spline_eval(dfield[0], x[i], dfield_accel[0])/gsl_spline_eval(eps[0], x[i], eps_accel[0])); 00346 fclose(foo); 00347 #endif 00348 int errored=0; 00349 gsl_integration_workspace** w = (gsl_integration_workspace**)malloc(sizeof(gsl_integration_workspace*)*n_threads); 00350 if(w == NULL) { 00351 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_efield_integrate: Error allocating the workspaces for the integration."); 00352 return NULL; 00353 } 00354 for(int i=0; i<n_threads; i++) { 00355 w[i] = gsl_integration_workspace_alloc(MAX_GSL_INTEGRATION_INTERVALS); 00356 } 00357 int status; 00358 double abserr_ = abserr; 00359 double max_abs_ierr[n_threads]; 00360 for(int i=0; i<n_threads; i++) max_abs_ierr[i]=-1; 00361 double max_ierr[n_threads]; 00362 double ierr; 00363 if(direction_pn) { 00364 errored=0; 00365 int i; 00366 GString* str; 00367 #ifdef OPENMP 00368 #pragma omp parallel for private(i, status, ierr, str, abserr_) 00369 #endif 00370 for(i=Dfield->N-1; i>=0; i--) { 00371 int thread=1; 00372 #ifdef OPENMP 00373 thread = omp_get_thread_num(); 00374 #endif 00375 abserr_ = abserr; 00376 do{ 00377 #ifdef DEBUG_POTENTIAL_1D_C 00378 str = g_string_new("charge_"); 00379 g_string_append_printf(str, "thread=%d_i=%d_abserr=%g.pdata", thread, i, abserr_); 00380 parms[thread].call = 0; 00381 parms[thread].file=fopen(str->str, "w"); 00382 g_string_free(str, TRUE); 00383 #else 00384 str = NULL; 00385 #endif 00386 status = gsl_integration_qag(&(gsl_func[thread]), (Dfield->N-1)*Dfield->dx, i*Dfield->dx, abserr_, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w[thread], &(phi->storage[i]), &ierr); 00387 #ifdef DEBUG_POTENTIAL_1D_C 00388 fclose(parms[thread].file); 00389 #endif 00390 if(abs(ierr) > max_abs_ierr[thread]) { 00391 max_ierr[thread] = ierr; 00392 max_abs_ierr[thread] = abs(ierr); 00393 } 00394 if(status == GSL_EROUND) abserr_ *= 10; 00395 }while(status == GSL_EROUND); 00396 if(status != 0) { 00397 #ifdef OPENMP 00398 #pragma omp critical 00399 #endif 00400 { 00401 errored=1; 00402 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: Got error %d (%s) integrating from 0 to %g (grid site %u).", status, gsl_strerror(status), i*Dfield->dx, i); 00403 } 00404 #ifndef OPENMP 00405 break; 00406 #endif 00407 } 00408 } 00409 *max_int_err = -1; 00410 /*Find the maximum error from all the threads*/ 00411 for(int i=0; i<n_threads; i++) if(max_abs_ierr[i] > abs(*max_int_err)) *max_int_err = max_ierr[i]; 00412 if(errored) { 00413 free_density_1d(phi); 00414 for(int i=0; i<n_threads; i++) { 00415 gsl_spline_free(dfield[i]); 00416 gsl_interp_accel_free(dfield_accel[i]); 00417 gsl_spline_free(eps[i]); 00418 gsl_interp_accel_free(eps_accel[i]); 00419 gsl_integration_workspace_free(w[i]); 00420 } 00421 free(x); 00422 return NULL; 00423 } 00424 }else{ 00425 errored=0; 00426 int i; 00427 GString* str; 00428 #ifdef OPENMP 00429 #pragma omp parallel for private(i, status, ierr, str, abserr_) 00430 #endif 00431 for(i=0; i<Dfield->N; i++) { 00432 int thread=1; 00433 #ifdef OPENMP 00434 thread = omp_get_thread_num(); 00435 #endif 00436 abserr_ = abserr; 00437 do{ 00438 #ifdef DEBUG_POTENTIAL_1D_C 00439 str = g_string_new("charge_"); 00440 g_string_append_printf(str, "thread=%d_i=%d_abserr=%g.pdata", thread, i, abserr_); 00441 parms[thread].call = 0; 00442 parms[thread].file=fopen(str->str, "w"); 00443 g_string_free(str, TRUE); 00444 #else 00445 str = NULL; 00446 #endif 00447 status = gsl_integration_qag(&(gsl_func[thread]), 0, i*Dfield->dx, abserr_, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w[thread], &(phi->storage[i]), &ierr); 00448 #ifdef DEBUG_POTENTIAL_1D_C 00449 fclose(parms[thread].file); 00450 #endif 00451 if(abs(ierr) > max_abs_ierr[thread]) { 00452 max_ierr[thread] = ierr; 00453 max_abs_ierr[thread] = abs(ierr); 00454 } 00455 if(status == GSL_EROUND) abserr_ *= 10; 00456 }while(status == GSL_EROUND); 00457 if(status != 0) { 00458 #ifdef OPENMP 00459 #pragma omp critical 00460 #endif 00461 { 00462 errored=1; 00463 *err = g_error_new(POTENTIAL_1D_GERROR_DOMAIN, 1, "funkalicious::libpostproc::potential_1d.c::potential_1d_get_potential: Got error %d (%s) integrating from 0 to %g (grid site %u).", status, gsl_strerror(status), i*Dfield->dx, i); 00464 } 00465 #ifndef OPENMP 00466 break; 00467 #endif 00468 } 00469 } 00470 *max_int_err = -1; 00471 /*Find the maximum error from all the threads*/ 00472 for(int i=0; i<n_threads; i++) if(max_abs_ierr[i] > abs(*max_int_err)) *max_int_err = max_ierr[i]; 00473 if(errored) { 00474 free_density_1d(phi); 00475 for(int i=0; i<n_threads; i++) { 00476 gsl_spline_free(dfield[i]); 00477 gsl_interp_accel_free(dfield_accel[i]); 00478 gsl_spline_free(eps[i]); 00479 gsl_interp_accel_free(eps_accel[i]); 00480 gsl_integration_workspace_free(w[i]); 00481 } 00482 free(x); 00483 return NULL; 00484 } 00485 } 00486 for(int i=0; i<n_threads; i++) { 00487 gsl_spline_free(dfield[i]); 00488 gsl_interp_accel_free(dfield_accel[i]); 00489 gsl_spline_free(eps[i]); 00490 gsl_interp_accel_free(eps_accel[i]); 00491 gsl_integration_workspace_free(w[i]); 00492 } 00493 free(x); 00494 return phi; 00495 }