1/******************************************************************************* 2* 3* McStas, neutron ray-tracing package 4* Copyright(C) 2007 Risoe National Laboratory. 5* 6* %I 7* Written by: Mads Bertelsen 8* Date: 20.08.15 9* Origin: Svanevej 19 10* 11* A sample component to separate geometry and phsysics 12* 13* %D 14* Part of the Union components, a set of components that work together and thus 15* sperates geometry and physics within McStas. 16* The use of this component requires other components to be used. 17* 18* 1) One specifies a number of processes using process components 19* 2) These are gathered into material definitions using Union_make_material 20* 3) Geometries are placed using Union_box/cylinder/sphere, assigned a material 21* 4) A Union_master component placed after all of the above 22* 23* Only in step 4 will any simulation happen, and per default all geometries 24* defined before this master, but after the previous will be simulated here. 25* 26* There is a dedicated manual available for the Union_components 27* 28* This logger logs a 2D projection of the scattering vector, q in the lab frame. 29* 30* A logger will log something for scattering events happening to certain volumes, 31* which are specified in the target_geometry string. By leaving it blank, all 32* geometries are logged, even the ones not defined at this point in the 33* instrument file. If a list og target_geometries is selected, one can further 34* narrow the events logged by providing a list of process names in target_process 35* which need to correspond with names of defined Union_process components. 36* 37* To use the logger_conditional_extend function, set it to some integer value n 38* and make and extend section to the master component that runs the geometry. 39* In this extend function, logger_conditional_extend[n] is 1 if the conditional 40* stack evaluated to true, 0 if not. This way one can check what rays is logged 41* using regular McStas monitors. Only works if a conditional is applied to this 42* logger. 43* 44* %P 45* INPUT PARAMETERS: 46* Q_direction_1: [string] Q direction for first axis ("x", "y" or "z") 47* Q1_max: [1] histogram boundery, max q value for first axis 48* Q1_min: [1] histogram boundery, min q value for first axis 49* n1: [1] number of bins for first axis 50* Q_direction_2: [string] Q direction for second axis ("x", "y" or "z") 51* Q2_max: [1] histogram boundery, max q value for second axis 52* Q2_min: [1] histogram boundery, min q value for second axis 53* n2: [1] number of bins for second axis 54* target_geometry: [string] Comma seperated list of geometry names that will be logged, leave empty for all volumes (even not defined yet) 55* target_process: [string] Comma seperated names of physical processes, if volumes are selected, one can select Union_process names 56* order_total: [1] Only log rays that scatter for the n'th time, 0 for all orders 57* order_volume: [1] Only log rays that scatter for the n'th time in the same geometry 58* order_volume_process [1] Only log rays that scatter for the n'th time in the same geometry, uwsing the same process 59* logger_conditional_extend_index [1] If a conditional is used with this logger, the result of each conditional calculation can be made available in extend as a array called "logger_conditional_extend", and one would then acces logger_conditional_extend[n] if logger_conditional_extend_index is set to n 60* 61* OUTPUT PARAMETERS: 62* 63* GLOBAL PARAMETERS: 64* 65* %L 66* 67* %E 68******************************************************************************/ 69 70DEFINE COMPONENT Union_logger_2DQ 71DEFINITION PARAMETERS (n1=90, n2=90) 72SETTING PARAMETERS(string target_geometry="NULL",string target_process="NULL",Q1_min=-5,Q1_max=5,Q2_min=-5,Q2_max=5,string Q_direction_1="x", string Q_direction_2="z",string filename="NULL", order_total=0,order_volume=0,order_volume_process=0,logger_conditional_extend_index=-1) 73OUTPUT PARAMETERS (loop_index,accepted_processes,accepted_volumes,logger_list_element,this_logger,this_storage,loggers_on_target_volume,target_volume,logger_conditional_extend_index) 74 75/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */ 76 77SHARE 78%{ 79#ifndef Union 80#define Union $Revision: 0.8 $ 81 82#include "Union_functions.c" 83#include "Union_initialization.c" 84 85#endif 86 87struct temp_2DQ_data_element_struct { 88int index_1; 89int index_2; 90double weight; 91}; 92 93struct temp_2DQ_data_struct { 94int num_elements; 95int allocated_elements; 96struct temp_2DQ_data_element_struct *elements; 97}; 98 99struct a_2DQ_storage_struct { 100struct Detector_2D_struct Detector_2D; 101struct temp_2DQ_data_struct temp_2DQ_data; 102int dim_1_choice; 103int dim_2_choice; 104int order; 105int order_in_this_volume; 106int order_process_in_this_volume; 107}; 108 109// record_to_temp 110// Would be nice if x y z, k_new and k_old were all coords 111void record_to_temp_2DQ(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { 112 113 struct a_2DQ_storage_struct *storage; 114 storage = logger->data_union.p_2DQ_storage; 115 116 int add_point = 1; 117 118 if (storage->order != 0) { 119 if (storage->order - 1 == total_number_of_scattering_events) 120 add_point = 1; 121 else 122 add_point = 0; 123 } 124 125 if (storage->order_in_this_volume != 0) { 126 if (storage->order_in_this_volume - 1 == scattered_in_this_volume) 127 add_point = 1; 128 else 129 add_point = 0; 130 } 131 132 if (storage->order_process_in_this_volume != 0) { 133 if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) 134 add_point = 1; 135 else 136 add_point = 0; 137 } 138 139 if (add_point == 1) { 140 141 double q1,q2; 142 143 // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input. "x" "y" "z". 144 q1 = k_old[storage->dim_1_choice] - k_new[storage->dim_1_choice]; 145 q2 = k_old[storage->dim_2_choice] - k_new[storage->dim_2_choice]; 146 147 int i,j; 148 149 // Find bin in histogram 150 if (q1>storage->Detector_2D.D1min && q1<storage->Detector_2D.D1max && q2>storage->Detector_2D.D2min && q2<storage->Detector_2D.D2max) { 151 i = floor((q1 - storage->Detector_2D.D1min)*storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); 152 j = floor((q2 - storage->Detector_2D.D2min)*storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); 153 154 // Save bin in histogram to temp (may need to allocate more memory) 155 int index; 156 //printf("number of data points used: %d space allocated for %d data points. \n",storage->temp_2DQ_data.num_elements,storage->temp_2DQ_data.allocated_elements); 157 158 if (storage->temp_2DQ_data.num_elements < storage->temp_2DQ_data.allocated_elements) { 159 storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_1 = i; 160 storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_2 = j; 161 storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements++].weight = p; 162 } else { 163 // No more space, need to allocate a larger buffer for this logger. Wish I had generics. 164 165 // copy current data to temp 166 struct temp_2DQ_data_struct temporary_storage; 167 temporary_storage.num_elements = storage->temp_2DQ_data.num_elements; 168 temporary_storage.elements = malloc(temporary_storage.num_elements*sizeof(struct temp_2DQ_data_element_struct)); 169 170 for (index=0;index<storage->temp_2DQ_data.num_elements;index++) { 171 temporary_storage.elements[index].index_1 = storage->temp_2DQ_data.elements[index].index_1; 172 temporary_storage.elements[index].index_2 = storage->temp_2DQ_data.elements[index].index_2; 173 temporary_storage.elements[index].weight = storage->temp_2DQ_data.elements[index].weight; 174 } 175 176 // free current data 177 free(storage->temp_2DQ_data.elements); 178 179 // allocate larger array (10 larger) 180 storage->temp_2DQ_data.allocated_elements = 10 + storage->temp_2DQ_data.num_elements; 181 storage->temp_2DQ_data.elements = malloc(storage->temp_2DQ_data.allocated_elements*sizeof(struct temp_2DQ_data_element_struct)); 182 183 // copy back from temp 184 for (index=0;index<storage->temp_2DQ_data.num_elements;index++) { 185 storage->temp_2DQ_data.elements[index].index_1 = temporary_storage.elements[index].index_1; 186 storage->temp_2DQ_data.elements[index].index_2 = temporary_storage.elements[index].index_2; 187 storage->temp_2DQ_data.elements[index].weight = temporary_storage.elements[index].weight; 188 } 189 190 // free temporary data 191 free(temporary_storage.elements); 192 193 // add new data point 194 storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_1 = i; 195 storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements].index_2 = j; 196 storage->temp_2DQ_data.elements[storage->temp_2DQ_data.num_elements++].weight = p; 197 } 198 199 // If this is the first time this ray is being recorded in this logger, add it to the list of loggers that write to temp and may get it moved to perm 200 if (storage->temp_2DQ_data.num_elements == 1) 201 add_to_logger_with_data(logger_with_data_array,logger); 202 } 203 } 204 205} 206 207// clear_temp 208void clear_temp_2DQ(union logger_data_union *data_union) { 209 data_union->p_2DQ_storage->temp_2DQ_data.num_elements = 0; 210} 211 212// record_to_perm 213void record_to_perm_2DQ(Coords *position, double *k_new, double *k_old, double p, double p_old, double time, int scattered_in_this_volume, int scattered_in_this_volume_by_this_process, int total_number_of_scattering_events, struct logger_struct *logger, struct logger_with_data_struct *logger_with_data_array) { 214 215 //printf("In record to permanent \n"); 216 struct a_2DQ_storage_struct *storage; 217 storage = logger->data_union.p_2DQ_storage; 218 219 int add_point = 1; 220 221 if (storage->order != 0) { 222 if (storage->order - 1 == total_number_of_scattering_events) 223 add_point = 1; 224 else 225 add_point = 0; 226 } 227 228 if (storage->order_in_this_volume != 0) { 229 if (storage->order_in_this_volume - 1 == scattered_in_this_volume) 230 add_point = 1; 231 else 232 add_point = 0; 233 } 234 235 if (storage->order_process_in_this_volume != 0) { 236 if (storage->order_process_in_this_volume - 1 == scattered_in_this_volume_by_this_process) 237 add_point = 1; 238 else 239 add_point = 0; 240 } 241 242 if (add_point == 1) { 243 //printf("storage was set \n"); 244 double q1,q2; 245 246 // dim_1_choice = 0 for x, 1 for y, 2 for z. Done in initialize from input "x" "y" "z". 247 q1 = k_old[storage->dim_1_choice] - k_new[storage->dim_1_choice]; 248 q2 = k_old[storage->dim_2_choice] - k_new[storage->dim_2_choice]; 249 250 int i,j; 251 252 // Find bin in histogram 253 if (q1>storage->Detector_2D.D1min && q1<storage->Detector_2D.D1max && q2>storage->Detector_2D.D2min && q2<storage->Detector_2D.D2max) { 254 255 i = floor((q1 - storage->Detector_2D.D1min)*(double)storage->Detector_2D.bins_1/(storage->Detector_2D.D1max - storage->Detector_2D.D1min)); 256 j = floor((q2 - storage->Detector_2D.D2min)*(double)storage->Detector_2D.bins_2/(storage->Detector_2D.D2max - storage->Detector_2D.D2min)); 257 258 //printf("Added to statistics for monitor [%d] [%d] \n",i,j); 259 //printf("indicies found\n"); 260 261 storage->Detector_2D.Array_N[i][j]++; 262 storage->Detector_2D.Array_p[i][j] += p; 263 storage->Detector_2D.Array_p2[i][j] += p*p; 264 265 } 266 } 267 268} 269 270// write_temp_to_perm 271void write_temp_to_perm_2DQ(union logger_data_union *data_union) { 272 273 struct a_2DQ_storage_struct *storage; 274 storage = data_union->p_2DQ_storage; 275 276 int index; 277 // Add all data points to the historgram, they are saved as index / weight combinations 278 for (index=0;index<storage->temp_2DQ_data.num_elements;index++) { 279 storage->Detector_2D.Array_N[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2]++; 280 281 storage->Detector_2D.Array_p[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += storage->temp_2DQ_data.elements[index].weight; 282 283 storage->Detector_2D.Array_p2[storage->temp_2DQ_data.elements[index].index_1][storage->temp_2DQ_data.elements[index].index_2] += storage->temp_2DQ_data.elements[index].weight*storage->temp_2DQ_data.elements[index].weight; 284 } 285 clear_temp_2DQ(data_union); 286} 287 288// Only need to define linking function for loggers once. 289#ifndef UNION_LOGGER 290#define UNION_LOGGER Dummy 291// Linking function for loggers, finds the indicies of the specified geometries on the global_geometry_list 292void manual_linking_function_logger_volumes(char *input_string, struct pointer_to_global_geometry_list *global_geometry_list, struct pointer_to_1d_int_list *accepted_volumes, char *component_name) { 293 // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. 294 char *token; 295 int loop_index; 296 char local_string[512]; 297 298 strcpy(local_string,input_string); 299 // get the first token 300 token = strtok(local_string,","); 301 302 // walk through other tokens 303 while( token != NULL ) 304 { 305 //printf( " %s\n", token ); 306 for (loop_index=0;loop_index<global_geometry_list->num_elements;loop_index++) { 307 if (strcmp(token,global_geometry_list->elements[loop_index].name) == 0) { 308 add_element_to_int_list(accepted_volumes,loop_index); 309 break; 310 } 311 312 if (loop_index == global_geometry_list->num_elements - 1) { 313 // All possible geometry names have been looked through, and the break was not executed. 314 // Alert the user to this problem by showing the geometry name that was not found and the currently available geometires 315 printf("\n"); 316 printf("ERROR: The target_geometry string \"%s\" in Union logger component \"%s\" had an entry that did not match a specified geometry. \n",input_string,component_name); 317 printf(" The unrecoignized geometry name was: \"%s\" \n",token); 318 printf(" The geometries available at this point (need to be defined before the logger): \n"); 319 for (loop_index=0;loop_index<global_geometry_list->num_elements;loop_index++) 320 printf(" %s\n",global_geometry_list->elements[loop_index].name); 321 exit(1); 322 } 323 } 324 325 // Updates the token 326 token = strtok(NULL,","); 327 } 328} 329 330void manual_linking_function_logger_processes(char *input_string, struct physics_struct *p_physics, struct pointer_to_1d_int_list *accepted_processes, char *component_name, char *Volume_name) { 331 // Need to check a input_string of text for an occurance of name. If it is in the inputstring, yes return 1, otherwise 0. 332 char *token; 333 int loop_index; 334 char local_string[256]; 335 336 strcpy(local_string,input_string); 337 // get the first token 338 token = strtok(local_string,","); 339 340 // walk through other tokens 341 while( token != NULL ) 342 { 343 //printf( " %s\n", token ); 344 for (loop_index=0;loop_index<p_physics->number_of_processes;loop_index++) { 345 if (strcmp(token,p_physics->p_scattering_array[loop_index].name) == 0) { 346 add_element_to_int_list(accepted_processes,loop_index); 347 break; 348 } 349 350 if (loop_index == p_physics->number_of_processes - 1) { 351 // All possible process names have been looked through, and the break was not executed. 352 // Alert the user to this problem by showing the process name that was not found and the currently available processes 353 printf("\n"); 354 printf("ERROR: The target process string \"%s\" in Union logger \"%s\" had an entry that did not match a specified process in assosiated volume \"%s\". \n",input_string,component_name,Volume_name); 355 printf(" The unrecoignized process name was: \"%s\" \n",token); 356 printf(" The processes defined in material \"%s\" of which Volume \"%s\" is made: \n",p_physics->name,Volume_name); 357 for (loop_index=0;loop_index<p_physics->number_of_processes;loop_index++) 358 printf(" %s\n",p_physics->p_scattering_array[loop_index].name); 359 exit(1); 360 } 361 } 362 363 // Updates the token 364 token = strtok(NULL,","); 365 } 366} 367#endif 368 369double** allocate2Ddouble(int count_x, int count_y) { 370 // This function is needed to dynamically declare an array 371 // that has continous data as a static array would have, 372 // as that is the format expected by DETECTOR_OUT_2D. 373 int i; 374 375 // allocate space for actual data 376 double *data = malloc(sizeof(double) * count_x * count_y); 377 378 // create array or pointers to first elem in each 2D row 379 double **ptr_array = malloc(sizeof(double*) * count_x); 380 for (i = 0; i < count_x; i++) { 381 ptr_array[i] = data + (i*count_y); 382 } 383 return ptr_array; 384} 385 386void free2Ddouble(double** ptr_array) { 387 if (!ptr_array) return; 388 if (ptr_array[0]) free(ptr_array[0]); 389 free(ptr_array); 390} 391 392%} 393 394DECLARE 395%{ 396// From make material 397// Needed for transport to the main component 398//struct global_material_element_struct global_material_element; 399//struct physics_struct this_material; 400 401int loop_index,l1,l2; 402int process_index; 403int found_process; 404int specified_processes; 405char local_string[256]; 406 407// Reused for logger 408struct pointer_to_1d_int_list accepted_processes = {0,NULL}; 409 410struct global_logger_element_struct logger_list_element; 411 412struct pointer_to_1d_int_list accepted_volumes = {0,NULL}; 413 414struct logger_struct this_logger; 415struct a_2DQ_storage_struct this_storage; 416 417struct loggers_struct *loggers_on_target_volume; 418struct Volume_struct *target_volume; 419 420char temp_string[2]; 421 422%} 423 424INITIALIZE 425%{ 426 427 428 // Initialize storage from input 429 if (Q1_min >= Q1_max) { 430 printf("ERROR, Union logger \"%s\" had Q1_min >= Q1_max.\n",NAME_CURRENT_COMP); 431 exit(1); 432 } 433 this_storage.Detector_2D.D1min = Q1_min; 434 this_storage.Detector_2D.D1max = Q1_max; 435 436 if (Q2_min >= Q2_max) { 437 printf("ERROR, Union logger \"%s\" had Q2_min >= Q2_max.\n",NAME_CURRENT_COMP); 438 exit(1); 439 } 440 this_storage.Detector_2D.D2min = Q2_min; 441 this_storage.Detector_2D.D2max = Q2_max; 442 443 if (n1 <= 0) { 444 printf("ERROR, Union logger \"%s\" had n1 <= 0.\n",NAME_CURRENT_COMP); 445 exit(1); 446 } 447 this_storage.Detector_2D.bins_1 = n1; 448 449 if (n2 <= 0) { 450 printf("ERROR, Union logger \"%s\" had n2 <= 0.\n",NAME_CURRENT_COMP); 451 exit(1); 452 } 453 this_storage.Detector_2D.bins_2 = n2; 454 455 //printf("past input sanitation \n"); 456 457 // Remember to take special care when deallocating this array, use free2Ddouble 458 this_storage.Detector_2D.Array_N = allocate2Ddouble(n1,n2); // Here the n1 double is cast to an int 459 this_storage.Detector_2D.Array_p = allocate2Ddouble(n1,n2); 460 this_storage.Detector_2D.Array_p2 = allocate2Ddouble(n1,n2); 461 462 for (l1=0;l1<n1;l1++) { //n1 is technically a double, but this works fine 463 for (l2=0;l2<n2;l2++) { 464 this_storage.Detector_2D.Array_N[l1][l2] = 0; 465 this_storage.Detector_2D.Array_p[l1][l2] = 0; 466 this_storage.Detector_2D.Array_p2[l1][l2] = 0; 467 } 468 } 469 470 //printf("past 2D pointer assignment \n"); 471 472 // Input sanitation for filename apparently done in 2D_detector_out 473 474 if (strcmp(Q_direction_1,"x") == 0 || strcmp(Q_direction_1,"X") == 0) { 475 this_storage.dim_1_choice = 0; 476 sprintf(this_storage.Detector_2D.string_axis_1,"Q_x [A^-1]"); 477 sprintf(this_storage.Detector_2D.title_string,"2D Q Union logger in plane x"); 478 } else if (strcmp(Q_direction_1,"y") == 0 || strcmp(Q_direction_1,"Y") == 0) { 479 this_storage.dim_1_choice = 1; 480 sprintf(this_storage.Detector_2D.string_axis_1,"Q_y [A^-1]"); 481 sprintf(this_storage.Detector_2D.title_string,"2D Q Union logger in plane y"); 482 } else if (strcmp(Q_direction_1,"z") == 0 || strcmp(Q_direction_1,"Z") == 0) { 483 this_storage.dim_1_choice = 2; 484 sprintf(this_storage.Detector_2D.string_axis_1,"Q_z [A^-1]"); 485 sprintf(this_storage.Detector_2D.title_string,"2D Q Union logger in plane z"); 486 } else { 487 printf("ERROR, Union logger 2DQ named \"%s\" has an invalid Q_direction_1 string, it should be \"x\",\"y\" or \"z\".\n",NAME_CURRENT_COMP); 488 exit(1); 489 } 490 491 if (strcmp(Q_direction_2,"x") == 0 || strcmp(Q_direction_2,"X") == 0) { 492 this_storage.dim_2_choice = 0; 493 sprintf(this_storage.Detector_2D.string_axis_2,"Q_x [A^-1]"); 494 sprintf(temp_string,"x"); 495 } else if (strcmp(Q_direction_2,"y") == 0 || strcmp(Q_direction_2,"Y") == 0) { 496 this_storage.dim_2_choice = 1; 497 sprintf(this_storage.Detector_2D.string_axis_2,"Q_y [A^-1]"); 498 sprintf(temp_string,"y"); 499 } else if (strcmp(Q_direction_2,"z") == 0 || strcmp(Q_direction_2,"Z") == 0) { 500 this_storage.dim_2_choice = 2; 501 sprintf(this_storage.Detector_2D.string_axis_2,"Q_z [A^-1]"); 502 sprintf(temp_string,"z"); 503 } else { 504 printf("ERROR, Union logger 2DQ named \"%s\" has an invalid Q_direction_2 string, it should be \"x\",\"y\" or \"z\".\n",NAME_CURRENT_COMP); 505 exit(1); 506 } 507 508 strcat(this_storage.Detector_2D.title_string,temp_string); // Connects the title string started in Q_direction_1 part with the ending in Q_direction_2 part 509 510 sprintf(this_storage.Detector_2D.Filename,filename); 511 512 513 this_storage.order = order_total; 514 this_storage.order_in_this_volume = order_volume; 515 this_storage.order_process_in_this_volume = order_volume_process; 516 this_storage.temp_2DQ_data.num_elements=0; 517 this_storage.temp_2DQ_data.allocated_elements = 10; 518 this_storage.temp_2DQ_data.elements = malloc(this_storage.temp_2DQ_data.allocated_elements*sizeof(struct temp_2DQ_data_element_struct)); 519 520 //printf("past direction choices sanitation \n"); 521 522 // Book keeping 523 this_logger.logger_extend_index = logger_conditional_extend_index; 524 this_logger.function_pointers.active_record_function = &record_to_perm_2DQ; // Assume no conditional 525 this_logger.function_pointers.inactive_record_function = &record_to_temp_2DQ; // If an assume is present, these two pointers are switched 526 this_logger.function_pointers.temp_to_perm = &write_temp_to_perm_2DQ; 527 this_logger.function_pointers.clear_temp = &clear_temp_2DQ; 528 // Initializing for conditional 529 this_logger.conditional_list.num_elements = 0; 530 531 //this_logger.function_pointers.perm_to_disk = &write_perm_to_disk_2DQ; //Obsolete 532 533 //printf("past this_logger function assignment \n"); 534 535 this_logger.data_union.p_2DQ_storage = &this_storage; 536 537 sprintf(this_logger.name,NAME_CURRENT_COMP); 538 539 //printf("past this_logger assignment \n"); 540 541 sprintf(logger_list_element.name,NAME_CURRENT_COMP); 542 logger_list_element.component_index = INDEX_CURRENT_COMP; 543 logger_list_element.logger = &this_logger; 544 545 //printf("past logger_list_element assignment \n"); 546 547 // In order to run the logger at the right times, pointers to this logger is stored in each volume it logs, 548 // and additionally for each avaiable process. If a process is not logged, the pointer is simply not stored. 549 550 // Need to find the volumes for which the processes should have a reference to this logger 551 if (target_geometry && strlen(target_geometry) && strcmp(target_geometry,"NULL") && strcmp(target_geometry, "0")) { 552 // Certain volumes were selected, find the indicies in the global_geometry_list 553 manual_linking_function_logger_volumes(target_geometry, &global_geometry_list, &accepted_volumes, NAME_CURRENT_COMP); 554 // Add this logger to the global_specific_volumes_logger_list (so that conditionals can affect it) 555 add_element_to_logger_list(&global_specific_volumes_logger_list,logger_list_element); 556 557 for (loop_index=0;loop_index<accepted_volumes.num_elements;loop_index++) { 558 target_volume = global_geometry_list.elements[accepted_volumes.elements[loop_index]].Volume; 559 // Add an element to its logger list 560 add_initialized_logger_in_volume(&target_volume->loggers,target_volume->p_physics->number_of_processes); 561 562 if (target_process && strlen(target_process) && strcmp(target_process,"NULL") && strcmp(target_process, "0")) { 563 // Unused process pointers should point to NULL 564 for (process_index=0;process_index<target_volume->p_physics->number_of_processes;process_index++) { 565 target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=NULL; 566 } 567 // A target_process was set, find it within the volume structure (can be many processes) 568 manual_linking_function_logger_processes(target_process, target_volume->p_physics, &accepted_processes, NAME_CURRENT_COMP,target_volume->name); 569 for (process_index=0;process_index<accepted_processes.num_elements;process_index++) { 570 // Add pointer to this logger for all the accepted processes in this newly added loggers element 571 target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[accepted_processes.elements[process_index]]=&this_logger; 572 } 573 } else { 574 // No target_process was set, attatch the logger to all processes 575 for (process_index=0;process_index<target_volume->p_physics->number_of_processes;process_index++) { 576 target_volume->loggers.p_logger_volume[target_volume->loggers.num_elements-1].p_logger_process[process_index]=&this_logger; 577 } 578 } 579 } 580 } else { 581 // Send to global_all_volumes_logger_list 582 // Here there is no system for selecting processes as well 583 add_element_to_logger_list(&global_all_volume_logger_list,logger_list_element); 584 } 585 586 587 %} 588 589TRACE 590%{ 591%} 592 593SAVE 594%{ 595// Write to disk 596DETECTOR_OUT_2D( 597 this_storage.Detector_2D.title_string, 598 this_storage.Detector_2D.string_axis_1, 599 this_storage.Detector_2D.string_axis_2, 600 this_storage.Detector_2D.D1min, this_storage.Detector_2D.D1max, 601 this_storage.Detector_2D.D2min, this_storage.Detector_2D.D2max, 602 this_storage.Detector_2D.bins_1, this_storage.Detector_2D.bins_2, 603 *this_storage.Detector_2D.Array_N, *this_storage.Detector_2D.Array_p, *this_storage.Detector_2D.Array_p2, 604 this_storage.Detector_2D.Filename); 605 606%} 607 608FINALLY 609%{ 610// Remember to clean up allocated lists 611if (this_storage.temp_2DQ_data.allocated_elements>0) free(this_storage.temp_2DQ_data.elements); 612 613free2Ddouble(this_storage.Detector_2D.Array_N); 614free2Ddouble(this_storage.Detector_2D.Array_p); 615free2Ddouble(this_storage.Detector_2D.Array_p2); 616 617if (accepted_processes.num_elements > 0) free(accepted_processes.elements); 618if (accepted_volumes.num_elements > 0) free(accepted_volumes.elements); 619 620%} 621 622END 623 624