/****************************************************************************** Module Name : material.c Module Date : 02/26/2014 Module Auth : Yonggang Li, ygli@theory.issp.ac.cn Description : Contains the material-related functions, etc. Others : Error codes used in this modul: 2000 - 2999. Refers to iradina. Revision History: Date Rel Ver. Notes ******************************************************************************/ #include "material.h" /*============================================================================= Function Name : init_materials Description : Read materials from input file and do preparatory calculations, etc. It must be called before calling InitializeTarget. Returns 0 on success. Inputs : char* file_name Outputs : no. Notes : TODO: free arrays Function call: fileio - int read_init_file (int (*read_data_block) (char* block_name), int (*read_data) (char* par_name, char* par_value), char* file_name); fromcorteo - float d2f (double val); float sqrtdf (double val); utils - int prepare_stopping_tables (); int prepare_straggling_tables (int model); int count_existing_elements (int* elementarray); target - int prepare_scattering_matrix (struct scattering_matrix * ScatMatrix, float ProjM, int ProjZ, float TarM, int TarZ). =============================================================================*/ int init_materials (char *file_name) { int i, j = 0, k = 0; int result; #ifndef MPI_PRALLEL /* MPI=============================================== */ int number_exist_element; /* number of existing elements */ unsigned int lui_temp; /* long to int for 32-bit to 64-bit */ /* MPI=============================================== */ #endif float temp; struct scattering_matrix *psm; /* pointer to a scattering matrix */ /* init some material arrays etc. */ number_of_materials = 0; for (i=0; i0) printf ("No ion SBE for material %i defined. Trying mean value: %f eV\n", i, list_of_materials[i].ion_surf_energy); /* MPI=============================================== */ #else if (print_level > 0) printf ("No ion SBE for material %i defined. Trying mean value: %f eV\n", i, list_of_materials[i].ion_surf_energy); #endif } if (isnan (list_of_materials[i].ion_surf_energy)) { list_of_materials[i].ion_surf_energy = 3; #ifdef MPI_PRALLEL /* MPI=============================================== */ if (my_node == ROOT) printf ("No ion SBE for material %i defined. Using %f eV\n", i, list_of_materials[i].ion_surf_energy); /* MPI=============================================== */ #else printf ("No ion SBE for material %i defined. Using %f eV\n", i, list_of_materials[i].ion_surf_energy); #endif } list_of_materials[i].mean_Z = 0; list_of_materials[i].mean_M = 0; list_of_materials[i].mean_Ed = 0; /* Modified Kinchin-Pease Model, Aug. 05, 2014 */ /* go through elements, normalize concentration, check for hydrogen existence*/ for (j=0; j=0) { printf ("Prepare scattering matrices for ion on target collisions..."); fflush (stdout); } /* MPI=============================================== */ #else if (print_level >= 0) { printf ("Prepare scattering matrices for ion on target collisions..."); fflush (stdout); } #endif for (i=0; i=0) printf (" finished\n"); fflush (stdout); /* MPI=============================================== */ #else if (print_level >= 0) printf (" finished\n"); fflush (stdout); #endif /* Go through all possible other projectiles (which are the target elements) and create scattering matrices for scattering of the projectile with any other target element. */ /* Beware, this two dimensional matrix might get rather large... */ #ifdef MPI_PRALLEL /* MPI=============================================== */ if (my_node==ROOT && print_level>=0) { printf ("Prepare scattering matrices for recoil on target collisions..."); fflush (stdout); } /* MPI=============================================== */ #else if (print_level >= 0) { printf ("Prepare scattering matrices for recoil on target collisions..."); fflush (stdout); } #endif for (j=0; j=0) printf (" finished\n"); fflush(stdout); /* MPI=============================================== */ #else if (print_level >= 0) printf (" finished\n"); fflush(stdout); #endif } else { /* only estimate memory usage */ #ifndef MPI_PRALLEL /* MPI=============================================== */ if (store_exiting_recoils == 1) { lui_temp = 0; for (i=0; i= MAX_NO_MATERIALS) { /* material index is full */ printf ("Warning! Maximum number of materials (%i) exceeded!\n", MAX_NO_MATERIALS); return -2002; } /* make sure, that material-name is not to long, i.e. cut it if it is */ if (strlen (material_name) >= 25) material_name[24] = '\0'; strcpy (list_of_materials[number_of_materials].name, material_name); /* store Name */ list_of_materials[number_of_materials].element_count = 0; list_of_materials[number_of_materials].density = 0; list_of_materials[number_of_materials].ion_surf_energy = -0.001; #ifdef MPI_PRALLEL /* MPI=============================================== */ if (my_node==ROOT && print_level>=1) printf ("\nNew material declared:\t%s\n", material_name); /* MPI=============================================== */ #else if (print_level >= 1) printf ("\nNew material declared:\t%s\n", material_name); #endif number_of_materials++; /* increase index */ return 0; } /*============================================================================= Function Name : read_materials_data Description : Needs to be called from the init file reader while the materials input file is read. Inputs : char* par_name char* par_value Outputs : no. Notes : no. =============================================================================*/ int read_materials_data (char *par_name, char *par_value) { /* check some limits */ if (number_of_materials >= MAX_NO_MATERIALS) return -2003; /* too large */ /* Compare the parameter name to known parameters and then read in corresponding value */ if (strcmp (par_name, "element_count") == 0) { /* read number of element into the current material */ sscanf (par_value,"%i", &(list_of_materials[number_of_materials-1].element_count)); #ifdef MPI_PRALLEL /* MPI=============================================== */ if (my_node==ROOT && print_level>=1) printf ("Number of elements:\t%i\n", list_of_materials[number_of_materials-1].element_count); /* MPI=============================================== */ #else if (print_level >= 1) printf ("Number of elements:\t%i\n", list_of_materials[number_of_materials-1].element_count); #endif } if (strcmp (par_name, "density") == 0) { /* */ sscanf (par_value, "%f", &(list_of_materials[number_of_materials-1].density)); if (isnan (list_of_materials[number_of_materials-1].density)) list_of_materials[number_of_materials-1].density = 0.0; #ifdef MPI_PRALLEL /* MPI=============================================== */ if (my_node==ROOT && print_level>=1) printf ("Density:\t\t%g\n", list_of_materials[number_of_materials-1].density); /* MPI=============================================== */ #else if (print_level >= 1) printf ("Density:\t\t%g\n", list_of_materials[number_of_materials-1].density); #endif } if (strcmp (par_name,"elements_Z") == 0) /* read list of integer Z values*/ if (make_int_array (par_value, MAX_EL_PER_MAT, list_of_materials[number_of_materials-1].elements_Z) != 0) return -2004; if (strcmp (par_name, "elements_M") == 0) /* read list of mass values*/ if (make_float_array (par_value, MAX_EL_PER_MAT, list_of_materials[number_of_materials-1].elements_M) != 0) return -2005; if (strcmp (par_name, "elements_conc") == 0) /* read list of concentrations */ if (make_float_array(par_value,MAX_EL_PER_MAT, list_of_materials[number_of_materials-1].elements_conc) != 0) return -2006; if (strcmp (par_name, "elements_disp_energy") == 0) /* read list of displacement energies */ if (make_float_array (par_value, MAX_EL_PER_MAT, list_of_materials[number_of_materials-1].elements_disp_energy) != 0) return -2007; if (strcmp (par_name, "elements_latt_energy") == 0) /* read list of lattice energies */ if (make_float_array (par_value, MAX_EL_PER_MAT, list_of_materials[number_of_materials-1].elements_latt_energy) != 0) return -2008; if (strcmp (par_name, "elements_surf_energy") == 0) /* read list of surface binding energies */ if (make_float_array(par_value, MAX_EL_PER_MAT, list_of_materials[number_of_materials-1].elements_surf_energy) != 0) return -2009; if (strcmp (par_name, "ion_surf_energy") == 0) { /* read ion surface binding energy */ sscanf (par_value,"%f", &(list_of_materials[number_of_materials-1].ion_surf_energy)); #ifdef MPI_PRALLEL /* MPI=============================================== */ if (my_node==ROOT && print_level>=1) printf ("Ion SBE:\t\t%g\n", list_of_materials[number_of_materials-1].ion_surf_energy); /* MPI=============================================== */ #else if (print_level >= 1) printf ("Ion SBE:\t\t%g\n", list_of_materials[number_of_materials-1].ion_surf_energy); #endif } return 0; } /*============================================================================= Function Name : prepare_stopping_tables Description : Read stopping data from file and fill arrays etc. Material version. Inputs : no. Outputs : no. Notes : Function call: fileio - int read_float_block (char* file_name, int offset, int count, float* array); =============================================================================*/ int prepare_stopping_tables (void) { int i, j, k, l, result; char StoppingFileName[1000]; float flt_temp[DIMD+1]; /* go through materials and create stopping tables for all existing elements */ for (i=0; i1) printf ("Straggling model %i\n", model); /* MPI=============================================== */ #else if (print_level > 1) printf ("Straggling model %i\n", model); #endif /* go through materials and create straggling tables for all existing elements */ for (i=0; i= target_Ed && E_v < E_c) { list_of_materials[i].Nd[j] = 1.0; } else if (E_v >= E_c) { list_of_materials[i].Nd[j] = E_v / E_c; } //printf ("0000: %f\n", list_of_materials[i].Nd[j]); } } return 0; } /*============================================================================= Function Name : prepare_KP_tables Description : Modified Kinchin-Pease model, Material version. Inputs : no. Outputs : no. Notes : Wrong!!! Added on Aug. 05, 2014. =============================================================================*/ //int prepare_KP_tables2 (void) { // int i, j, k; // double target_Z, target_M, target_Ed, energy, k_d, g_ed, e_d, E_v, E_c; // for (i=0; i= target_Ed && E_v < E_c) { // list_of_materials[i].Nd[k] += list_of_materials[i].elements_conc[j]; // } // else if (E_v >= E_c) { // list_of_materials[i].Nd[k] += (E_v / E_c) * list_of_materials[i].elements_conc[j]; // } //printf ("0000: %f\n", list_of_materials[i].Nd[k]); // } // } // } // return 0; //} /*============================================================================= Function Name : prepare_KP_tables Description : Modified Kinchin-Pease model, Material version. Inputs : no. Outputs : no. Notes : Z_1 and Z_2, M_1 and M_2. Added on Aug. 13, 2014. =============================================================================*/ int prepare_KP_tables2 (void) { int i, j, k, l; double project_Z, project_M, target_Z, target_M, target_Ed, energy, k_d, g_ed, aa, e_d, E_v, E_c; for (i=0; i= target_Ed && E_v < E_c) { list_of_materials[i].Nd_Z[j][l] += list_of_materials[i].elements_conc[k]; } else if (E_v >= E_c) { list_of_materials[i].Nd_Z[j][l] += (E_v / E_c) * list_of_materials[i].elements_conc[k]; } //printf ("0000: %f\n", list_of_materials[i].Nd_Z[j][l]); } } } } return 0; } /*============================================================================= Function Name : count_existing_elements Description : Returns the number of ones in the provided array. Inputs : int* elementarray Outputs : no. Notes : no. =============================================================================*/ int count_existing_elements (int *element_array) { int result = 0; int i; for (i=0; i -2) printf ("Parsing elements (create separate elements for each material) ...\n"); fprintf (elem_fp, "ElementCount=%i\n\n", number_of_all_target_elements); for (i=0; i 0) printf ("Element %s found in material %s. Storing data.\n", atomic_names[list_of_materials[i].elements_Z[j]], list_of_materials[i].name); fprintf (elem_fp, "[%s_from_%s]\n", atomic_names[list_of_materials[i].elements_Z[j]], list_of_materials[i].name); fprintf (elem_fp, "Z=%i\n", list_of_materials[i].elements_Z[j]); fprintf (elem_fp, "M=%g\n", list_of_materials[i].elements_M[j]); fprintf (elem_fp, "DispEnergy=%g\n", list_of_materials[i].elements_disp_energy[j]); fprintf (elem_fp, "LattEnergy=%g\n", list_of_materials[i].elements_latt_energy[j]); fprintf (elem_fp, "SurfEnergy=%g\n\n", list_of_materials[i].elements_surf_energy[j]); mean_disp += list_of_materials[i].elements_disp_energy[j]; /* add stuff up to calc mean values */ mean_latt += list_of_materials[i].elements_latt_energy[j]; mean_surf += list_of_materials[i].elements_surf_energy[j]; mat_elem_vector_p[i*MAX_EL_PER_MAT+j] = elem_count+1; /* note, which element number this will get later */ if (print_level > 2) printf ("New element number %i assigned to mat. %i, elem. %i\n", elem_count + 1, i, j); elem_count ++; } } /* calculate mean values */ mean_disp /= (float) elem_count; mean_latt /= (float) elem_count; mean_surf /= (float) elem_count; if (print_level > -2) printf ("Finished parsing elements.\n"); } else { /* each element to appear only once */ if (print_level > -2) printf ("Parsing elements (list each elements not more than once) ...\n"); /* first: count element to put into file: */ for (i=1; i1) && (i != ion_Z)) || ((i==ion_Z) && (ionZ_in_target==1))) { /* OK, element really exists in target, not just additionally added ion or hydrogen */ elem_count ++; } } } fprintf (elem_fp, "ElementCount=%i\n\n", elem_count); elem_count = 0; /* restart counting !*/ /* then work on elements */ for (i=1; i1) && (i!=ion_Z)) || ((i==ion_Z) && (ionZ_in_target==1))) { /* OK, element really exists in target, not just additionally added ion or hydrogen */ if (print_level > 0) printf ("Element %s found. Storing data.\n", atomic_names[i]); /* Now search in which materials the element appears and obtain mean values for mass, energies... : */ mean_disp = 0; mean_latt = 0; mean_surf = 0; mean_mass = 0; elem_count2 = 0; for (k=0; k2) printf ("New element number %i assigned to mat. %i, elem. %i. Absolute element: %i\n", elem_count + 1, k, j, i); /* add stuff up to calc mean values */ mean_disp += list_of_materials[k].elements_disp_energy[j]; mean_latt += list_of_materials[k].elements_latt_energy[j]; mean_surf += list_of_materials[k].elements_surf_energy[j]; mean_mass += list_of_materials[k].elements_M[j]; elem_count2++; } } } mean_disp /= (float) elem_count2; mean_latt /= (float) elem_count2; mean_surf /= (float) elem_count2; mean_mass /= (float) elem_count2; /* Ok, write element info: */ fprintf (elem_fp, "[%s]\n", atomic_names[i]); fprintf (elem_fp, "Z=%i\n", i); fprintf (elem_fp, "M=%g\n", mean_mass); fprintf (elem_fp, "DispEnergy=%g\n", mean_disp); fprintf (elem_fp, "LattEnergy=%g\n", mean_latt); fprintf (elem_fp, "SurfEnergy=%g\n\n", mean_surf); elem_count ++; } else { /* element is in list, but does not really exist in target, ignore */ } } } if (print_level > -2) printf ("Finished parsing elements.\n"); /* For now, the ion's displacement, lattice and surface energy are simply determined by the last element that appeared. The values should anyway better be set by the user later! */ } fprintf (elem_fp, "[ion]\n"); fprintf (elem_fp, "DispEnergy=%g\n", mean_disp); fprintf (elem_fp, "LattEnergy=%g\n", mean_latt); fprintf (elem_fp, "SurfEnergy=%g\n", mean_surf); fclose (elem_fp); /* OK, element file has been written, new create composition file */ if (print_level > -2) printf ("New element file has been created.\n"); compVector = (float*) malloc ((elem_count + 1) * sizeof (float)); if (compVector == NULL) { printf ("Error: insufficient memory!\n"); return -2021; } comp_fp = fopen (TargetCompositionFileName, "w"); if(comp_fp==NULL) { printf ("Error. Cannot open file %s for writing.\n", TargetCompositionFileName); return -2022; } if (print_level > -2) printf ("Creating new composition file %s ...\n", TargetCompositionFileName); for (i=0; idensity); /* print density to file */ /* now construct composition vector for current cell: */ for (j=0; j<=elem_count; j++) compVector[j] = 0; /* init with zeros */ for (j=0; jelement_count; j++) /* cycle through elements of this material and get the concentration */ compVector[mat_elem_vector_p[target_composition[i]*MAX_EL_PER_MAT+j]] = cell_mat->elements_conc[j]; /* now, write the composition vector into the composition file */ for (j=0; j<=elem_count; j++) fprintf (comp_fp, "\t%g", compVector[j]); fprintf (comp_fp, "\n"); } fclose (comp_fp); if (print_level > -2) printf ("New composition file %s has been created.\n", TargetCompositionFileName); if (single_input_file == 1) { /* OK, create a single output file */ if (print_level > -2) printf ("Combining input files to create single project file %s... \n", ConversionFileName); sprintf (str_temp2, "ElementsFileName=%s\n\n#<< -2) printf ("Combined input files %s has been created.\n", ConversionFileName); } if (print_level > -2) printf("\nMaterial based input file successfully converted to element based input file. \n\n"); return 0; }