funkalicious 0.1

potential_1d.c

Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines