|
funkalicious 0.1
|
00001 /* 00002 ** wavefunction.h 00003 ** 00004 00005 Copyright (C) 2009 Joseph Pingenot 00006 00007 This program is free software: you can redistribute it and/or modify 00008 it under the terms of the GNU Affero General Public License as published by 00009 the Free Software Foundation, either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Affero General Public License for more details. 00016 00017 You should have received a copy of the GNU Affero General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 00020 ** Made by Johnny Q. Hacker 00021 ** Login <solarion@nathan> 00022 ** 00023 ** Started on Tue Nov 17 22:28:05 2009 Johnny Q. Hacker 00024 ** Last update Tue Nov 17 22:28:05 2009 Johnny Q. Hacker 00025 */ 00026 00027 #include <glib-2.0/glib.h> 00028 #include <gio/gio.h> 00029 #include <libdotcode/function_parser.h> 00030 #include <libdotcode/binary_data_common.h> 00031 #include <libpostproc/density_common.h> 00032 00033 #ifndef WAVEFUNCTION_H_ 00034 # define WAVEFUNCTION_H_ 00035 00036 #ifdef __cplusplus 00037 extern "C" { 00038 #endif 00039 00040 00041 /*For clarity, X, Y, and Z specify respective array indices.*/ 00042 enum coord {X, Y, Z}; 00043 00044 struct wavefunction { 00045 GFile* file; 00046 double charge; 00047 int N[3]; 00048 double dx[3]; 00049 int bands; 00050 struct wavefunc_header header; 00051 double* storage; 00052 }; 00053 00054 struct density { 00055 int N[3]; 00056 double dx[3]; 00057 double* storage; 00058 }; 00059 00060 00061 /**Gets a new density with a double-resolution grid, using an average for interpolation 00062 *\param original original density 00063 *\param auto_scale flags on which dimension to use to scale: 1->Y 2->Y 4->Z (combine for multiple directions) 00064 *\return pointer to a density, or NULL if memory allocation failed. 00065 *\note the new grid doesn't add an outside row of new sites; it only places a new grid site between two existing ones 00066 */ 00067 struct density* get_double_resolution_density(const struct density* original, int auto_scale); 00068 00069 /**Gets a new density with a half-resolution grid, using an average for assignment 00070 *\param original original density 00071 *\param e pointer to pointer to Gerror in which to store the error information 00072 *\param auto_scale flags on which dimension to use to scale: 1->Y 2->Y 4->Z (combine for multiple directions) 00073 *\return pointer to a density, or NULL if memory allocation failed. 00074 *\note the new grid doesn't add an outside row of new sites; it only places a new grid site between two existing ones 00075 */ 00076 struct density* get_half_resolution_density(const struct density* original, GError **e, int auto_scale); 00077 00078 /**Gets a density from a list of *loaded* wavefunctions 00079 *\param list the list of *loaded* wavefunction structures. 00080 *\param err pointer to a pointer in which to store the GError (if 00081 *there's an error) 00082 *\returns a density that is the sum of the individual wavefunctions. 00083 *\note Wavefunctions must be *loaded* before calling this function! 00084 *\note The charge is used! If you just want pre-normalized |psi|^2, 00085 *set charge to 1. 00086 */ 00087 struct density* get_density_for_list_of_wavefunctions(GList *list, GError **err); 00088 /**Loads the wavefunctions from the respective GFiles. 00089 *\param wf_list List of wavefunctions 00090 *\param err pointer to a pointer in which to store the GError (if 00091 *there's an error) 00092 */ 00093 void load_wavefunctions(GList* wf_list, GError** err); 00094 void init_density(struct density* d, double initial_value); 00095 void add_to_density(struct density* d, struct wavefunction* wf); 00096 /**Puts a density into *one section* of a metadensity. 00097 *\param md the target meta_density 00098 *\param d the source density 00099 *\param Nn an array of ints representing the number of neighbors in 00100 *each direction. 00101 *\param x location of this block to be inserted. 00102 *\param y location of this block to be inserted. 00103 *\param z location of this block to be inserted. 00104 *\param invert_x if true, the x-coordinates are read backwards from 00105 *the source. 00106 *\param invert_y if true, the y-coordinates are read backwards from 00107 *the source. 00108 *\param invert_z if true, the z-coordinates are read backwards from 00109 *the source. 00110 *\param offsets offset in grid sites between neighborsa 00111 */ 00112 void put_density_into_metadensity(struct density* md, const struct density* d, const int *Nn, int x, int y, int z, gboolean invert_x, gboolean invert_y, gboolean invert_z, const unsigned* offsets); 00113 /**Writes out a single, ascii density slice or the entire box. 00114 *\param c the coordinate to output 00115 *\param index pointer to an int containing the index which should be 00116 *written out 00117 *\param d the density to be written 00118 *\param filename pointer to a pointer to a char, to provide the 00119 *filename of the written file. 00120 *\param err pointer to a pointer to a GError, for returning any error 00121 *info 00122 *\param location base directory to output, or NULL if cwd. If index 00123 *is NULL, this is the file to write the dump into. 00124 *\param sepchar character to use to separate the columns in the 00125 *output 00126 *\return nothing 00127 */ 00128 void write_density_slice(enum coord c, const int* index, const struct density* d, char** filename, GError **err, GFile *location, char sepchar, const char* coord_units, const char* density_units); 00129 void write_density_sweep(enum coord c, const struct density* d, char** filename, GError **err, GFile* location, gboolean sweep_log); 00130 void write_density_line(enum coord axis, const int* gridsite, const struct density* d, char** filename, GError **err, GFile *location, char sepchar, const char* coord_units, const char* density_units); 00131 00132 void density_mul_by_const(struct density* d, double c); 00133 /**Gets a block of the meta_density back out. 00134 *\param md the meta denstiy 00135 *\param d an initialized density the sizeo f one block 00136 *\param buffzone the buffer zone size around the meta_density 00137 *\param Mn the number of neighbors in each direction 00138 *\param x the x-coordinate of the block 00139 *\param y the y-coordinate of the block 00140 *\param z the z-coordinate of the block 00141 *\param offsets offset in grid sites between neighborsa 00142 */ 00143 void get_density_from_metadensity(const struct density* md, struct density* d, const int* buffzone, const int *Nn, int x, int y, int z, const unsigned* offsets); 00144 00145 /**Writes the density into a povray visualization. 00146 *\param d the density to be written out 00147 *\param towrite the file into which the povray visualization should be written 00148 *\paarm err pointer to a pointer to a GError, used to "return" a GError pointer if an error ocurred. 00149 */ 00150 void write_density_povray(const struct density* d, GFile *towrite, int pixel_strategy, GError **err); 00151 00152 /**Expands a density box using material mat 00153 *\param od the original density 00154 *\param I a 3-int array indicating how many grid sites to expand outward. 00155 *\param value a double containing the value of the density throughout the new region 00156 *\returns a pointer to a new density. 00157 */ 00158 struct density* expand_density_box_with_value(const struct density* od, const int* I, double value, GError **err); 00159 /**Expands a density box using the value from the outermost grid site. 00160 *\param od the original density 00161 *\param I a 3-int array containing the number of grid sites to expand 00162 *outwards 00163 */ 00164 struct density* expand_density_box(const struct density* od, const int* I, GError **err); 00165 00166 struct density* new_density(const int* N, const double* dx, double intial_value); 00167 struct density* new_density_copy(const struct density* orig); 00168 void free_density(struct density* d); 00169 int op_density_to_density(struct density* to, enum density_op op, const struct density* from); 00170 /**Executes the specified callback 00171 *\param d density struct 00172 *\param callback pointer to function to call 00173 *\param privdat private data for the callback 00174 *\return nothing 00175 */ 00176 void density_execute_callback(const struct density* d, void (*callback)(int x, int y, int z, const struct density*d, void* privdat), void* privdat); 00177 /**same, but takes two density functions*/ 00178 void density_2_execute_callback(const struct density* d1, const struct density* d2, void (*callback)(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat), void* privdat); 00179 /**OpenMP-parallelized callback executors. 00180 *This is identical to the serial executors above, but parallelized with OpenMP. The most obvious effect is a slight change in the API: the executor itself is passed an *array* of pointers to void. The callback itself still accepts a pointer to void (not a pointer to a pointer to void). The specified callback is executed in an OpenMP parallelized for loop (on the z index, for whatever that matters). Each thread is assigned (by thread number) a pointer to void to use as its privdat argument to the callback. Each thread, then, executes the callback on its specified points (subject to OpenMP scheduling; no guarantees can be made with regard to order) with the same callback privdat pointer. See the density_get_max function for an example of how to use this. 00181 *\param d density struct 00182 *\param callback pointer to function to call 00183 *\param privdat array of private data pointers for the callback, one per thread. 00184 *\param x_report array of ints, one per thread. Set to 1 if a thread is executed, and is left untouched otherwise. 00185 *\return nothing 00186 */ 00187 void density_execute_callback_parallel(const struct density* d, void (*callback)(int x, int y, int z, const struct density*d, void* privdat), void** privdat, int* x_report); 00188 void density_2_execute_callback_parallel(const struct density* d1, const struct density* d2, void (*callback)(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat), void** privdat, int* x_report); 00189 00190 00191 /**returns the maximum percent (at the point) difference between two densities, or NaN if the dimensions differ 00192 *\param d1 density to compare 00193 *\param d2 density to compare 00194 *\param scaleby 00195 * if 3, use scaling to scale before comparing (the difference will be multiplied by this value) 00196 * if 2, get diff as percent of global maximum of d2 00197 * if 1, get diff as percent of global maximum of d1 00198 * if 0, get diff as percent of local value in d1. 00199 * if -1, get diff as percent of local value in d2. 00200 *\param scaling value to use for scaling if scaleby==3, else ignored 00201 */ 00202 double density_get_max_abs_delta_pct(const struct density* d1, const struct density* d2, int scaleby, double scaling); 00203 /**returns the minimum percent (at the point) difference between two densities, or NaN if the dimensions differ 00204 *\param d1 density to compare 00205 *\param d2 density to compare 00206 *\param scaleby 00207 * if 3, use scaling to scale before comparing (the difference will be multiplied by this value) 00208 * if 2, get diff as percent of global maximum of d2 00209 * if 1, get diff as percent of global maximum of d1 00210 * if 0, get diff as percent of local value in d1. 00211 * if -1, get diff as percent of local value in d2. 00212 *\param scaling value to use for scaling if scaleby==3, else ignored 00213 */ 00214 double density_get_min_abs_delta_pct(const struct density* d1, const struct density* d2, int scaleby, double scaling); 00215 /**Gets the maximum value in the density 00216 *\param d density to inspect 00217 *\param abs if true, compare absolute value instead of raw value. 00218 *\return the maximum value in d 00219 */ 00220 double density_get_max(const struct density* d, int abs); 00221 double density_get_max_and_loc(const struct density* d, int abs, int* location); 00222 /**Gets the minimum value in the density 00223 *\param d density to inspect 00224 *\param abs if true, compare absolute value instead of raw value. 00225 *\return the minimum value in d 00226 */ 00227 double density_get_min(const struct density* d, int abs); 00228 double density_get_min_and_loc(const struct density* d, int abs, int* location); 00229 00230 struct dotcode_grid* dotcode_grid_from_density(const struct density *d, GError **err); 00231 long unsigned int get_density_storage_index_(unsigned int x, unsigned int y, unsigned int z, unsigned int Nx, unsigned int Ny); 00232 00233 /**gets pointer to the cell at this location 00234 *\param x coordinate 00235 *\param y coordinate 00236 *\param z coordinate 00237 *\param d density structure 00238 *\return pointer to the density value at the specified point 00239 *\note no error checking is performed 00240 */ 00241 double* get_density_storage_at_(unsigned x, unsigned y, unsigned z,struct density* d); 00242 /**gets const pointer to the cell at this location 00243 *\param x coordinate 00244 *\param y coordinate 00245 *\param z coordinate 00246 *\param d density structure 00247 *\return const pointer to the density value at the specified point 00248 *\note no error checking is performed 00249 */ 00250 const double* get_density_storage_at_c_(unsigned x, unsigned y, unsigned z, const struct density* d); 00251 00252 /**Evaluates an integral of the density using GSL and a spline fit. 00253 *\param z_error_estimate: pointer to a double in which to store the estimated integration error from the final integration along z, or NULL if the error isn't to be saved. 00254 *\param y_error_estimate: pointer to an array (of size wf->N[2], one for each z point) of doubles in which to store the estimated integration error for each y integral, or NULL if the error isn't to be saved. 00255 *\param x_error_estimate: pointer to an array (of size wf->N[1]*wf->N[2], one for each (y, z) pairing) of doubles in which to store the estimated error for each x integral, or NULL if the error isn't to be saved. 00256 *\param abserr the requested absolute error (see GSL documentation) 00257 *\param relerr the requested relative error (see GSL documentation) 00258 *\param d the density over which to integrate 00259 *\param f a function to call at each point (if NULL, does nothing). 00260 *\param privdat private data to pass to f. 00261 *\return the integral 00262 *\note d will be fit to a cubic spline before integration. 00263 *\note THIS IS BROKEN 00264 */ 00265 double density_integrate_spline(double* z_error_estimate, double* y_error_estimate, double* x_error_estimate, double relerr, double abserr, const struct density* d, double (*f)(double x, double y, double z, void* privdat), void* privdat); 00266 00267 /**Evaluates an integral of the density using GSL and a spline fit, parallelized with OpenMP on the z coordinate 00268 *\param d the density over which to integrate 00269 *\param f a function to call at each point (if NULL, does nothing). 00270 *\param privdat array of private data to pass to the callback (one for each thread, indexed by omp_get_thread_num()). 00271 *\return the integral 00272 *\note d will be fit to a cubic spline before integration. 00273 *\note the same f can be used for both the single- and multi-threaded functions. 00274 *\note if privdat is NULL, NULL will be passed to f (this saves you having to allocate an array of NULLs 00275 *\note THIS IS SUPER-BROKEN 00276 */ 00277 double density_integrate_spline_parallel(const struct density* d, double (*f)(double x, double y, double z, void* privdat), void** privdat); 00278 00279 /**Evaluates an integral of the density using GSL and a simple summing mechanism: sum goes inwards from both ends, assuming that each end is a minimum. 00280 *\param d the density over which to integrate 00281 *\param f a function to call at each point (if NULL, does nothing). 00282 *\param privdat array of private data to pass to the callback (one for each thread, indexed by omp_get_thread_num()). 00283 *\return the integral 00284 *\note d will be fit to a cubic spline before integration. 00285 *\note the same f can be used for both the single- and multi-threaded functions. 00286 *\note if privdat is NULL, NULL will be passed to f (this saves you having to allocate an array of NULLs 00287 */ 00288 double density_integrate_sum(const struct density* d, double (*f)(double x, double y, double z, void* privdat), void* privdat); 00289 double density_integrate_sum_parallel(const struct density* d, double (*f)(double x, double y, double z, void* privdat), void** privdat); 00290 00291 00292 #ifdef __cplusplus 00293 } 00294 #endif 00295 00296 #endif /* !WAVEFUNCTION_H_ */