コード例 #1
0
long  AT_n_bins_for_single_impact_local_dose_distrib(
		const long    n,
		const double  E_MeV_u[],
		const long    particle_no[],
		const long    material_no,
		const long    rdd_model,
		const double  rdd_parameter[],
		const long    er_model,
		const long    N2,
		const long    stopping_power_source_no)
{
	/* get lowest and highest dose */
	double d_max_Gy    =  0.0;
	double d_min_Gy    =  0.0;

	// TODO think if d_min calculations can be done in smarter way. LET is only needed for Geiss RDD

	long  i;
	for (i = 0; i < n; i++){

		double max_electron_range_m = AT_max_electron_range_m( E_MeV_u[i], (int)material_no, (int)er_model);
		double LET_MeV_cm2_g        = AT_Stopping_Power_MeV_cm2_g_single( stopping_power_source_no, E_MeV_u[i], particle_no[i], material_no);
		double norm_constant_Gy     = AT_RDD_precalculated_constant_Gy(max_electron_range_m, LET_MeV_cm2_g, E_MeV_u[i], particle_no[i], material_no, rdd_model, rdd_parameter, er_model);
		double current_d_min_Gy     = AT_RDD_d_min_Gy( E_MeV_u[i], particle_no[i], material_no, rdd_model, rdd_parameter, er_model, norm_constant_Gy);
		double current_d_max_Gy     = AT_RDD_d_max_Gy( E_MeV_u[i], particle_no[i], material_no, rdd_model, rdd_parameter, er_model, stopping_power_source_no);

		if(i == 0){
			d_min_Gy      =  current_d_min_Gy;
			d_max_Gy      =  current_d_max_Gy;
		}
		else{
			d_min_Gy      =  GSL_MIN(d_min_Gy, current_d_min_Gy);
			d_max_Gy      =  GSL_MAX(d_max_Gy, current_d_max_Gy);
		}
	}

	long n_bins_for_singe_impact_local_dose_ditrib = 0;
	// get number of bins needed to span that dose range
	if( (d_min_Gy > 0) && (d_max_Gy >0) ){
		// OLD:
		//		double tmp        =  log10(d_max_Gy/d_min_Gy) / log10(2.0) * ((double)N2);
		//		n_bins_for_singe_impact_local_dose_ditrib        =  (long)(floor(tmp) + 1.0);
		AT_histo_n_bins(     d_min_Gy,
				d_max_Gy,
				AT_N2_to_step(N2),
				AT_histo_log,
				&n_bins_for_singe_impact_local_dose_ditrib);
	} else {
#ifndef NDEBUG
		printf("AT_n_bins_for_singe_impact_local_dose_ditrib: problem in evaluating n_bins_for_singe_impact_local_dose_ditrib: d_min = %g [Gy], d_max = %g [Gy] \n", d_min_Gy, d_max_Gy);
		exit(EXIT_FAILURE);
#endif
	}
	return n_bins_for_singe_impact_local_dose_ditrib + 1;
}
コード例 #2
0
void  AT_single_impact_local_dose_distrib(
		const long    n,
		const double  E_MeV_u[],
		const long    particle_no[],
		const double  fluence_cm2_or_dose_Gy[],
		const long    material_no,
		const long    rdd_model,
		const double  rdd_parameter[],
		const long    er_model,
		const long    N2,
		const long    n_bins_f1,
		const double  f1_parameters[],
		const long    stopping_power_source_no,
		double        f1_d_Gy[],
		double        f1_dd_Gy[],
		double        frequency_1_Gy_f1[])
{
	long i, j;

	/*
	 * Get relative fluence for beam components
	 * Convert dose to fluence if necessary
	 */
	double*  fluence_cm2    =  (double*)calloc(n, sizeof(double));
	if(fluence_cm2_or_dose_Gy[0] < 0){
		double*  dose_Gy        =  (double*)calloc(n, sizeof(double));
		for (i = 0; i < n; i++){
			dose_Gy[i] = -1.0 * fluence_cm2_or_dose_Gy[i];
		}
		AT_fluence_cm2_from_dose_Gy(  n,
				E_MeV_u,
				particle_no,
				dose_Gy,
				material_no,
				stopping_power_source_no,
				fluence_cm2);
		free( dose_Gy );
	}else{
		for (i = 0; i < n; i++){
			fluence_cm2[i] = fluence_cm2_or_dose_Gy[i];
		}
	}
	double*  norm_fluence                                 =  (double*)calloc(n, sizeof(double));
	AT_normalize(    n,
			fluence_cm2,
			norm_fluence);
	free( fluence_cm2 );

	/*
	 * Prepare single impact local dose distribution histogram
	 */

	if(n_bins_f1 > 0){
		const double step		= AT_N2_to_step(N2);
		const long   histo_type	= AT_histo_log;

		// Find lowest and highest dose (looking at ALL particles)
		// TODO: redundant, already used in finding number of bins, replace
		double  d_min_f1      =  f1_parameters[0*AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 3];
		double  d_max_f1      =  f1_parameters[0*AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 4];
		for (i = 1; i < n; i++){
			d_min_f1          =  GSL_MIN(f1_parameters[i*AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 3], d_min_f1);
			d_max_f1          =  GSL_MAX(f1_parameters[i*AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 4], d_max_f1);
		}

		double	 lowest_left_limit_f1 = d_min_f1;

		AT_histo_midpoints(n_bins_f1,
				lowest_left_limit_f1,
				step,
				histo_type,
				f1_d_Gy);

		AT_histo_bin_widths(n_bins_f1,
				lowest_left_limit_f1,
				step,
				histo_type,
				f1_dd_Gy);

		for (i = 0; i < n_bins_f1; i++){
			frequency_1_Gy_f1[i] = 0.0;
		}

		/*
		 * Fill histogram with single impact distribution(s) from individual components
		 */

		// loop over all components (i.e. particles and energies), compute contribution to f1
		long n_bins_used = 1;
		for (i = 0; i < n; i++){

			// Find lowest and highest dose for component
			double  d_min_f1_comp   =  f1_parameters[i*AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 3];
			double  d_max_f1_comp   =  f1_parameters[i*AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 4];

			// Find position and number of bins for component f1 in overall f1
			long lowest_bin_no_comp  		 	= AT_histo_bin_no(n_bins_f1,
					lowest_left_limit_f1,
					step,
					histo_type,
					d_min_f1_comp);
			long highest_bin_no_comp 			= AT_histo_bin_no(n_bins_f1,
					lowest_left_limit_f1,
					step,
					histo_type,
					d_max_f1_comp);
			long n_bins_f1_comp      			=  highest_bin_no_comp - lowest_bin_no_comp + 1;


			if (n_bins_f1_comp > 1){
				/*
				 * Compute component F1 (accumulated single impact density)
				 * Computation is done with bin limits as sampling points and later differential
				 * f1 will be computed (therefore we need one bin more)
				 * The lowest and highest value for F1 have however to be adjusted as they might
				 * not coincide with the actual min/max values for dose, r, and F1 resp.
				 * They bin widths have to be the same though to assure the integral to be 1
				 *
				 * At the limits F1 will be set to 0 and 1, resp. This enable to account for all
				 * dose, e.g. also in the core, where many radii have the same dose. This procedure,
				 * however, will only work with monotonously falling RDDs which we can assume for all
				 * realistic cases.
				 */
				double*  dose_left_limits_Gy_F1_comp =  (double*)calloc(n_bins_f1_comp + 1, sizeof(double));
				double*  r_m_comp           		 =  (double*)calloc(n_bins_f1_comp + 1, sizeof(double));
				double*  F1_comp        			 =  (double*)calloc(n_bins_f1_comp + 1, sizeof(double));

				// left limit of lowest bin for component
				double   lowest_left_limit_f1_comp = 0.0;
				AT_histo_left_limit(n_bins_f1,
						lowest_left_limit_f1,
						step,
						histo_type,
						lowest_bin_no_comp,
						&lowest_left_limit_f1_comp);

				// get all left limits
				AT_histo_left_limits(n_bins_f1_comp + 1,
						lowest_left_limit_f1_comp,
						step,
						histo_type,
						dose_left_limits_Gy_F1_comp);

				// compute radius as function of dose (inverse RDD),
				// but not for lowest and highest value (i.e. 'n_bins_f1_comp - 1'
				// instead of 'n_bins_f1_comp + 1' and &dose_left_limits_Gy_F1_comp[1]
				// as entry point instead of dose_left_limits_Gy_F1_comp
				// exit in case of problems
				int inverse_RDD_status_code = AT_r_RDD_m  (  n_bins_f1_comp - 1,
						&dose_left_limits_Gy_F1_comp[1],
						E_MeV_u[i],
						particle_no[i],
						material_no,
						rdd_model,
						rdd_parameter,
						er_model,
						stopping_power_source_no,
						&r_m_comp[1]);

				if( inverse_RDD_status_code != 0 ){
#ifndef NDEBUG
					printf("Problem in evaluating inverse RDD in AT_SC_get_f1, probably wrong combination of ER and RDD used\n");
#endif
					char rdd_model_name[100];
					AT_RDD_name_from_number(rdd_model, rdd_model_name);
					char er_model_name[100];
					getERName( er_model, er_model_name);
#ifndef NDEBUG
					printf("rdd_model: %ld (%s), er_model: %ld (%s)\n", rdd_model, rdd_model_name, er_model, er_model_name);
					exit(EXIT_FAILURE);
#endif
				}

				// compute F1 as function of radius
				// use F1 - 1 instead of F1 to avoid numeric cut-off problems
				double r_max_m_comp = f1_parameters[i * AT_SC_F1_PARAMETERS_SINGLE_LENGTH + 2];
				for (j = 1; j < n_bins_f1_comp; j++){
					F1_comp[j]            = gsl_pow_2(r_m_comp[j] / r_max_m_comp);
				}

				// Set extreme values of F1
				F1_comp[0]					= 1.0;
				F1_comp[n_bins_f1_comp]		= 0.0;

				// Write out F1 for debugging
				FILE* output = fopen("F1_output.csv", "w");
				fprintf(output, "bin.no;r.m;d.Gy;F1\n");
				for (j = 0; j < n_bins_f1_comp + 1; j++){
					fprintf(output,
							"%ld;%7.6e;%7.6e;%7.6e\n",
							j, r_m_comp[j], dose_left_limits_Gy_F1_comp[j], F1_comp[j]);
				}
				fclose(output);

				// now compute f1 as the derivative of F1 and add to overall f1
				double f1_comp;
				for (j = 0; j < n_bins_f1_comp; j++){
					f1_comp				  						=  (F1_comp[j] - F1_comp[j + 1]) / (dose_left_limits_Gy_F1_comp[j + 1] - dose_left_limits_Gy_F1_comp[j]);
					frequency_1_Gy_f1[lowest_bin_no_comp + j]   += norm_fluence[i] * f1_comp;
				}

				// adjust the density in first and last bin, because upper limit is not d.max.Gy and lower not d.min.Gy
				free(dose_left_limits_Gy_F1_comp);
				free(r_m_comp);
				free(F1_comp);
			}
			else{ // in case of n_bins_df == 1 (all doses fall into single bin, just add a value of 1.0
				frequency_1_Gy_f1[lowest_bin_no_comp ]        +=  norm_fluence[i] * 1.0 / f1_dd_Gy[lowest_bin_no_comp];
			}

			// remember highest bin used
			n_bins_used          =  GSL_MAX(n_bins_used, highest_bin_no_comp);
		}

		// normalize f1 (should be ok anyway but there could be small round-off errors)
		double  f1_norm    =  0.0;
		for (i = 0; i < n_bins_f1; i++){
			f1_norm    +=    frequency_1_Gy_f1[i] * f1_dd_Gy[i];
		}
		for (i = 0; i < n_bins_f1; i++){
			frequency_1_Gy_f1[i]    /=    f1_norm;
		}
	} // if(f1_d_Gy != NULL)

	// Write out f1 for debugging
	FILE* output = fopen("f1_output.csv", "w");
	fprintf(output, "bin.no;d.Gy;dd.Gy;f1\n");
	for (int j = 0; j < n_bins_f1; j++){
		fprintf(output,
				"%d;%7.6e;%7.6e;%7.6e\n",
				j, f1_d_Gy[j], f1_dd_Gy[j], frequency_1_Gy_f1[j]);
	}
	fclose(output);
	free( norm_fluence );
}