|
funkalicious 0.1
|
00001 /* 00002 ** wavefunction.c 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:22 2009 Johnny Q. Hacker 00024 ** Last update Sun May 12 01:17:25 2002 Speed Blue 00025 */ 00026 00027 #include <gsl/gsl_errno.h> 00028 #include <gsl/gsl_interp.h> 00029 #include <gsl/gsl_spline.h> 00030 #include <gsl/gsl_integration.h> 00031 #include <stdlib.h> 00032 #include <stdio.h> 00033 #include <glib-2.0/glib.h> 00034 #include <gio/gio.h> 00035 #include <math.h> 00036 #include <libpostproc/lp_wavefunction.h> 00037 #include <libdotcode/binary_data_common.h> 00038 #include <libpostproc/unit_conversion.h> 00039 #include "gcc_hints.h" 00040 00041 #ifdef OPENMP 00042 #include <omp.h> 00043 #endif 00044 00045 #define NUM_STEPS 12 00046 #define THRESHOLD 0.5 00047 00048 #define WAVEFUNC_GERROR_DOMAIN 4096 00049 00050 #define MAX_PIXEL_VAL 255 00051 00052 #define MAX_GSL_INTEGRATION_INTERVALS 4096 00053 00054 /** 00055 *Gets the index into the storage member for a wavefunction, or for a density 00056 *\param x x index component 00057 *\param y y index component 00058 *\param z z index component 00059 *\param b band index component 00060 *\param im 1 if imaginary component is wanted; 0 else. 00061 *\param Nx Number of x sites 00062 *\param Ny Number of y sites 00063 *\param Nb Number of bands 00064 *\returns long unsigned int, which is the address in the storage 00065 *array. 00066 *\note there is no error checking, for speed purposes. E.g. if im is 00067 *3, it'll just be blindly used as a 3 and you'll be addressing the 00068 *imaginary component of the next index. 00069 *\note Nz is not needed. 00070 */ 00071 hotfunc ___const ___always_inline long unsigned int get_wavefunction_storage_index(unsigned int x, unsigned int y, unsigned int z, unsigned int im, unsigned int b, unsigned int Nx, unsigned int Ny, int Nb) { 00072 return im + 2*(b + Nb*(x + Nx*(y + Ny*(z)))); 00073 } 00074 00075 hotfunc ___const ___always_inline long unsigned int get_density_storage_index(unsigned int x, unsigned int y, unsigned int z, unsigned int Nx, unsigned int Ny) { 00076 return x + Nx*(y + Ny*(z)); 00077 } 00078 hotfunc ___const ___always_inline long unsigned int get_density_slice_storage_index(enum coord c, unsigned int x, unsigned int y, unsigned int z, unsigned int Nx, unsigned int Ny) { 00079 switch(c) { 00080 case X: 00081 x=0; 00082 Nx=1; 00083 break; 00084 case Y: 00085 y=0; 00086 Ny=1; 00087 break; 00088 case Z: 00089 z=0; 00090 break; 00091 } 00092 return x + Nx*(y + Ny*(z)); 00093 } 00094 00095 long unsigned int get_density_storage_index_(unsigned int x, unsigned int y, unsigned int z, unsigned int Nx, unsigned int Ny) { 00096 return get_density_storage_index(x, y, z, Nx, Ny); 00097 } 00098 00099 hotfunc ___always_inline double* get_density_storage_at(unsigned x, unsigned y, unsigned z, struct density* d) { 00100 return &(d->storage[get_density_storage_index(x, y, z, d->N[0], d->N[1])]); 00101 } 00102 00103 double* get_density_storage_at_(unsigned x, unsigned y, unsigned z, struct density* d) { 00104 return get_density_storage_at(x, y, z, d); 00105 } 00106 00107 hotfunc ___always_inline const double* get_density_storage_at_c(unsigned x, unsigned y, unsigned z, const struct density* d) { 00108 return &(d->storage[get_density_storage_index(x, y, z, d->N[0], d->N[1])]); 00109 } 00110 00111 const double* get_density_storage_at_c_(unsigned x, unsigned y, unsigned z, const struct density* d) { 00112 return get_density_storage_at_c(x, y, z, d); 00113 } 00114 00115 00116 00117 void init_density(struct density* d, double value) { 00118 int i, j, k; 00119 #ifdef DEBUG2 00120 fprintf(stderr, "wavefunc::init_density: d->N={%d,%d,%d} d->dx={%g,%g,%g}\n", d->N[0], d->N[1], d->N[2], d->dx[0], d->dx[1], d->dx[2]); 00121 #endif 00122 for(k=0; k<d->N[2]; k++) { 00123 for(j=0; j<d->N[1]; j++) { 00124 for(i=0; i<d->N[0]; i++) { 00125 d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])] = value; 00126 } 00127 } 00128 } 00129 } 00130 00131 /*This is where the complex wavefunction becomes real (and 00132 pre-normalized like LAPACK) density.*/ 00133 void internal_add_to_density(struct density* d, struct wavefunction* wf) { 00134 register int i, j, k, b; 00135 double re, im; 00136 for(k=0; k<d->N[2]; k++) { 00137 for(j=0; j<d->N[1]; j++) { 00138 for(i=0; i<d->N[0]; i++) { 00139 for(b=0; b<wf->bands; b++){ 00140 re = wf->storage[get_wavefunction_storage_index(i, j, k, b, 0, wf->N[0], wf->N[1], wf->bands)]; 00141 im = wf->storage[get_wavefunction_storage_index(i, j, k, b, 0, wf->N[0], wf->N[1], wf->bands)]; 00142 d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])] += (re*re + im*im)*wf->charge; 00143 } 00144 } 00145 } 00146 } 00147 } 00148 void add_to_density(struct density* d, struct wavefunction* wf) { 00149 internal_add_to_density(d, wf); 00150 } 00151 00152 struct density* get_density_for_list_of_wavefunctions(GList *list, GError** err) { 00153 if(list==NULL) { 00154 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 1, "lp_wavefunction.c::get_density_for_list_of_wavefunctions: ERROR: list was empty!\n"); 00155 return NULL; 00156 } 00157 struct density *d; 00158 struct wavefunction *wf = (struct wavefunction*)(list->data); 00159 if((d = (struct density*)malloc(sizeof(struct density))) == NULL) { 00160 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 2, "lp_wavefunction.c::get_density_for_list_of_wavefunctions: ERROR: failed to allocate memory for total density structure."); 00161 return NULL; 00162 } 00163 if((d->storage = (double*)malloc(sizeof(double)*(wf->N[0])*(wf->N[1])*(wf->N[2]))) == NULL) { 00164 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 2, "lp_wavefunction.c::get_density_for_list_of_wavefunctions: ERROR: failed to allocate memory for total density's storage."); 00165 free(d); 00166 return NULL; 00167 } 00168 for(int i=0; i<3; i++) d->N[i] = wf->N[i]; 00169 for(int i=0; i<3; i++) d->dx[i] = wf->dx[i]; 00170 init_density(d, 0); 00171 GList *l; 00172 for(l=list; l != NULL; l=l->next) { 00173 wf = (struct wavefunction*)l->data; 00174 for(int i=0; i<3; i++) { 00175 if((wf->N[i] != d->N[i]) || (wf->dx[i] != d->dx[i])) { 00176 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 2, "lp_wavefunction.c::get_density_for_list_of_wavefunctions: ERROR: wavefunction (%s) has an inconsistent size N=(%d, %d, %d) expected (%d, %d, %d); dx=(%g, %g, %g) expected (%g %g %g)", g_file_get_uri(wf->file), wf->N[0], wf->N[1], wf->N[2], d->N[0], d->N[1], d->N[2], wf->dx[0], wf->dx[1], wf->dx[2], d->dx[0], d->dx[1], d->dx[2]); 00177 free(d->storage); 00178 free(d); 00179 return NULL; 00180 } 00181 internal_add_to_density(d, wf); 00182 } 00183 } 00184 return d; 00185 } 00186 00187 void load_wavefunctions(GList* wf_list, GError** err) { 00188 GList *l; 00189 struct wavefunction* wf; 00190 int ie; 00191 GError *e = NULL; 00192 for(l=wf_list; l!=NULL; l=l->next) { 00193 wf = (struct wavefunction *)(l->data); 00194 e=NULL; 00195 ie = read_wavefunction_gfile(wf->file, &(wf->header), &(wf->storage), &e); 00196 if((ie != 0) || (e != NULL)) { 00197 if(e == NULL) { 00198 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, ie, "wavefunction::load_wavefunctions: Got a non-zero return value from function_parser::read_wavefunction_gfile: %d\n", ie); 00199 }else{ 00200 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, ie, "wavefunction::load_wavefunctions: Got following GError from function_parser::read_wavefunction_gfile: %d/%s\n", e->code, e->message); 00201 } 00202 return; 00203 } 00204 wf->N[0] = wf->header.Nx; 00205 wf->N[1] = wf->header.Ny; 00206 wf->N[2] = wf->header.Nz; 00207 wf->bands = wf->header.Nc; 00208 wf->dx[0] = wf->header.dx; 00209 wf->dx[1] = wf->header.dy; 00210 wf->dx[2] = wf->header.dz; 00211 } 00212 } 00213 00214 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){ 00215 if(d == NULL) return; 00216 if(d->storage == NULL) return; 00217 int xoffset = x*(d->N[0]+offsets[0]); 00218 int yoffset = y*(d->N[1]+offsets[1]); 00219 int zoffset = z*(d->N[2]+offsets[2]); 00220 int source_x, source_y, source_z; 00221 int k, j, i; 00222 #ifdef OPENMP 00223 #pragma omp parallel for private(k, j, i, source_z, source_y, source_x) 00224 #endif 00225 for(k=0; k<d->N[2]; k++) { 00226 /*The -1 is to ensure that we start at the last *valid* location 00227 *in the source (and end at the beginning of the source) 00228 */ 00229 source_z = invert_z?(d->N[2]-k-1):k; 00230 for(j=0; j<d->N[1]; j++) { 00231 source_y = invert_y?(d->N[1]-j-1):j; 00232 for(i=0; i<d->N[0]; i++) { 00233 source_x = invert_x?(d->N[0]-i-1):i; 00234 md->storage[get_density_storage_index(i+xoffset, j+yoffset, k+zoffset, md->N[0], md->N[1])] 00235 = d->storage[get_density_storage_index(source_x, source_y, source_z, d->N[0], d->N[1])]; 00236 } 00237 } 00238 } 00239 } 00240 00241 /**Gets a block of the meta_density back out. 00242 *\param md the meta denstiy 00243 *\param d an initialized density the sizeo f one block 00244 *\param buffzone the buffer zone size around the meta_density 00245 *\param Mn the number of neighbors in each direction 00246 *\param x the x-coordinate of the block 00247 *\param y the y-coordinate of the block 00248 *\param z the z-coordinate of the block 00249 *\param offsets offset between neighbors in each dimension 00250 */ 00251 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){ 00252 if(d == NULL) return; 00253 if(d->storage == NULL) return; 00254 int xoffset = x*(d->N[0]+offsets[0]); 00255 int yoffset = y*(d->N[1]+offsets[1]); 00256 int zoffset = z*(d->N[2]+offsets[2]); 00257 if(buffzone != NULL) { 00258 xoffset += buffzone[0]; 00259 yoffset += buffzone[1]; 00260 zoffset += buffzone[2]; 00261 } 00262 int k, j, i; 00263 #ifdef OPENMP 00264 #pragma omp parallel for private(k, j, i) 00265 #endif 00266 for(k=0; k<d->N[2]; k++) { 00267 for(j=0; j<d->N[1]; j++) { 00268 for(i=0; i<d->N[0]; i++) { 00269 d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])] 00270 = md->storage[get_density_storage_index(i+xoffset, j+yoffset, k+zoffset, md->N[0], md->N[1])]; 00271 } 00272 } 00273 } 00274 } 00275 00276 void density_mul_by_const(struct density* d, double c) { 00277 int i, j, k; 00278 #ifdef OPENMP 00279 #pragma omp parallel for private(i, j, k) 00280 #endif 00281 for(k=0; k<d->N[2]; k++) { 00282 for(j=0; j<d->N[1]; j++) { 00283 for(i=0; i<d->N[0]; i++) { 00284 d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])] *= c; 00285 } 00286 } 00287 } 00288 } 00289 00290 /** 00291 *The wavefunction itself is normalized such that adding all the values 00292 *togetheer yields 1. We need the density at each point; hence must divide 00293 * by dx*dy*dz 00294 */ 00295 void density_un_normalize(struct density* d) { 00296 double volume = 1.0/((d->dx[0])*(d->dx[1])*(d->dx[2])); 00297 density_mul_by_const(d, volume); 00298 } 00299 00300 00301 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) { 00302 /*If we're iterating on an index, go to the next loop unless the index is right*/ 00303 GError *e = NULL; 00304 GFile* f; 00305 GString *s = g_string_new("slice_"); 00306 if(index != NULL) { 00307 switch(c) { 00308 case X: 00309 g_string_append_printf(s, "X=%d.pdata", *index); 00310 break; 00311 case Y: 00312 g_string_append_printf(s, "Y=%d.pdata", *index); 00313 break; 00314 case Z: 00315 g_string_append_printf(s, "Z=%d.pdata", *index); 00316 break; 00317 } 00318 if(location == NULL) { 00319 f = g_file_new_for_path(s->str); 00320 }else{ 00321 f = g_file_resolve_relative_path(location, s->str); 00322 } 00323 }else{ 00324 f = location; 00325 } 00326 *filename = g_file_get_uri(f); 00327 //GFileIOStream *gfos = g_file_create_readwrite(f, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &e); 00328 GFileOutputStream *fos = g_file_replace(f, NULL, FALSE, 0, NULL, &e); 00329 if(e != NULL) { 00330 *err = e; 00331 return; 00332 } 00333 //GOutputStream *os = 00334 //g_io_stream_get_output_stream((GIOStream*)gfos); 00335 GDataOutputStream *dos = g_data_output_stream_new((GOutputStream*)fos); 00336 if(index != NULL) { 00337 switch(c) { 00338 case X: 00339 g_string_printf(s, "#Y(%s)%cZ(%s)%c(%s)\n", coord_units, sepchar, coord_units, sepchar, density_units); 00340 break; 00341 case Y: 00342 g_string_printf(s, "#X(%s)%cZ(%s)%c(%s)\n", coord_units, sepchar, coord_units, sepchar, density_units); 00343 break; 00344 case Z: 00345 g_string_printf(s, "#X(%s)%cY(%s)%c(%s)\n", coord_units, sepchar, coord_units, sepchar, density_units); 00346 break; 00347 } 00348 }else{ 00349 g_string_printf(s, "#X(%s)%cY(%s)%cZ(%s)%c(%s)\n", coord_units, sepchar, coord_units, sepchar, coord_units, sepchar, density_units); 00350 } 00351 e=NULL; 00352 char *str; 00353 g_data_output_stream_put_string(dos, s->str, NULL, &e); 00354 if(e != NULL) { 00355 *err = e; 00356 g_string_free(s, TRUE); 00357 e=NULL; 00358 //g_io_stream_close((GIOStream*)gfos, NULL, &e); 00359 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00360 if(e != NULL) { 00361 fprintf(stderr, "wavefunction::write_density_slice: had an error (%s) while writing string (%s), but had another error (%s) while closing the file (%s)!\n", (*err)->message, s->str, e->message, str=g_file_get_uri(f)); 00362 g_free(str); 00363 } 00364 return; 00365 } 00366 for(int k=0; k<d->N[2]; k++) { 00367 if((index != NULL) && (c == Z) && (k != *index)) continue; 00368 for(int j=0; j<d->N[1]; j++) { 00369 if((index != NULL) && (c == Y) && (j != *index)) continue; 00370 for(int i=0; i<d->N[0]; i++) { 00371 if((index != NULL) && (c == X) && (i != *index)) continue; 00372 e=NULL; 00373 if(index != NULL) { 00374 switch(c) { 00375 case X: 00376 g_string_printf(s, "%g%c%g%c%g\n", j*(d->dx[1]), sepchar, k*(d->dx[2]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 00377 break; 00378 case Y: 00379 g_string_printf(s, "%g%c%g%c%g\n", i*(d->dx[0]), sepchar, k*(d->dx[2]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 00380 break; 00381 case Z: 00382 g_string_printf(s, "%g%c%g%c%g\n", i*(d->dx[0]), sepchar, j*(d->dx[1]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 00383 break; 00384 } 00385 }else{ 00386 g_string_printf(s, "%g%c%g%c%g%c%g\n", i*(d->dx[0]), sepchar, j*(d->dx[1]), sepchar, k*(d->dx[2]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 00387 } 00388 g_data_output_stream_put_string(dos, s->str, NULL, &e); 00389 if(e != NULL) { 00390 *err = e; 00391 g_string_free(s, TRUE); 00392 e=NULL; 00393 //g_io_stream_close(os, NULL, &e); 00394 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00395 if(e != NULL) { 00396 fprintf(stderr, "wavefunction::write_density_slice: had an error (%s) while writing string (%s), but had another error (%s) while closing the file (%s)!\n", (*err)->message, s->str, e->message, str=g_file_get_uri(f)); 00397 g_free(str); 00398 } 00399 return; 00400 } 00401 } 00402 } 00403 } 00404 //g_io_stream_close((GIOStream*)gfos, NULL, &e); 00405 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00406 if(e != NULL) { 00407 *err = e; 00408 } 00409 g_string_free(s, TRUE); 00410 } 00411 00412 void write_density_sweep_slice(enum coord c, const int* index, const struct density* d, char** filename, GError **err, GFile *location, double maxval, int pixel_strategy) { 00413 /*If we're iterating on an index, go to the next loop unless the index is right*/ 00414 GError *e; 00415 GString *s = g_string_new(""); 00416 switch(c) { 00417 case X: 00418 g_string_append_printf(s, "X=%d.pbm", *index); 00419 break; 00420 case Y: 00421 g_string_append_printf(s, "Y=%d.pbm", *index); 00422 break; 00423 case Z: 00424 g_string_append_printf(s, "Z=%d.pbm", *index); 00425 break; 00426 } 00427 GFile* f; 00428 if(location == NULL) { 00429 f = g_file_new_for_path(s->str); 00430 }else{ 00431 f = g_file_resolve_relative_path(location, s->str); 00432 } 00433 *filename = g_file_get_uri(f); 00434 e = NULL; 00435 //GFileIOStream *gfos = g_file_create_readwrite(f, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &e); 00436 GFileOutputStream *fos = g_file_replace(f, NULL, FALSE, 0, NULL, &e); 00437 if(e != NULL) { 00438 *err = e; 00439 return; 00440 } 00441 //GOutputStream *os = g_io_stream_get_output_stream((GIOStream*)gfos); 00442 char *str; 00443 /*Calculate the width and height of the resulting image*/ 00444 s = g_string_new("P6\n"); 00445 /*Height and width of the image. Format is width, whitespace, height*/ 00446 int invert_coord = Z; 00447 switch(c) { 00448 case X: 00449 /*In x sweep, width is y height is z*/ 00450 g_string_append_printf(s, "%d\t%d\n", d->N[1], d->N[2]); 00451 invert_coord=Z; 00452 break; 00453 case Y: 00454 /*In y sweep, width is x height is z*/ 00455 g_string_append_printf(s, "%d\t%d\n", d->N[0], d->N[2]); 00456 invert_coord=Z; 00457 break; 00458 case Z: 00459 /*In z sweep, width is x height is y*/ 00460 g_string_append_printf(s, "%d\t%d\n", d->N[0], d->N[1]); 00461 invert_coord=Y; 00462 break; 00463 } 00464 /*Notes from the above: 00465 ** x is always a width (Y, Z sweeps) 00466 ** z is always a height (X, Y sweeps) 00467 ** y is a width if Z sweep, height if X 00468 ** The below loop should be right: rows are x, then y if not x 00469 */ 00470 g_string_append_printf(s, "%d\n", MAX_PIXEL_VAL); 00471 #ifdef DEBUG3 00472 fprintf(stderr, "wavefunc::write_density_sweep_slice: write header %s\n", s->str); 00473 #endif 00474 e=NULL; 00475 g_output_stream_write((GOutputStream*)fos, s->str, s->len, NULL, &e); 00476 if(e != NULL) { 00477 *err = e; 00478 g_string_free(s, TRUE); 00479 e=NULL; 00480 g_io_stream_close((GIOStream*)fos, NULL, &e); 00481 if(e != NULL) { 00482 fprintf(stderr, "wavefunction::write_density_slice: had an error (%s) while writing string (%s), but had another error (%s) while closing the file (%s)!\n", (*err)->message, s->str, e->message, str=g_file_get_uri(f)); 00483 g_free(str); 00484 } 00485 return; 00486 } 00487 double val; 00488 double v; 00489 double oo_maxval = 1.0/maxval; 00490 char set[3]; 00491 /**\note that the indices in the dotcode go from bottom to top, while the columns in the ppm file go from top to bottom; we need to go backwards here in order for the image to correspond to what the user is expecting to see*/ 00492 for(int k=0; k<(d->N[2]); k++) { 00493 if((c == Z) && (k != *index)) continue; 00494 for(int j=0; j<(d->N[1]); j++) { 00495 if((c == Y) && (j != *index)) continue; 00496 for(int i=0; i<(d->N[0]); i++) { 00497 if((c == X) && (i != *index)) continue; 00498 e=NULL; 00499 v = (d->storage[get_density_storage_index((invert_coord==X)?(d->N[0]-i-1):i, (invert_coord==Y)?(d->N[1]-j-1):j, (invert_coord==Z)?(d->N[2]-k-1):k, d->N[0], d->N[1])]); 00500 /*oo_maxval is already absolute value*/ 00501 if(pixel_strategy == 1) { 00502 val = log(oo_maxval*fabs(v)+1)/log(2); 00503 }else if(pixel_strategy == 2) { 00504 val = (1.0-exp(oo_maxval*fabs(v)))/(1.0-M_E); 00505 }else{ 00506 val = fabs(oo_maxval*v); 00507 } 00508 /*use the following color scheme: blue is positive, red is neg.*/ 00509 if(v>0) { 00510 set[0]=set[1]=0; 00511 set[2] = (char)(MAX_PIXEL_VAL*val); 00512 }else{ 00513 set[2]=set[1]=0; 00514 set[0] = (char)(MAX_PIXEL_VAL*val); 00515 } 00516 #ifdef DEBUG3 00517 fprintf(stderr, "wavefunc::write_density_sweep_slice: i=%d j=%d k=%d val=%g->%d \n", i, j, k, val, set[0]); 00518 #endif 00519 g_output_stream_write((GOutputStream*)fos, set, 3, NULL, &e); 00520 if(e != NULL) { 00521 *err = e; 00522 g_string_free(s, TRUE); 00523 e=NULL; 00524 //g_io_stream_close((GIOStream*)gfos, NULL, &e); 00525 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00526 if(e != NULL) { 00527 fprintf(stderr, "wavefunction::write_density_slice: had an error (%s) while writing (%d,%d,%d->%g->%d), but had another error (%s) while closing the file (%s)!\n", (*err)->message, i, j, k, val, set[0], e->message, str=g_file_get_uri(f)); 00528 g_free(str); 00529 } 00530 return; 00531 } 00532 } 00533 } 00534 } 00535 //g_io_stream_close((GIOStream*)gfos, NULL, &e); 00536 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00537 if(e != NULL) { 00538 *err = e; 00539 } 00540 g_string_free(s, TRUE); 00541 } 00542 00543 /*Gets the *magnitude* of the largest value.*/ 00544 double get_max_density_value(const struct density*d) { 00545 /*Find the max value.*/ 00546 double maxval = -1; 00547 double v; 00548 for(int k=0; k<d->N[2]; k++) { 00549 for(int j=0; j<d->N[1]; j++) { 00550 for(int i=0; i<d->N[0]; i++) { 00551 v = d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]; 00552 if(fabs(v) > maxval) { 00553 maxval = fabs(v); 00554 } 00555 } 00556 } 00557 } 00558 return maxval; 00559 } 00560 00561 void write_density_sweep(enum coord c, const struct density* d, char** filename, GError **err, GFile* location, int pixel_strategy) { 00562 /*If we're iterating on an index, go to the next loop unless the index is right*/ 00563 GError *e; 00564 GString *s = g_string_new("sweep_"); 00565 switch(c) { 00566 case X: 00567 g_string_append_printf(s, "x"); 00568 break; 00569 case Y: 00570 g_string_append_printf(s, "y"); 00571 break; 00572 case Z: 00573 g_string_append_printf(s, "z"); 00574 break; 00575 } 00576 GFile* f; 00577 if(location == NULL) { 00578 f = g_file_new_for_path(s->str); 00579 }else{ 00580 f = g_file_resolve_relative_path(location, s->str); 00581 } 00582 e=NULL; 00583 g_file_make_directory_with_parents(f, NULL, &e); 00584 if((e != NULL) && (e->code != G_IO_ERROR_EXISTS)) { 00585 char* fn = g_file_get_uri(f); 00586 fprintf(stderr, "E1\n"); 00587 if(e == NULL) { 00588 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 32, "wavefunction::write_density_sweep: unable to make directory for writing density sweep (%s)", fn); 00589 }else{ 00590 g_propagate_prefixed_error(err, e, "wavefunction::write_density_sweep: unable to make directory for writing density sweep (%s): %s", fn, e->message); 00591 } 00592 free(fn); 00593 g_string_free(s, TRUE); 00594 return; 00595 } 00596 double maxval = get_max_density_value(d); 00597 /*Iterate over the sweep var*/ 00598 char *fn; 00599 for(int i=0; i<(d->N[c]); i++) { 00600 e = NULL; 00601 write_density_sweep_slice(c, &i, d, &fn, &e, f, maxval, pixel_strategy); 00602 if(e != NULL) { 00603 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 32, "Error writing slice into %s: %s", fn, e->message); 00604 g_error_free(e); 00605 free(fn); 00606 return; 00607 } 00608 free(fn); 00609 } 00610 *filename = s->str; 00611 /*We don't want to return false, since we're not getting the filename.*/ 00612 g_string_free(s, FALSE); 00613 } 00614 00615 00616 struct density* new_density(const int* N, const double* dx, double initial_value) { 00617 struct density* d = (struct density*)malloc(sizeof(struct density)); 00618 if(d == NULL) { 00619 return NULL; 00620 } 00621 for(int i=0; i<3; i++) { 00622 d->N[i] = N[i]; 00623 d->dx[i] = dx[i]; 00624 } 00625 d->storage = (double*)malloc(N[0]*N[1]*N[2]*sizeof(double)); 00626 if(d->storage == NULL) { 00627 free(d); 00628 return NULL; 00629 } 00630 int k, j, i; 00631 #ifdef OPENMP 00632 #pragma omp parallel for private(k, j, i) 00633 #endif 00634 for(k=0; k<d->N[2]; k++) { 00635 for(j=0; j<d->N[1]; j++) { 00636 for(i=0; i<d->N[0]; i++) { 00637 d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])] 00638 = initial_value; 00639 } 00640 } 00641 } 00642 return d; 00643 } 00644 struct density* new_density_copy(const struct density* orig) { 00645 struct density* d = (struct density*)malloc(sizeof(struct density)); 00646 if(d == NULL) { 00647 return NULL; 00648 } 00649 for(int i=0; i<3; i++) { 00650 d->N[i] = orig->N[i]; 00651 d->dx[i] = orig->dx[i]; 00652 } 00653 d->storage = (double*)malloc((d->N[0])*(d->N[1])*(d->N[2])*sizeof(double)); 00654 if(d->storage == NULL) { 00655 free(d); 00656 return NULL; 00657 } 00658 int k, j, i; 00659 #ifdef OPENMP 00660 #pragma omp parallel for private(k, j, i) 00661 #endif 00662 for(k=0; k<d->N[2]; k++) { 00663 for(j=0; j<d->N[1]; j++) { 00664 for(i=0; i<d->N[0]; i++) { 00665 d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])] 00666 = orig->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]; 00667 } 00668 } 00669 } 00670 return d; 00671 } 00672 00673 int op_density_to_density(struct density* to, enum density_op op, const struct density* from) { 00674 for(int i=0; i<3; i++) { 00675 if((to->N[i] != from->N[i]) || (to->dx[i] != from->dx[i])) { 00676 return 1; 00677 } 00678 } 00679 /*The switch can probably be lifted out of the loops by the compiler.*/ 00680 int k, j, i; 00681 #ifdef OPENMP 00682 #pragma omp parallel for private(k, j, i) 00683 #endif 00684 for(k=0; k<to->N[2]; k++) { 00685 for(j=0; j<to->N[1]; j++) { 00686 for(i=0; i<to->N[0]; i++) { 00687 switch(op) { 00688 case ASSIGN: 00689 *get_density_storage_at(i, j, k, to) = *get_density_storage_at_c(i, j, k, from); 00690 case ADD_EQUALS: 00691 to->storage[get_density_storage_index(i, j, k, to->N[0], to->N[1])] 00692 += from->storage[get_density_storage_index(i, j, k, from->N[0], from->N[1])] 00693 ; 00694 break; 00695 case MINUS_EQUALS: 00696 to->storage[get_density_storage_index(i, j, k, to->N[0], to->N[1])] 00697 -= from->storage[get_density_storage_index(i, j, k, from->N[0], from->N[1])] 00698 ; 00699 break; 00700 case MUL_EQUALS: 00701 to->storage[get_density_storage_index(i, j, k, to->N[0], to->N[1])] 00702 *= from->storage[get_density_storage_index(i, j, k, from->N[0], from->N[1])] 00703 ; 00704 break; 00705 case DIV_EQUALS: 00706 to->storage[get_density_storage_index(i, j, k, to->N[0], to->N[1])] 00707 /= from->storage[get_density_storage_index(i, j, k, from->N[0], from->N[1])] 00708 ; 00709 break; 00710 } 00711 } 00712 } 00713 } 00714 return 0; 00715 } 00716 00717 void free_density(struct density* d) { 00718 if(d == NULL) return; 00719 if(d->storage != NULL) free(d->storage); 00720 free(d); 00721 } 00722 00723 struct dotcode_grid* dotcode_grid_from_density(const struct density *d, GError **err) { 00724 struct dotcode_grid* g = (struct dotcode_grid*)malloc(sizeof(struct dotcode_grid)); 00725 if(unlikely(g == NULL)) { 00726 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 100, "wavefunction::dotcode_grid_from_density: Error allocating memory for new dotcode_grid."); 00727 return NULL; 00728 } 00729 g->data = (struct dotcode_tensor*)malloc(sizeof(struct dotcode_tensor)); 00730 if(unlikely(g->data == NULL)) { 00731 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 101, "wavefunction::dotcode_grid_from_density: Error allocating memory for tensor for the new grid."); 00732 free(g); 00733 return NULL; 00734 } 00735 g->data->Nd = 3; 00736 g->data->metadata = g_strdup("2.0"); 00737 g->data->indices = (int*)malloc(2*(g->data->Nd)*sizeof(int)); 00738 if(unlikely(g->data->indices == NULL)) { 00739 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 102, "wavefunction::dotcode_grid_from_density: Error allocating memory for indicies in the tensor for the new grid."); 00740 free(g->data); 00741 free(g); 00742 return NULL; 00743 } 00744 for(int i=0; i<3; i++) { 00745 (g->gridsites)[i] = (struct dotcode_array*)malloc(sizeof(struct dotcode_array)); 00746 if(unlikely((g->gridsites)[i] == NULL)) { 00747 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 103, "wavefunction::dotcode_grid_from_density: Error allocating memory for the %d-th array for the new grid.", i); 00748 GError *e = NULL; 00749 for(int j=i-1; j>=0; j++) { 00750 dotcode_free_type(DOTCODE_ARRAY, (g->gridsites)[j], 1, &e, TRUE); 00751 if(e != NULL) g_error_free(e); 00752 } 00753 free(g->data->indices); 00754 free(g->data); 00755 free(g); 00756 return NULL; 00757 } 00758 (g->gridsites)[i]->t = DOTCODE_FLOAT8; 00759 (g->gridsites)[i]->imin = g->data->indices[2*i] = 0; 00760 (g->gridsites)[i]->imax = g->data->indices[2*i + 1] = d->N[i]-1; 00761 (g->gridsites)[i]->storage = (double*)malloc((d->N[i])*sizeof(double)); 00762 if(unlikely((g->gridsites)[i]->storage == NULL)) { 00763 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 104, "wavefunction::dotcode_grid_from_density: Error allocating memory for storage in the %d-th array for the new grid.", i); 00764 GError *e = NULL; 00765 for(int j=i-1; j>=0; j++) { 00766 dotcode_free_type(DOTCODE_ARRAY, (g->gridsites)[j], 1, &e, TRUE); 00767 if(e != NULL) g_error_free(e); 00768 } 00769 free(g->data->indices); 00770 free((g->gridsites)[i]); 00771 free(g->data); 00772 free(g); 00773 return NULL; 00774 } 00775 for(int j=0; j<d->N[i]; j++) ((double*)((g->gridsites)[i]->storage))[j] = j*(d->dx[i]); 00776 /*Put 0 in the center*/ 00777 //g->Ng[i] = d->N[i]-1; 00778 g->Ng[i] = 0; 00779 } 00780 g->data->t = DOTCODE_FLOAT8; 00781 g->data->metadata = g_strdup("2.0"); 00782 g->data->data = (double*)malloc((d->N[0])*(d->N[1])*(d->N[2])*sizeof(double)); 00783 if(unlikely(g->data->data == NULL)) { 00784 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 105, "wavefunction::dotcode_grid_from_density: Error allocating memory for storage in the tensor for the new grid."); 00785 GError *e = NULL; 00786 for(int j=2; j>=0; j++) { 00787 dotcode_free_type(DOTCODE_ARRAY, (g->gridsites)[j], 1, &e, TRUE); 00788 if(e != NULL) g_error_free(e); 00789 } 00790 free(g->data->indices); 00791 free(g->data); 00792 free(g); 00793 return NULL; 00794 } 00795 /*i is z 00796 *j is y 00797 *k is x 00798 */ 00799 int i, j, k; 00800 #ifdef OPENMP 00801 #pragma omp parallel for private(i, j, k) 00802 #endif 00803 for(i=0; i<d->N[2]; i++) { 00804 for(j=0; j<d->N[1]; j++) { 00805 for(k=0; k<d->N[0]; k++) { 00806 ((double*)(g->data->data))[k + (d->N[0])*(j + (d->N[1])*i)] = ev_to_hartree((d->storage)[get_density_storage_index(k, j, i, d->N[0], d->N[1])]); 00807 } 00808 } 00809 } 00810 00811 return g; 00812 } 00813 00814 struct density* expand_density_box_with_value(const struct density* od, const int* I, double value, GError **err) { 00815 struct density* d = (struct density*)malloc(sizeof(struct density)); 00816 if(d == NULL) { 00817 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 106, "libpostproc::wavefunction::expand_density_box_with_material: failed to allocate the new density structure."); 00818 return NULL; 00819 } 00820 for(int i=0; i<3; i++) { 00821 d->dx[i] = od->dx[i]; 00822 d->N[i] = od->N[i]+2*I[i]; 00823 fprintf(stderr, "dx[%d](%g)->%g d->N[%d](%d)->%d (%d+2*%d)\n", i, od->dx[i], d->dx[i], i, od->N[i], d->N[i], od->N[i], I[i]); 00824 } 00825 d->storage = (double*)malloc(sizeof(double)*(d->N[0])*(d->N[1])*(d->N[2])); 00826 if(d->storage == NULL) { 00827 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 106, "libpostproc::wavefunction::expand_density_box_with_material: failed to allocate value storage for the new density (size is %dx%dx%d=%ld", d->N[0], d->N[1], d->N[2], ((long int)d->N[0])*((long int)d->N[1])*((long int)d->N[2])); 00828 free(d); 00829 return NULL; 00830 } 00831 /*Explicitly breaking out the regions saves 1 *branch* per loop*/ 00832 /*First, the top of the box*/ 00833 int i, j, k; 00834 #ifdef OPENMP 00835 #pragma omp parallel for private(i, j, k) 00836 #endif 00837 for(k=0; k<I[2]; k++) { 00838 for(j=0; j<d->N[1]; j++) { 00839 for(i=0; i<d->N[0]; i++) { 00840 (d->storage)[get_density_storage_index(i, j, k, d->N[0], d->N[1])] = value; 00841 } 00842 } 00843 } 00844 /*Now the z-interior of the box*/ 00845 int yoffset, zoffset; 00846 #ifdef OPENMP 00847 #pragma omp parallel for private(i, j, k, yoffset, zoffset) 00848 #endif 00849 for(k=0; k<od->N[2]; k++) { 00850 zoffset = I[2]; 00851 00852 /*The lower-y outer region*/ 00853 for(j=0; j<I[1]; j++) { 00854 for(i=0; i<d->N[0]; i++) { 00855 (d->storage)[get_density_storage_index(i, j, k+zoffset, d->N[0], d->N[1])] = value; 00856 } 00857 } 00858 00859 /*Interior of the box in y (and z)*/ 00860 for(j=0; j<od->N[1]; j++) { 00861 yoffset = I[1]; 00862 00863 for(i=0; i<I[0]; i++) { 00864 (d->storage)[get_density_storage_index(i, j+yoffset, k+zoffset, d->N[0], d->N[1])] = value; 00865 } 00866 00867 /*We're in the middle region. Copy over from the source.*/ 00868 for(i=0; i<od->N[0]; i++) { 00869 (d->storage)[get_density_storage_index(i+I[0], j+yoffset, k+zoffset, d->N[0], d->N[1])] = (od->storage)[get_density_storage_index(i, j, k, od->N[0], od->N[1])]; 00870 } 00871 00872 /*we're out the back region.*/ 00873 for(i=0; i<I[0]; i++) { 00874 (d->storage)[get_density_storage_index(i+(od->N[0])+I[0], j+yoffset, k+zoffset, d->N[0], d->N[1])] = value; 00875 } 00876 00877 } 00878 00879 /*The upper-y outer region*/ 00880 for(j=0; j<I[1]; j++) { 00881 yoffset = I[1] + od->N[1]; 00882 for(i=0; i<d->N[0]; i++) { 00883 (d->storage)[get_density_storage_index(i, j+yoffset, k+zoffset, d->N[0], d->N[1])] = value; 00884 } 00885 } 00886 00887 } 00888 /*Finally, the bottom of the box*/ 00889 #ifdef OPENMP 00890 #pragma omp parallel for private(i, j, k, zoffset) 00891 #endif 00892 for(k=0; k<I[2]; k++) { 00893 zoffset = I[2] + od->N[2]; 00894 for(j=0; j<d->N[2]; j++) { 00895 for(i=0; i<d->N[0]; i++) { 00896 (d->storage)[get_density_storage_index(i, j, k+zoffset, d->N[0], d->N[1])] = value; 00897 } 00898 } 00899 } 00900 return d; 00901 } 00902 00903 struct density* expand_density_box(const struct density* od, const int* I, GError **err) { 00904 double val = od->storage[0]; 00905 for(int i=0; i<od->N[2]; i++) { 00906 if((i != 0) && (i != (od->N[2]-1))) continue; 00907 for(int j=0; j<od->N[1]; j++) { 00908 if((j != 0) && (j != (od->N[1]-1))) continue; 00909 for(int k=0; k<od->N[0]; k++) { 00910 if((k != 0) && (k != (od->N[0]-1))) continue; 00911 if((od->storage)[get_density_storage_index(k, j, i, od->N[0], od->N[1])] != val) { 00912 *err = g_error_new(WAVEFUNC_GERROR_DOMAIN, 106, "libpostproc::wavefunction::expand_density_box: value is not identical across the entire outside of the box! (was, %g is %g at %d/%d/%d)", val, (od->storage)[get_density_storage_index(k, j, i, od->N[0], od->N[1])], k, j, i); 00913 return NULL; 00914 } 00915 } 00916 } 00917 } 00918 return expand_density_box_with_value(od, I, val, err); 00919 } 00920 00921 void write_density_povray(const struct density* d, GFile *towrite, int pixel_strategy, GError **err) { 00922 GError *e = NULL; 00923 GFileOutputStream *fos = g_file_replace(towrite, NULL, FALSE, 0, NULL, &e); 00924 if(e != NULL) { 00925 g_propagate_prefixed_error(err, e, "libpostproc::lp_wavefunction.c::write_density_povray: Error opening output file."); 00926 return; 00927 } 00928 00929 double oo_maxval = 1.0/get_max_density_value(d); 00930 00931 /*First, write out the initial chunks.*/ 00932 GString* s = g_string_new("//Density vidualziation generated by libpostproc\n"); 00933 s = g_string_append(s, "//\n//Important switches for the end-user are located here.\n"); 00934 s = g_string_append(s, "//Below the ====BLOCKS==== label are the individual data blocks.\n\n"); 00935 s = g_string_append(s, "#include \"colors.inc\"\n"); 00936 s = g_string_append(s, "global_settings { ambient_light rgb<1, 1, 1> }\n"); 00937 s = g_string_append(s, "//background {rgb<1,1,1>}\n\n"); 00938 s = g_string_append(s, "#declare pos_block_color = rgb<0, 0, 1>;\n\n"); 00939 s = g_string_append(s, "#declare neg_block_color = rgb<1, 0, 0>;\n\n"); 00940 g_string_append_printf(s, "camera {\nlocation <%g, %g, %g>\nlook_at <%g, %g, %g>\n}\n\n", 00941 d->N[0]*d->dx[0]*1.5, d->N[1]*d->dx[1]*1.5, -d->N[2]*d->dx[2]*1.5, 00942 d->N[0]*d->dx[0]*0.5, d->N[1]*d->dx[1]*0.5, -d->N[2]*d->dx[2]*0.5); 00943 g_string_append_printf(s, "light_source {<%g, %g, %g> color rgb<1, 1, 1> shadowless}\n", 00944 d->N[0]*d->dx[0]*1.5, d->N[1]*d->dx[1]*1.5, -d->N[2]*d->dx[2]*1.5); 00945 s = g_string_append(s, "//====BLOCKS=====\n"); 00946 s = g_string_append(s, "merge {\n"); 00947 g_output_stream_write((GOutputStream*)fos, s->str, s->len, NULL, &e); 00948 if(e != NULL) { 00949 g_propagate_prefixed_error(err, e, "libpostproc::wavefunction::write_density_povray: Error while writing header to output stream: %s", e->message); 00950 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00951 return; 00952 } 00953 00954 double v, val; 00955 for(int k=0; k<d->N[2]; k++) { 00956 for(int j=0; j<d->N[1]; j++) { 00957 for(int i=0; i<d->N[0]; i++) { 00958 v = d->storage[get_density_storage_index_(i, j, k, d->N[0], d->N[1])]; 00959 /*oo_maxval is already absolute value*/ 00960 if(pixel_strategy == 1) { 00961 val = log(oo_maxval*fabs(v)+1)/log(2); 00962 }else if(pixel_strategy == 2) { 00963 val = (1.0-exp(oo_maxval*fabs(v)))/(1.0-M_E); 00964 }else{ 00965 val = fabs(oo_maxval*v); 00966 } 00967 00968 if(val < THRESHOLD) continue; 00969 /*Break the floating-point chunk into pieces. 1 is max, 0 is min, and we have N steps*/ 00970 val *= NUM_STEPS; 00971 val = floor(val); 00972 /*Don't waste the processing time if it's totally clear!*/ 00973 if(val == 0) continue; 00974 val /= NUM_STEPS; 00975 00976 00977 g_string_printf(s, "box {\n\t<%g, %g, %g>\n\t<%g, %g, %g>\n\ttexture {\n", i*d->dx[0], j*d->dx[1], -k*d->dx[2], (i+1)*d->dx[0], (j+1)*d->dx[1], -(k+1)*d->dx[2]); 00978 g_string_append_printf(s, "\t\tpigment{\n\t\t\tcolor %s_block_color\n\t\t\ttransmit %g\n\t\t}\n", (v>=0)?"pos":"neg", 1.0-val); 00979 s = g_string_append(s, "\t}\n}\n\n"); 00980 g_output_stream_write((GOutputStream*)fos, s->str, s->len, NULL, &e); 00981 if(e != NULL) { 00982 g_propagate_prefixed_error(err, e, "libpostproc::wavefunction::write_density_povray: Error while writing block <%d,%d,%d> to output stream: %s", i, j, k, e->message); 00983 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00984 return; 00985 } 00986 } 00987 } 00988 } 00989 00990 /*File footer*/ 00991 g_string_printf(s, "}\n"); 00992 g_output_stream_write((GOutputStream*)fos, s->str, s->len, NULL, &e); 00993 if(e != NULL) { 00994 g_propagate_prefixed_error(err, e, "libpostproc::wavefunction::write_density_povray: Error while writing file footer: %s\n", e->message); 00995 g_output_stream_close((GOutputStream*)fos, NULL, &e); 00996 return; 00997 } 00998 00999 g_output_stream_close((GOutputStream*)fos, NULL, &e); 01000 if(e != NULL) { 01001 *err = e; 01002 } 01003 } 01004 01005 01006 struct density* get_double_resolution_density(const struct density* original, int auto_scale) { 01007 int N_new[3]; 01008 double dx[3]; 01009 for(int i=0; i<3; i++) { 01010 N_new[i] = (original->N[i])*2-1; 01011 dx[i] = original->dx[i]/2.0; 01012 } 01013 struct density* nd = new_density(N_new, dx, 0); 01014 if(nd == NULL) return NULL; 01015 /*Now do the interpolation. We loop over the old points, setting the new ones in the inner loop (avoids branch prediction misses if we iterated over the new grid.*/ 01016 long x, y, z; 01017 double a, b, c, d, e, f, g, h; 01018 #ifdef OPENMP 01019 #pragma omp parallel for private(y, x, a, b, c, d, e, f, g, h) 01020 #endif 01021 for(z=0; z<original->N[2]-1; z++) { 01022 for(y=0; y<original->N[1]-1; y++) { 01023 for(x=0; x<original->N[0]-1; x++) { 01024 /*For notational simplicity, we'll define the corners of the cube here. 01025 *\note Starting from the top (x=0 y=0 z=0) and going clockwise (y=1 x=0 z=0), and then the same for the upper 4 points*/ 01026 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01027 b=original->storage[get_density_storage_index(x, y+1, z, original->N[0], original->N[1])]; 01028 c=original->storage[get_density_storage_index(x+1, y+1, z, original->N[0], original->N[1])]; 01029 d=original->storage[get_density_storage_index(x+1, y, z, original->N[0], original->N[1])]; 01030 e=original->storage[get_density_storage_index(x, y, z+1, original->N[0], original->N[1])]; 01031 f=original->storage[get_density_storage_index(x, y+1, z+1, original->N[0], original->N[1])]; 01032 g=original->storage[get_density_storage_index(x+1, y+1, z+1, original->N[0], original->N[1])]; 01033 h=original->storage[get_density_storage_index(x+1, y, z+1, original->N[0], original->N[1])]; 01034 /*Set the original 4 sites (the other sites in the new cell will be set by later iterations*/ 01035 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01036 nd->storage[get_density_storage_index(2*(x+1), 2*y, 2*z, N_new[0], N_new[1])] = d; 01037 nd->storage[get_density_storage_index(2*x, 2*(y+1), 2*z, N_new[0], N_new[1])] = b; 01038 nd->storage[get_density_storage_index(2*x, 2*y, 2*(z+1), N_new[0], N_new[1])] = e; 01039 /*Set the axial sites*/ 01040 nd->storage[get_density_storage_index(2*x+1, 2*y, 2*z, N_new[0], N_new[1])] = (a+d)/2.0; 01041 nd->storage[get_density_storage_index(2*x, 2*y+1, 2*z, N_new[0], N_new[1])] = (a+b)/2.0; 01042 nd->storage[get_density_storage_index(2*x, 2*y, 2*z+1, N_new[0], N_new[1])] = (a+e)/2.0; 01043 /*Set the face sites*/ 01044 nd->storage[get_density_storage_index(2*x+1, 2*y+1, 2*z, N_new[0], N_new[1])] = (a+b+c+d)/4.0; 01045 nd->storage[get_density_storage_index(2*x+1, 2*y, 2*z+1, N_new[0], N_new[1])] = (a+d+e+h)/4.0; 01046 nd->storage[get_density_storage_index(2*x, 2*y+1, 2*z+1, N_new[0], N_new[1])] = (a+b+e+f)/4.0; 01047 /*Set the interior point*/ 01048 nd->storage[get_density_storage_index(2*x+1, 2*y+1, 2*z+1, N_new[0], N_new[1])] = (a+b+c+d+e+f+g+h)/8.0; 01049 #ifdef DEBUG3 01050 fprintf(stderr, "density doubling %ld %ld %ld: a=%g b=%g c=%g d=%g e=%g f=%g g=%g h=%g\n", x, y, z, a, b, c, d, e, f, g, h); 01051 fprintf(stderr, "\toriginal: %ld %ld %ld = %g, %ld %ld %ld = %g, %ld %ld %ld = %g, %ld %ld %ld = %g\n", 01052 2*x, 2*y, 2*z, *get_density_storage_at_c_(2*x, 2*y, 2*z, nd), 01053 2*(x+1), 2*y, 2*z, *get_density_storage_at_c_(2*(x+1), 2*y, 2*z, nd), 01054 2*x, 2*(y+1), 2*z, *get_density_storage_at_c_(2*x, 2*(y+1), 2*z, nd), 01055 2*x, 2*y, 2*(z+1), *get_density_storage_at_c_(2*x, 2*y, 2*(z+1), nd) 01056 ); 01057 fprintf(stderr, "\taxial: %ld %ld %ld = %g, %ld %ld %ld = %g, %ld %ld %ld = %g\n", 01058 2*x+1, 2*y, 2*z, *get_density_storage_at_c_(2*x+1, 2*y, 2*z, nd), 01059 2*x, 2*y+1, 2*z, *get_density_storage_at_c_(2*x, 2*y+1, 2*z, nd), 01060 2*x, 2*y, 2*z+1, *get_density_storage_at_c_(2*x, 2*y, 2*z+1, nd) 01061 ); 01062 fprintf(stderr, "\tface: %ld %ld %ld = %g, %ld %ld %ld = %g, %ld %ld %ld = %g\n", 01063 2*x+1, 2*y+1, 2*z, *get_density_storage_at_c_(2*x+1, 2*y+1, 2*z, nd), 01064 2*x+1, 2*y, 2*z+1, *get_density_storage_at_c_(2*x+1, 2*y, 2*z+1, nd), 01065 2*x, 2*y+1, 2*z+1, *get_density_storage_at_c_(2*x, 2*y+1, 2*z+1, nd) 01066 ); 01067 fprintf(stderr, "\tinterior: %ld %ld %ld = %g\n", 01068 2*x+1, 2*y+1, 2*z+1, *get_density_storage_at_c_(2*x+1, 2*y+1, 2*z+1, nd) 01069 ); 01070 #endif 01071 } 01072 } 01073 } 01074 /*All of the points but the final x y and z planes have been set. There are still axial and facial sites to be set on these.*/ 01075 /*x face*/ 01076 x=original->N[0]-1; 01077 #ifdef OPENMP 01078 #pragma omp parallel for private(y, a, b, e, f) 01079 #endif 01080 for(z=0; z<original->N[2]-1; ++z) { 01081 for(y=0; y<original->N[1]-1; ++y) { 01082 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01083 b=original->storage[get_density_storage_index(x, y+1, z, original->N[0], original->N[1])]; 01084 e=original->storage[get_density_storage_index(x, y, z+1, original->N[0], original->N[1])]; 01085 f=original->storage[get_density_storage_index(x, y+1, z+1, original->N[0], original->N[1])]; 01086 /*Set the original sites (the other sites in the new cell will be set by later iterations*/ 01087 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01088 nd->storage[get_density_storage_index(2*x, 2*(y+1), 2*z, N_new[0], N_new[1])] = b; 01089 nd->storage[get_density_storage_index(2*x, 2*y, 2*(z+1), N_new[0], N_new[1])] = e; 01090 /*Set the axial sites*/ 01091 nd->storage[get_density_storage_index(2*x, 2*y+1, 2*z, N_new[0], N_new[1])] = (a+b)/2.0; 01092 nd->storage[get_density_storage_index(2*x, 2*y, 2*z+1, N_new[0], N_new[1])] = (a+e)/2.0; 01093 /*Set the face sites*/ 01094 nd->storage[get_density_storage_index(2*x, 2*y+1, 2*z+1, N_new[0], N_new[1])] = (a+b+e+f)/4.0; 01095 } 01096 } 01097 /*y face*/ 01098 y=original->N[1]-1; 01099 #ifdef OPENMP 01100 #pragma omp parallel for private(x, a, d, e, h) 01101 #endif 01102 for(z=0; z<original->N[2]-1; ++z) { 01103 for(x=0; x<original->N[0]-1; ++x) { 01104 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01105 d=original->storage[get_density_storage_index(x+1, y, z, original->N[0], original->N[1])]; 01106 e=original->storage[get_density_storage_index(x, y, z+1, original->N[0], original->N[1])]; 01107 h=original->storage[get_density_storage_index(x+1, y, z+1, original->N[0], original->N[1])]; 01108 /*Set the original sites (the other sites in the new cell will be set by later iterations*/ 01109 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01110 nd->storage[get_density_storage_index(2*(x+1), 2*y, 2*z, N_new[0], N_new[1])] = d; 01111 nd->storage[get_density_storage_index(2*x, 2*y, 2*(z+1), N_new[0], N_new[1])] = e; 01112 /*Set the axial sites*/ 01113 nd->storage[get_density_storage_index(2*x+1, 2*y, 2*z, N_new[0], N_new[1])] = (a+d)/2.0; 01114 nd->storage[get_density_storage_index(2*x, 2*y, 2*z+1, N_new[0], N_new[1])] = (a+e)/2.0; 01115 /*Set the face sites*/ 01116 nd->storage[get_density_storage_index(2*x+1, 2*y, 2*z+1, N_new[0], N_new[1])] = (a+d+e+h)/4.0; 01117 } 01118 } 01119 z=original->N[2]-1; 01120 #ifdef OPENMP 01121 #pragma omp parallel for private(x, a, b, c, d) 01122 #endif 01123 for(y=0; y<original->N[1]-1; ++y) { 01124 for(x=0; x<original->N[0]-1; ++x) { 01125 /*we only get the one set of z sites since the next z site is not extant*/ 01126 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01127 b=original->storage[get_density_storage_index(x, y+1, z, original->N[0], original->N[1])]; 01128 c=original->storage[get_density_storage_index(x+1, y+1, z, original->N[0], original->N[1])]; 01129 d=original->storage[get_density_storage_index(x+1, y, z, original->N[0], original->N[1])]; 01130 /*Set the original sites (the other sites in the new cell will be set by later iterations*/ 01131 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01132 nd->storage[get_density_storage_index(2*(x+1), 2*y, 2*z, N_new[0], N_new[1])] = d; 01133 nd->storage[get_density_storage_index(2*x, 2*(y+1), 2*z, N_new[0], N_new[1])] = b; 01134 /*Set the axial sites*/ 01135 nd->storage[get_density_storage_index(2*x+1, 2*y, 2*z, N_new[0], N_new[1])] = (a+d)/2.0; 01136 nd->storage[get_density_storage_index(2*x, 2*y+1, 2*z, N_new[0], N_new[1])] = (a+b)/2.0; 01137 /*Set the face sites*/ 01138 nd->storage[get_density_storage_index(2*x+1, 2*y+1, 2*z, N_new[0], N_new[1])] = (a+b+c+d)/4.0; 01139 } 01140 } 01141 /*Finally, we have some axial sites that still haven't been set along the very edges:*/ 01142 /*x axis*/ 01143 y=original->N[1]-1; 01144 z=original->N[2]-1; 01145 #ifdef OPENMP 01146 #pragma omp parallel for private(a, d) 01147 #endif 01148 for(x=0; x<original->N[0]-1; ++x) { 01149 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01150 d=original->storage[get_density_storage_index(x+1, y, z, original->N[0], original->N[1])]; 01151 /*Set the original sites (the other sites in the new cell will be set by later iterations*/ 01152 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01153 nd->storage[get_density_storage_index(2*(x+1), 2*y, 2*z, N_new[0], N_new[1])] = d; 01154 /*Set the axial sites*/ 01155 nd->storage[get_density_storage_index(2*x+1, 2*y, 2*z, N_new[0], N_new[1])] = (a+d)/2.0; 01156 } 01157 /*y axis*/ 01158 x=original->N[0]-1; 01159 z=original->N[2]-1; 01160 #ifdef OPENMP 01161 #pragma omp parallel for private(a, b) 01162 #endif 01163 for(y=0; y<original->N[1]-1; ++y) { 01164 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01165 b=original->storage[get_density_storage_index(x, y+1, z, original->N[0], original->N[1])]; 01166 /*Set the original sites (the other sites in the new cell will be set by later iterations*/ 01167 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01168 nd->storage[get_density_storage_index(2*x, 2*(y+1), 2*z, N_new[0], N_new[1])] = b; 01169 /*Set the axial sites*/ 01170 nd->storage[get_density_storage_index(2*x, 2*y+1, 2*z, N_new[0], N_new[1])] = (a+b)/2.0; 01171 } 01172 /*z axis*/ 01173 x=original->N[0]-1; 01174 y=original->N[1]-1; 01175 #ifdef OPENMP 01176 #pragma omp parallel for private(a, e) 01177 #endif 01178 for(z=0; z<original->N[2]-1; ++z) { 01179 a=original->storage[get_density_storage_index(x, y, z, original->N[0], original->N[1])]; 01180 e=original->storage[get_density_storage_index(x, y, z+1, original->N[0], original->N[1])]; 01181 /*Set the original sites (the other sites in the new cell will be set by later iterations*/ 01182 nd->storage[get_density_storage_index(2*x, 2*y, 2*z, N_new[0], N_new[1])] = a; 01183 nd->storage[get_density_storage_index(2*x, 2*y, 2*(z+1), N_new[0], N_new[1])] = e; 01184 /*Set the axial sites*/ 01185 nd->storage[get_density_storage_index(2*x, 2*y, 2*z+1, N_new[0], N_new[1])] = (a+e)/2.0; 01186 } 01187 /*Set the original very corner site*/ 01188 nd->storage[get_density_storage_index(2*(original->N[0]-1), 2*(original->N[1]-1), 2*(original->N[2]-1), N_new[0], N_new[1])] = original->storage[get_density_storage_index(original->N[0]-1, original->N[1]-1, original->N[2]-1, original->N[0], original->N[1])]; 01189 if(auto_scale != 0) { 01190 double scaling=1; 01191 int invert=0; 01192 if(auto_scale < 0) { 01193 /*Units are grid size, not inverse grid size, so invert*/ 01194 invert=1; 01195 /*Set it so we get the bits back out*/ 01196 auto_scale=-auto_scale; 01197 } 01198 /**since units are f/(dx*dy*dz) -> f/(dx/2*dy/2*dz/2) we need to *divide* f by 2*2*2 to maintain the proper density (f/(dx*dy*dz)->(f/(2*2*2*dx/2*dy/2*dz/2))*/ 01199 if(auto_scale & 1) { 01200 scaling /= 2; 01201 } 01202 if(auto_scale & 2) { 01203 scaling /= 2; 01204 } 01205 if(auto_scale & 4) { 01206 scaling /= 2; 01207 } 01208 if(invert) scaling = 1.0/scaling; 01209 fprintf(stderr, "DOUBLE-RES SCALING BY %g\n", scaling); 01210 density_mul_by_const(nd, scaling); 01211 } 01212 return nd; 01213 } 01214 01215 01216 /**Gets a new density with a half-resolution grid, using an average for assignment 01217 *\param original original density 01218 *\return pointer to a density, or NULL if memory allocation failed. 01219 *\note the new grid doesn't add an outside row of new sites; it only places a new grid site between two existing ones 01220 */ 01221 struct density* get_half_resolution_density(const struct density* original, GError **e, int auto_scale) { 01222 int N_new[3]; 01223 double dx[3]; 01224 for(int i=0; i<3; i++) { 01225 if(original->N[i]%2 != 1) { 01226 *e = g_error_new(WAVEFUNC_GERROR_DOMAIN, 1, "lp_wavefunction.c::get_half_resolution_density: ERROR: %d-th coordinate is not odd, so there's no clean half-resolution grid! (This feature is possible and may be added at some point in the future; at the moment, this function is solely for bringining the density back to the original resolution after doubling", i); 01227 return NULL; 01228 } 01229 N_new[i] = (original->N[i]+1)/2; 01230 dx[i] = original->dx[i]*2.0; 01231 } 01232 struct density* nd = new_density(N_new, dx, 0); 01233 if(nd == NULL) { 01234 *e = g_error_new(WAVEFUNC_GERROR_DOMAIN, 1, "lp_wavefunction.c::get_half_resolution_density: ERROR: failed to allocate space for half-resolution density."); 01235 return NULL; 01236 } 01237 for(long z=0; z<N_new[2]; ++z) { 01238 for(long y=0; y<N_new[1]; ++y) { 01239 for(long x=0; x<N_new[0]; ++x) { 01240 /*Simple version: just grab the point and neglect the double-res points*/ 01241 nd->storage[get_density_storage_index(x, y, z, N_new[0], N_new[1])] = original->storage[get_density_storage_index(2*x, 2*y, 2*z, original->N[0], original->N[1])]; 01242 } 01243 } 01244 } 01245 if(auto_scale != 0) { 01246 double scaling=1; 01247 int invert=1; 01248 if(auto_scale < 0) { 01249 /*Units are grid size, not inverse grid size, so don't (this is inverse operation of doubling the resolution)*/ 01250 invert=0; 01251 /*Set it so we get the bits back out*/ 01252 auto_scale=-auto_scale; 01253 } 01254 if(auto_scale & 1) { 01255 scaling /= 2; 01256 } 01257 if(auto_scale & 2) { 01258 scaling /= 2; 01259 } 01260 if(auto_scale & 4) { 01261 scaling /= 2; 01262 } 01263 if(invert) scaling = 1.0/scaling; 01264 fprintf(stderr, "HALF-RES SCALING BY %g\n", scaling); 01265 density_mul_by_const(nd, scaling); 01266 } 01267 return nd; 01268 } 01269 01270 void density_execute_callback(const struct density* d, void (*callback)(int x, int y, int z, const struct density*d, void* privdat), void* privdat) { 01271 for(int z=0; z<d->N[2]; ++z) { 01272 for(int y=0; y<d->N[1]; ++y) { 01273 for(int x=0; x<d->N[0]; ++x) { 01274 callback(x, y, z, d, privdat); 01275 } 01276 } 01277 } 01278 } 01279 01280 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) { 01281 for(int z=0; z<d1->N[2]; ++z) { 01282 for(int y=0; y<d1->N[1]; ++y) { 01283 for(int x=0; x<d1->N[0]; ++x) { 01284 callback(x, y, z, d1, d2, privdat); 01285 } 01286 } 01287 } 01288 } 01289 01290 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) { 01291 int x, y, z; 01292 #ifdef OPENMP 01293 #pragma omp parallel for private(x, y, z) 01294 #endif 01295 for(z=0; z<d->N[2]; ++z) { 01296 x_report[ 01297 #ifdef OPENMP 01298 omp_get_thread_num() 01299 #else 01300 0 01301 #endif 01302 ] = 1; 01303 for(y=0; y<d->N[1]; ++y) { 01304 for(x=0; x<d->N[0]; ++x) { 01305 callback(x, y, z, d, 01306 #ifdef OPENMP 01307 privdat[omp_get_thread_num()] 01308 #else 01309 privdat[0] 01310 #endif 01311 ); 01312 } 01313 } 01314 } 01315 } 01316 01317 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) { 01318 int x, y, z; 01319 #ifdef OPENMP 01320 #pragma omp parallel for private(x, y, z) 01321 #endif 01322 for(z=0; z<d1->N[2]; ++z) { 01323 x_report[ 01324 #ifdef OPENMP 01325 omp_get_thread_num() 01326 #else 01327 0 01328 #endif 01329 ] = 1; 01330 for(y=0; y<d1->N[1]; ++y) { 01331 for(x=0; x<d1->N[0]; ++x) { 01332 callback(x, y, z, d1, d2, 01333 #ifdef OPENMP 01334 privdat[omp_get_thread_num()] 01335 #else 01336 privdat[0] 01337 #endif 01338 ); 01339 } 01340 } 01341 } 01342 } 01343 01344 01345 struct diff_data { 01346 double* minmax; 01347 /*Value to scale by, ready to *multiply* (i.e. should be inverse of e.g. the global maximum*/ 01348 double scaling; 01349 }; 01350 static void get_max_diff_scaled(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat) { 01351 struct diff_data* dd = (struct diff_data*)privdat; 01352 double diff = fabs((d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])] - d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])])*dd->scaling); 01353 /**\note that this comparison will fail if diff is a NaN */ 01354 if(!(diff <= (*dd->minmax))) (*dd->minmax) = diff; 01355 } 01356 static void get_min_diff_scaled(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat) { 01357 struct diff_data* dd = (struct diff_data*)privdat; 01358 double diff = fabs((d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])] - d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])])*dd->scaling); 01359 if(!(diff >= (*dd->minmax))) (*dd->minmax) = diff; 01360 } 01361 01362 static void get_max_diff_d1(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat) { 01363 double diff = fabs((d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])] - d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])])/d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])]); 01364 //fprintf(stderr, "MAX: %d %d %d: %g - %g = %g\n", x, y, z, d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])], d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])], diff); 01365 /**\note that this comparison will fail if diff is a NaN */ 01366 if(!(diff <= *(double*)privdat)) *(double*)privdat = diff; 01367 } 01368 static void get_min_diff_d1(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat) { 01369 double diff = fabs((d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])] - d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])])/d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])]); 01370 //fprintf(stderr, "MIN: %d %d %d: %g - %g = %g\n", x, y, z, d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])], d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])], diff); 01371 if(!(diff >= *(double*)privdat)) *(double*)privdat = diff; 01372 } 01373 static void get_max_diff_d2(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat) { 01374 double diff = fabs((d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])] - d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])])/d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])]); 01375 //fprintf(stderr, "MAX: %d %d %d: %g - %g = %g\n", x, y, z, d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])], d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])], diff); 01376 /**\note that this comparison will fail if diff is a NaN */ 01377 if(!(diff <= *(double*)privdat)) *(double*)privdat = diff; 01378 } 01379 static void get_min_diff_d2(int x, int y, int z, const struct density* d1, const struct density* d2, void* privdat) { 01380 double diff = fabs((d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])] - d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])])/d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])]); 01381 //fprintf(stderr, "MIN: %d %d %d: %g - %g = %g\n", x, y, z, d1->storage[get_density_storage_index(x, y, z, d1->N[0], d1->N[1])], d2->storage[get_density_storage_index(x, y, z, d2->N[0], d2->N[1])], diff); 01382 if(!(diff >= *(double*)privdat)) *(double*)privdat = diff; 01383 } 01384 01385 double density_get_max_abs_delta_pct(const struct density* d1, const struct density* d2, int scaleby, double scaling) { 01386 double max = nan("NaN"); 01387 for(int i=0; i<3; i++) if(d1->N[i] != d2->N[i]) return max; 01388 #ifdef OPENMP 01389 int N_threads = omp_get_max_threads(); 01390 fprintf(stderr, "Got %d threads.\n", N_threads); 01391 struct diff_data dd_[N_threads]; 01392 double max_[N_threads]; 01393 void* maxset[N_threads]; 01394 void* ddset[N_threads]; 01395 int x_report[N_threads]; 01396 int i; 01397 for(i=0; i<N_threads; ++i) { 01398 max_[i] = max; 01399 maxset[i] = (void*)&(max_[i]); 01400 dd_[i].minmax = &(max_[i]); 01401 ddset[i] = (void*)&(dd_[i]); 01402 x_report[i] = 0; 01403 } 01404 switch(scaleby) { 01405 case -1: 01406 density_2_execute_callback_parallel(d1, d2, get_max_diff_d2, maxset, x_report); 01407 break; 01408 case 0: 01409 density_2_execute_callback_parallel(d1, d2, get_max_diff_d1, maxset, x_report); 01410 break; 01411 case 1: 01412 for(i=0; i<N_threads; ++i) { 01413 dd_[i].scaling = 1.0/density_get_max(d1, 1); 01414 } 01415 density_2_execute_callback_parallel(d1, d2, get_max_diff_scaled, ddset, x_report); 01416 break; 01417 case 2: 01418 for(i=0; i<N_threads; ++i) { 01419 dd_[i].scaling = 1.0/density_get_max(d2, 1); 01420 } 01421 density_2_execute_callback_parallel(d1, d2, get_max_diff_scaled, ddset, x_report); 01422 break; 01423 case 3: 01424 for(i=0; i<N_threads; ++i) { 01425 dd_[i].scaling = scaling; 01426 } 01427 density_2_execute_callback_parallel(d1, d2, get_max_diff_scaled, ddset, x_report); 01428 break; 01429 default: 01430 return max; 01431 } 01432 max = max_[0]; 01433 for(int i=1; i<N_threads; ++i) { 01434 /**\note that max[i] is already one or zero.*/ 01435 fprintf(stderr, "\tmax_[%d]=%g max=%g\n", i, max_[i], max); 01436 if(x_report[i] && (!(max_[i] <= max))) max = max_[i]; 01437 } 01438 #else 01439 struct diff_data dd; 01440 dd.minmax = &max; 01441 switch(scaleby) { 01442 case -1: 01443 density_2_execute_callback(d1, d2, get_max_diff_d2, &max); 01444 break; 01445 case 0: 01446 density_2_execute_callback(d1, d2, get_max_diff_d1, &max); 01447 break; 01448 case 1: 01449 dd.scaling = 1.0/density_get_max(d1, 1); 01450 density_2_execute_callback(d1, d2, get_max_diff_scaled, &dd); 01451 break; 01452 case 2: 01453 dd.scaling = 1.0/density_get_max(d2, 1); 01454 density_2_execute_callback(d1, d2, get_max_diff_scaled, &dd); 01455 break; 01456 case 3: 01457 dd.scaling = scaling; 01458 density_2_execute_callback(d1, d2, get_max_diff_scaled, &dd); 01459 break; 01460 default: 01461 return max; 01462 } 01463 #endif 01464 return max; 01465 } 01466 01467 double density_get_min_abs_delta_pct(const struct density* d1, const struct density* d2, int scaleby, double scaling) { 01468 double min = nan("NaN"); 01469 for(int i=0; i<3; i++) if(d1->N[i] != d2->N[i]) return min; 01470 #ifdef OPENMP 01471 int N_threads = omp_get_max_threads(); 01472 fprintf(stderr, "Got %d threads.\n", N_threads); 01473 struct diff_data dd_[N_threads]; 01474 double min_[N_threads]; 01475 void* minset[N_threads]; 01476 void* ddset[N_threads]; 01477 int x_report[N_threads]; 01478 int i; 01479 for(i=0; i<N_threads; ++i) { 01480 min_[i] = min; 01481 minset[i] = &(min_[i]); 01482 dd_[i].minmax = &(min_[i]); 01483 ddset[i] = &(dd_[i]); 01484 x_report[i] = 0; 01485 } 01486 switch(scaleby) { 01487 case -1: 01488 density_2_execute_callback_parallel(d1, d2, get_min_diff_d2, minset, x_report); 01489 break; 01490 case 0: 01491 density_2_execute_callback_parallel(d1, d2, get_min_diff_d1, minset, x_report); 01492 break; 01493 case 1: 01494 for(i=0; i<N_threads; ++i) { 01495 dd_[i].scaling = 1.0/density_get_min(d1, 1); 01496 } 01497 density_2_execute_callback_parallel(d1, d2, get_min_diff_scaled, ddset, x_report); 01498 break; 01499 case 2: 01500 for(i=0; i<N_threads; ++i) { 01501 dd_[i].scaling = 1.0/density_get_min(d2, 1); 01502 } 01503 density_2_execute_callback_parallel(d1, d2, get_min_diff_scaled, ddset, x_report); 01504 break; 01505 case 3: 01506 for(i=0; i<N_threads; ++i) { 01507 dd_[i].scaling = scaling; 01508 } 01509 density_2_execute_callback_parallel(d1, d2, get_min_diff_scaled, ddset, x_report); 01510 break; 01511 default: 01512 return min; 01513 } 01514 min = min_[0]; 01515 for(int i=1; i<N_threads; ++i) { 01516 /**\note that min[i] is already one or zero.*/ 01517 fprintf(stderr, "\tmin_[%d]=%g min=%g\n", i, min_[i], min); 01518 if((x_report[i]) && (!(min_[i] >= min))) min = min_[i]; 01519 } 01520 #else 01521 struct diff_data dd; 01522 dd.minmax = &min; 01523 switch(scaleby) { 01524 case -1: 01525 density_2_execute_callback(d1, d2, get_min_diff_d2, &min); 01526 break; 01527 case 0: 01528 density_2_execute_callback(d1, d2, get_min_diff_d1, &min); 01529 break; 01530 case 1: 01531 dd.scaling = 1.0/density_get_min(d1, 1); 01532 density_2_execute_callback(d1, d2, get_min_diff_scaled, &dd); 01533 break; 01534 case 2: 01535 dd.scaling = 1.0/density_get_min(d2, 1); 01536 density_2_execute_callback(d1, d2, get_min_diff_scaled, &dd); 01537 break; 01538 case 3: 01539 dd.scaling = scaling; 01540 density_2_execute_callback(d1, d2, get_min_diff_scaled, &dd); 01541 break; 01542 default: 01543 return min; 01544 } 01545 #endif 01546 return min; 01547 } 01548 01549 struct minmax_dat { 01550 double minmax; 01551 int location[3]; 01552 }; 01553 01554 static void get_max(int x, int y, int z, const struct density* d, void* privdat) { 01555 struct minmax_dat* mmd = (struct minmax_dat*)privdat; 01556 if(!(mmd->minmax >= *get_density_storage_at_c(x, y, z, d))) { 01557 mmd->minmax = *get_density_storage_at_c(x, y, z, d); 01558 mmd->location[0]=x; 01559 mmd->location[1]=y; 01560 mmd->location[2]=z; 01561 } 01562 } 01563 static void get_min(int x, int y, int z, const struct density* d, void* privdat) { 01564 struct minmax_dat* mmd = (struct minmax_dat*)privdat; 01565 if(!(mmd->minmax <= *get_density_storage_at_c(x, y, z, d))) { 01566 mmd->minmax = *get_density_storage_at_c(x, y, z, d); 01567 mmd->location[0]=x; 01568 mmd->location[1]=y; 01569 mmd->location[2]=z; 01570 } 01571 } 01572 01573 static void get_max_abs(int x, int y, int z, const struct density* d, void* privdat) { 01574 struct minmax_dat* mmd = (struct minmax_dat*)privdat; 01575 if(!(fabs(mmd->minmax) >= fabs(*get_density_storage_at_c(x, y, z, d)))) { 01576 mmd->minmax = fabs(*get_density_storage_at_c(x, y, z, d)); 01577 mmd->location[0]=x; 01578 mmd->location[1]=y; 01579 mmd->location[2]=z; 01580 } 01581 } 01582 static void get_min_abs(int x, int y, int z, const struct density* d, void* privdat) { 01583 struct minmax_dat* mmd = (struct minmax_dat*)privdat; 01584 if(!(fabs(mmd->minmax) <= fabs(*get_density_storage_at_c(x, y, z, d)))) { 01585 mmd->minmax = fabs(*get_density_storage_at_c(x, y, z, d)); 01586 mmd->location[0]=x; 01587 mmd->location[1]=y; 01588 mmd->location[2]=z; 01589 } 01590 } 01591 01592 double density_get_max(const struct density* d, int abs) { 01593 int location[3]; 01594 return density_get_max_and_loc(d, abs, location); 01595 } 01596 double density_get_max_and_loc(const struct density* d, int abs, int* location) { 01597 double max = nan("NaN"); 01598 int N_threads = 0; 01599 #ifdef OPENMP 01600 N_threads = omp_get_max_threads(); 01601 #endif 01602 struct minmax_dat max_[N_threads]; 01603 /*maxset is the array of private data pointers*/ 01604 void* maxset[N_threads]; 01605 int x_report[N_threads]; 01606 for(int i=0; i<N_threads; ++i) { 01607 max_[i].minmax = nan("NaN"); 01608 maxset[i] = &max_[i]; 01609 x_report[i] = 0; 01610 } 01611 if(abs) { 01612 density_execute_callback_parallel(d, get_max_abs, maxset, x_report); 01613 }else{ 01614 density_execute_callback_parallel(d, get_max, maxset, x_report); 01615 } 01616 max = max_[0].minmax; 01617 for(int j=0; j<3; ++j) location[j] = max_[0].location[j]; 01618 for(int i=1; i<N_threads; ++i) { 01619 /**\note that max[i] is already one or zero.*/ 01620 if(x_report[i] && (!(max_[i].minmax <= max))) { 01621 max = max_[i].minmax; 01622 for(int j=0; j<3; ++j) location[j] = max_[0].location[j]; 01623 } 01624 } 01625 return max; 01626 } 01627 double density_get_min(const struct density* d, int abs) { 01628 int location[3]; 01629 return density_get_min_and_loc(d, abs, location); 01630 } 01631 double density_get_min_and_loc(const struct density* d, int abs, int* location) { 01632 double min = nan("NaN"); 01633 int N_threads = 0; 01634 #ifdef OPENMP 01635 N_threads = omp_get_max_threads(); 01636 #endif 01637 struct minmax_dat min_[N_threads]; 01638 /*minset is the array of private data pointers*/ 01639 void* minset[N_threads]; 01640 int x_report[N_threads]; 01641 for(int i=0; i<N_threads; ++i) { 01642 min_[i].minmax = nan("NaN"); 01643 minset[i] = &min_[i]; 01644 x_report[i] = 0; 01645 } 01646 if(abs) { 01647 density_execute_callback_parallel(d, get_min_abs, minset, x_report); 01648 }else{ 01649 density_execute_callback_parallel(d, get_min, minset, x_report); 01650 } 01651 min = min_[0].minmax; 01652 for(int j=0; j<3; ++j) location[j] = min_[0].location[j]; 01653 for(int i=1; i<N_threads; ++i) { 01654 /**\note that min[i] is already one or zero.*/ 01655 if(x_report[i] && (!(min_[i].minmax <= min))) { 01656 min = min_[i].minmax; 01657 for(int j=0; j<3; ++j) location[j] = min_[0].location[j]; 01658 } 01659 } 01660 return min; 01661 } 01662 01663 01664 struct gsl_integrand_x { 01665 gsl_interp_accel* accel; 01666 gsl_spline* spline; 01667 double(*f)(double x, double y, double z, void* privdat); 01668 void* privdat; 01669 double y; 01670 double z; 01671 FILE* outfile; 01672 int iter; 01673 }; 01674 01675 hotfunc double gsl_integrand_x_func(double x, void* privdat) { 01676 struct gsl_integrand_x* gix = (struct gsl_integrand_x*)privdat; 01677 double val = gix->f(x, gix->y, gix->z, gix->privdat); 01678 double splineval = gsl_spline_eval(gix->spline, x, gix->accel); 01679 fprintf(gix->outfile, "%d\t%g\t%g\t%g\t%g\t%g\t%g\n", ++gix->iter, x, gix->y, gix->z, val, splineval, val*splineval); 01680 return val*splineval; 01681 } 01682 01683 hotfunc double gsl_integrand_x_nofunc(double x, void* privdat) { 01684 struct gsl_integrand_x* gix = (struct gsl_integrand_x*)privdat; 01685 double splineval = gsl_spline_eval(gix->spline, x, gix->accel); 01686 fprintf(gix->outfile, "%d\t%g\t%g\t%g\t%g\n", ++gix->iter, x, gix->y, gix->z, splineval); 01687 return splineval; 01688 } 01689 01690 hotfunc double gsl_integrand_yz(double coord, void* privdat) { 01691 struct gsl_integrand_x* gix = (struct gsl_integrand_x*)privdat; 01692 double splineval = gsl_spline_eval(gix->spline, coord, gix->accel); 01693 fprintf(gix->outfile, "%d\t%g\t%g\n", ++gix->iter, coord, splineval); 01694 return splineval; 01695 } 01696 01697 /**Note to self: this will be much cleaner for a templated version. What would happen is this: 01698 1) Allocate array of doubles 01699 2) Integrate each point in this dimension (e.g. if we're in 3D, do a 2D integral at each z point) 01700 3) Integrate the array of integrals 01701 4) We're done! 01702 01703 What's more, one could set an extra argument (of dimension D-1, if template is for dimension D) which specifies the index to integrate at each step, e.g. 01704 int integrate_first[] = {2, 1}; 01705 would specify that first the Z coordinate is to be integrated over (3D) then in the 2D integral, integrate over Y. When we're at 1D, we have no further coordinate to specify. 01706 01707 Of course, 0 has to be a specialized template. 01708 01709 if this isnt' a class member, remember that we must fully specialize the template to provide the termination condition. 01710 01711 Of course, this would obscure the fact that the strid is critically important to performance. 01712 And we'd have to fetch out full on classes of the D-1 dim. 01713 */ 01714 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) { 01715 /**Integrating x results in a yz plane of values 01716 *\note that the y coords are contiguous in memory 01717 */ 01718 double* yzvals = (double*)malloc(sizeof(double)*d->N[1]*d->N[2]); 01719 /*This array has the coordinate we're integrating over*/ 01720 double* coords = (double*)malloc(sizeof(double)*d->N[0]); 01721 if((yzvals == NULL) || (coords == NULL)) { 01722 if(yzvals != NULL) free(yzvals); 01723 if(coords != NULL) free(coords); 01724 return nan("NaN"); 01725 } 01726 for(int x=0; x<d->N[0]; ++x) coords[x] = (x - d->N[0]/2)*d->dx[0]; 01727 fprintf(stderr, "coords[0]=%g\tcoords[%d]=%g\n", coords[0], d->N[0]-1, coords[d->N[0]-1]); 01728 int index, z, y, status; 01729 gsl_interp_accel* accel = gsl_interp_accel_alloc(); 01730 gsl_spline* spline = gsl_spline_alloc(gsl_interp_cspline, d->N[0]); 01731 gsl_integration_workspace *w = gsl_integration_workspace_alloc(MAX_GSL_INTEGRATION_INTERVALS); 01732 struct gsl_integrand_x gix = {.accel=accel, .spline=spline, .f=f, .privdat=privdat, 0, 0}; 01733 gsl_function gsl_func = {.function = gsl_integrand_x_nofunc, .params=&gix}; 01734 if(f != NULL) gsl_func.function = gsl_integrand_x_func; 01735 double err_estimate; 01736 GString* filename = g_string_new(""); 01737 status = 0; 01738 for(z=0; z<d->N[0]; ++z) { 01739 gix.z = (z - d->N[2]/2)*d->dx[2]; 01740 for(y=0; y<d->N[1]; ++y) { 01741 gix.y = (y - d->N[1]/2)*d->dx[1]; 01742 index = z*d->N[1] + y; 01743 g_string_printf(filename, "x_integration_y_%d_z_%d.pdata", y, z); 01744 gix.outfile = fopen(filename->str, "w+"); 01745 gix.iter = -1; 01746 /*\note The x coordinates are contiguous; if we get the address for x=0, just move to the next double to get x=1 and so on. That's why this next line works*/ 01747 gsl_spline_init(spline, coords, get_density_storage_at_c(0, y, z, d), d->N[0]); 01748 status |= gsl_integration_qag(&gsl_func, coords[0], coords[d->N[0]-1], abserr, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w, &(yzvals[index]), (x_error_estimate==NULL)?(&err_estimate):(&x_error_estimate[index])); 01749 fclose(gix.outfile); 01750 } 01751 } 01752 free(coords); 01753 gsl_spline_free(spline); 01754 if(status != 0) { 01755 free(yzvals); 01756 gsl_interp_accel_free(accel); 01757 gsl_spline_free(spline); 01758 free(coords); 01759 return nan("NaN"); 01760 } 01761 01762 /*Now do the y integration; we end up with a z array of values.*/ 01763 coords = (double*)malloc(sizeof(double)*d->N[1]); 01764 double* zvals = (double*)malloc(sizeof(double)*d->N[1]); 01765 for(int y=0; y<d->N[1]; ++y) coords[y] = (y - d->N[1]/2)*d->dx[1]; 01766 fprintf(stderr, "coords[0]=%g\tcoords[%d]=%g\n", coords[0], d->N[1]-1, coords[d->N[1]-1]); 01767 if((zvals == NULL) || (coords == NULL)){ 01768 free(yzvals); 01769 gsl_interp_accel_free(accel); 01770 gsl_spline_free(spline); 01771 if(coords != NULL) free(coords); 01772 if(zvals != NULL) free(zvals); 01773 return nan("NaN"); 01774 } 01775 spline = gsl_spline_alloc(gsl_interp_cspline, d->N[1]); 01776 gsl_func.function = gsl_integrand_yz; 01777 for(int z=0; z<d->N[0]; ++z) { 01778 g_string_printf(filename, "y_integration_z_%d.pdata", z); 01779 gix.outfile = fopen(filename->str, "w+"); 01780 gix.iter = -1; 01781 gsl_spline_init(spline, coords, &yzvals[z*d->N[1]], d->N[1]); 01782 status |= gsl_integration_qag(&gsl_func, coords[0], coords[d->N[0]-1], abserr, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w, zvals, (y_error_estimate==NULL)?(&err_estimate):(&y_error_estimate[z])); 01783 fclose(gix.outfile); 01784 } 01785 free(coords); 01786 free(yzvals); 01787 gsl_spline_free(spline); 01788 if(status != 0) { 01789 gsl_interp_accel_free(accel); 01790 gsl_spline_free(spline); 01791 free(coords); 01792 free(zvals); 01793 return nan("NaN"); 01794 } 01795 01796 /*Finally, do the z integration.*/ 01797 coords = (double*)malloc(sizeof(double)*d->N[2]); 01798 for(int z=0; z<d->N[2]; ++z) coords[z] = (z - d->N[2]/2)*d->dx[2]; 01799 fprintf(stderr, "coords[0]=%g\tcoords[%d]=%g\n", coords[0], d->N[2]-1, coords[d->N[2]-1]); 01800 if(coords == NULL){ 01801 gsl_interp_accel_free(accel); 01802 gsl_spline_free(spline); 01803 free(zvals); 01804 if(coords != NULL) free(coords); 01805 return nan("NaN"); 01806 } 01807 spline = gsl_spline_alloc(gsl_interp_cspline, d->N[2]); 01808 gsl_spline_init(spline, coords, zvals, d->N[2]); 01809 double final_value = nan("NaN"); 01810 g_string_printf(filename, "y_integration_z_%d.pdata", z); 01811 gix.outfile = fopen(filename->str, "w+"); 01812 gix.iter = -1; 01813 status = gsl_integration_qag(&gsl_func, coords[0], coords[d->N[0]-1], abserr, relerr, MAX_GSL_INTEGRATION_INTERVALS, GSL_INTEG_GAUSS61, w, &final_value, (z_error_estimate==NULL)?(&err_estimate):(z_error_estimate)); 01814 fclose(gix.outfile); 01815 01816 gsl_interp_accel_free(accel); 01817 gsl_spline_free(spline); 01818 free(coords); 01819 free(zvals); 01820 01821 if(status != 0) return nan("NaN"); 01822 return final_value; 01823 } 01824 01825 double density_integrate_sum(const struct density* d, double (*f)(double x, double y, double z, void* privdat), void* privdat) { 01826 double val; 01827 int x, y, z; 01828 double sum = 0; 01829 for(z=0; z<d->N[2]; ++z) { 01830 for(y=0; y<d->N[1]; ++y) { 01831 for(x=0; x<d->N[0]; ++x) { 01832 val = *get_density_storage_at_c_(x, y, z, d); 01833 if(f != NULL) { 01834 val *= f((x-d->N[0])*d->dx[0], (y-d->N[1])*d->dx[0], (z-d->N[2])*d->dx[0], privdat); 01835 } 01836 sum += val; 01837 } 01838 } 01839 } 01840 return sum; 01841 } 01842 01843 double density_integrate_sum_parallel(const struct density* d, double (*f)(double x, double y, double z, void* privdat), void** privdat) { 01844 double val; 01845 int x, y, z; 01846 double sum = 0; 01847 #ifdef OPENMP 01848 #pragma omp parallel for private(x, y, z, val) reduction(+:sum) 01849 #endif 01850 for(z=0; z<d->N[2]; ++z) { 01851 for(y=0; y<d->N[1]; ++y) { 01852 for(x=0; x<d->N[0]; ++x) { 01853 val = *get_density_storage_at_c_(x, y, z, d); 01854 if(f != NULL) { 01855 if(privdat != NULL) { 01856 val *= f((x-d->N[0])*d->dx[0], (y-d->N[1])*d->dx[0], (z-d->N[2])*d->dx[0], privdat[ 01857 #ifdef OPENMP 01858 omp_get_thread_num() 01859 #else 01860 0 01861 #endif 01862 ]); 01863 01864 }else{ 01865 val *= f((x-d->N[0])*d->dx[0], (y-d->N[1])*d->dx[0], (z-d->N[2])*d->dx[0], NULL); 01866 } 01867 } 01868 sum += val; 01869 } 01870 } 01871 } 01872 return sum; 01873 } 01874 01875 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) { 01876 /*If we're iterating on an index, go to the next loop unless the index is right*/ 01877 GError *e = NULL; 01878 GFile* f; 01879 GString *s = g_string_new("line_"); 01880 switch(axis) { 01881 case X: 01882 g_string_append_printf(s, "Y=%d_Z=%d.pdata", gridsite[1], gridsite[2]); 01883 break; 01884 case Y: 01885 g_string_append_printf(s, "X=%d_Z=%d.pdata", gridsite[0], gridsite[2]); 01886 break; 01887 case Z: 01888 g_string_append_printf(s, "X=%d_Y=%d.pdata", gridsite[0], gridsite[1]); 01889 break; 01890 } 01891 if(location == NULL) { 01892 f = g_file_new_for_path(s->str); 01893 }else{ 01894 f = g_file_resolve_relative_path(location, s->str); 01895 } 01896 *filename = g_file_get_uri(f); 01897 //GFileIOStream *gfos = g_file_create_readwrite(f, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &e); 01898 GFileOutputStream *fos = g_file_replace(f, NULL, FALSE, 0, NULL, &e); 01899 if(e != NULL) { 01900 *err = e; 01901 return; 01902 } 01903 //GOutputStream *os = 01904 //g_io_stream_get_output_stream((GIOStream*)gfos); 01905 GDataOutputStream *dos = g_data_output_stream_new((GOutputStream*)fos); 01906 switch(axis) { 01907 case X: 01908 g_string_printf(s, "#X(%s)%c(%s)\n", coord_units, sepchar, density_units); 01909 break; 01910 case Y: 01911 g_string_printf(s, "#Y(%s)%c(%s)\n", coord_units, sepchar, density_units); 01912 break; 01913 case Z: 01914 g_string_printf(s, "#Z(%s)%c(%s)\n", coord_units, sepchar, density_units); 01915 break; 01916 } 01917 e=NULL; 01918 char *str; 01919 g_data_output_stream_put_string(dos, s->str, NULL, &e); 01920 if(e != NULL) { 01921 *err = e; 01922 g_string_free(s, TRUE); 01923 e=NULL; 01924 //g_io_stream_close((GIOStream*)gfos, NULL, &e); 01925 g_output_stream_close((GOutputStream*)fos, NULL, &e); 01926 if(e != NULL) { 01927 fprintf(stderr, "wavefunction::write_density_line: had an error (%s) while writing string (%s), but had another error (%s) while closing the file (%s)!\n", (*err)->message, s->str, e->message, str=g_file_get_uri(f)); 01928 g_free(str); 01929 } 01930 return; 01931 } 01932 for(int k=0; k<d->N[2]; k++) { 01933 if(((axis == X) || (axis == Y)) && (k != gridsite[2])) continue; 01934 for(int j=0; j<d->N[1]; j++) { 01935 if(((axis == X) || (axis == Z)) && (j != gridsite[1])) continue; 01936 for(int i=0; i<d->N[0]; i++) { 01937 if(((axis == Z) || (axis == Y)) && (i != gridsite[0])) continue; 01938 e=NULL; 01939 switch(axis) { 01940 case X: 01941 g_string_printf(s, "%g%c%g\n", i*(d->dx[0]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 01942 break; 01943 case Y: 01944 g_string_printf(s, "%g%c%g\n", j*(d->dx[1]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 01945 break; 01946 case Z: 01947 g_string_printf(s, "%g%c%g\n", k*(d->dx[2]), sepchar, d->storage[get_density_storage_index(i, j, k, d->N[0], d->N[1])]); 01948 break; 01949 } 01950 g_data_output_stream_put_string(dos, s->str, NULL, &e); 01951 if(e != NULL) { 01952 *err = e; 01953 g_string_free(s, TRUE); 01954 e=NULL; 01955 //g_io_stream_close(os, NULL, &e); 01956 g_output_stream_close((GOutputStream*)fos, NULL, &e); 01957 if(e != NULL) { 01958 fprintf(stderr, "wavefunction::write_density_line: had an error (%s) while writing string (%s), but had another error (%s) while closing the file (%s)!\n", (*err)->message, s->str, e->message, str=g_file_get_uri(f)); 01959 g_free(str); 01960 } 01961 return; 01962 } 01963 } 01964 } 01965 } 01966 //g_io_stream_close((GIOStream*)gfos, NULL, &e); 01967 g_output_stream_close((GOutputStream*)fos, NULL, &e); 01968 if(e != NULL) { 01969 *err = e; 01970 } 01971 g_string_free(s, TRUE); 01972 }