/*! \file Configuration.h */ #ifndef INCLUDE_CONFIGURATION_H_ #define INCLUDE_CONFIGURATION_H_ #include #include #include /** * \brief Exception for open file error handlers. */ class OpenConfigurationFileException: public std::exception { protected: //! \brief Name of the file that was accessed. std::string file_name; public: /** * \brief Exception instance constructor. * * \param name: `string` Name of the file that was accessed. */ OpenConfigurationFileException(std::string name) { file_name = name; } /** * \brief Exception message. */ virtual const char* what() const throw() { std::string message = "Error opening configuration file: " + file_name; return message.c_str(); } }; /** * \brief Exception for unrecognized configuration data sets. */ class UnrecognizedConfigurationException: public std::exception { protected: //! Description of the problem. std::string message; public: /** * \brief Exception instance constructor. * * \param problem: `string` Description of the problem that occurred. */ UnrecognizedConfigurationException(std::string problem) { message = problem; } /** * \brief Exception message. */ virtual const char* what() const throw() { return message.c_str(); } }; /** * \brief A class to represent the configuration of the scattering geometry. * * GeometryConfiguration is a class designed to store the necessary configuration * data to describe the scattering geometry, including the distribution of the * particle components, the orientation of the incident and scattered radiation * fields and their polarization properties. */ class GeometryConfiguration { //! Temporary work-around to allow sphere() peeking in. friend void sphere(); protected: //! \brief Number of spherical components. int number_of_spheres; //! \brief Maximum expansion order of angular momentum. int l_max; //! \brief Incident field polarization status (0 - linear, 1 - circular). int in_pol; //! \brief Number of transition points. QUESTION: correct? int npnt; //! \brief Transition smoothness. QUESTION: correct? int npntts; //! \brief Type of meridional plane definition. int meridional_type; //! \brief Transition matrix layer ID. QUESTION: correct? int jwtm; //! \brief Incident field initial azimuth. double in_theta_start; //! \brief Incident field azimuth step. double in_theta_step; //! \brief Incident field final azimuth. double in_theta_end; //! \brief Scattered field initial azimuth. double sc_theta_start; //! \brief Scattered field azimuth step. double sc_theta_step; //! \brief Scattered field final azimuth. double sc_theta_end; //! \brief Incident field initial elevation. double in_phi_start; //! \brief Incident field elevation step. double in_phi_step; //! \brief Incident field final elevation. double in_phi_end; //! \brief Scattered field initial elevation. double sc_phi_start; //! \brief Scattered field elevation step. double sc_phi_step; //! \brief Scattered field final elevation. double sc_phi_end; //! \brief Vector of spherical components X coordinates. double *sph_x; //! \brief Vector of spherical components Y coordinates. double *sph_y; //! \brief Vector of spherical components Z coordinates. double *sph_z; public: /*! \brief Build a scattering geometry configuration structure. * * \param nsph: `int` Number of spheres to be used in calculation. * \param lm: `int` Maximum field angular momentum expansion order. * \param in_pol: `int` Incident field polarization status * \param npnt: `int` Number of transition points. QUESTION: correct? * \param npntts: `int` Transition smoothness. QUESTION: correct? * \param meridional_type: `int` Type of meridional plane definition (<0 * for incident angles, 0 if determined by incidence and observation, =1 * accross z-axis for incidence and observation, >1 across z-axis as a * function of incidence angles for fixed scattering). * \param x: `double*` Vector of spherical components X coordinates. * \param y: `double*` Vector of spherical components Y coordinates. * \param z: `double*` Vector of spherical components Z coordinates. * \param in_th_start: `double` Incident field starting azimuth angle. * \param in_th_step: `double` Incident field azimuth angle step. * \param in_th_end: `double` Incident field final azimuth angle. * \param sc_th_start: `double` Scattered field starting azimuth angle. * \param sc_th_step: `double` Scattered field azimuth angle step. * \param sc_th_end: `double` Scattered field final azimuth angle. * \param in_ph_start: `double` Incident field starting elevation angle. * \param in_ph_step: `double` Incident field elevation angle step. * \param in_ph_end: `double` Incident field final elevation angle. * \param sc_ph_start: `double` Scattered field starting elevation angle. * \param sc_ph_step: `double` Scattered field elevation angle step. * \param sc_ph_end: `double` Scattered field final elevation angle. * \param jwtm: `int` Transition Matrix layer ID. QUESTION: correct? */ GeometryConfiguration( int nsph, int lm, int in_pol, int npnt, int npntts, int meridional_type, double *x, double *y, double *z, double in_th_start, double in_th_step, double in_th_end, double sc_th_start, double sc_th_step, double sc_th_end, double in_ph_start, double in_ph_step, double in_ph_end, double sc_ph_start, double sc_ph_step, double sc_ph_end, int jwtm ); /*! \brief Destroy a GeometryConfiguration instance. */ ~GeometryConfiguration(); /*! \brief Build geometry configuration from legacy configuration input file. * * To allow for consistency tests and backward compatibility, geometry * configurations can be built from legacy configuration files. This function * replicates the approach implemented by the FORTRAN SPH and CLU codes, but * using a C++ oriented work-flow. * * \param file_name: `string` Name of the legacy configuration data file. * \return config: `GeometryConfiguration*` Pointer to object containing the * configuration data. */ static GeometryConfiguration *from_legacy(std::string file_name); }; /** * \brief A class to represent scatterer configuration objects. * * ScattererConfiguration is a class designed to store the necessary configuration * data to describe the scatterer properties. */ class ScattererConfiguration { //! Temporary work-around to allow sphere() peeking in. friend void sphere(); protected: //! \brief Matrix of dielectric parameters with size [NON_TRANS_LAYERS x N_SPHERES x LAYERS]. std::complex ***dc0_matrix; //! \brief Vector of sphere radii expressed in m, with size [N_SPHERES]. double *radii_of_spheres; //! \brief Matrix of fractional transition radii with size [N_SPHERES x LAYERS]. double **rcf; //! \brief Vector of sphere ID numbers, with size [N_SPHERES]. int *iog_vec; //! \brief Vector of layer numbers for every sphere, with size [N_SPHERES]. int *nshl_vec; //! \brief Vector of scale parameters, with size [N_SCALES]. double *scale_vec; //! \brief Name of the reference variable type (one of XIV, WNS, WLS, PUS, EVS). std::string reference_variable_name; //! \brief Number of spherical components. int number_of_spheres; //! \brief Number of scales to use in calculation. int number_of_scales; //! \brief Type of dielectric functions (<0 at XIP, =0 as function of XI, >0 contants). int idfc; //! \brief External medium dielectric constant. QUESTION: correct? double exdc; //! \brief WP. QUESTION: better definition? double wp; //! \brief Peak XI. QUESTION: correct? double xip; //! \brief Flag to control whether to add an external layer. bool use_external_sphere; public: /*! \brief Build a scatterer configuration structure. * * Prepare a default configuration structure by allocating the necessary * memory structures. * * \param nsph: `int` The number of spheres in the simulation. * \param scale_vector: `double*` The radiation-particle scale vector. * \param nxi: `int` The number of radiation-particle scalings. * \param variable_name: `string` The name of the radiation-particle scaling type. * \param iog_vector: `int*` Array of sphere identification numbers. QUESTION: correct? * \param ros_vector: `double*` Sphere radius array. * \param nshl_vector: `int*` Array of layer numbers. * \param rcf_vector: `double**` Array of fractional break radii. QUESTION: correct? * \param dielectric_func_type: `int` Type of dielectric function definition (=0 for constant, * \>0 as function of scale parameter, <0 for functions at XIP value and XI is scale factor * for dimensions). * \param dc_matrix: Matrix of reference dielectric constants. * \param has_external: `bool` Flag to set whether to add an external spherical layer. * \param exdc: `double` EXDC * \param wp: `double` wp * \param xip: `double` xip */ ScattererConfiguration( int nsph, double *scale_vector, int nxi, std::string variable_name, int *iog_vector, double *ros_vector, int *nshl_vector, double **rcf_vector, int dielectric_func_type, std::complex ***dc_matrix, bool has_external, double exdc, double wp, double xip ); /*! \brief Destroy a scatterer configuration instance. */ ~ScattererConfiguration(); /*! \brief Build configuration from binary configuration input file. * * The configuration step can save configuration data as a binary file. The original * FORTRAN code used this possibility to manage communication between the configuring * code and the calculation program. This possibility is maintained, in case the * configuration step needs to be separated from the calculation execution. In this * case, `from_binary()` is the class method that restores a ScattererConfiguration * object from a previously saved binary file. * * \param file_name: `string` Name of the binary configuration data file. * \param mode: `string` Binary encoding. Can be one of "LEGACY", ... . Optional * (default is "LEGACY"). * \return config: `ScattererConfiguration*` Pointer to object containing the * scatterer configuration data. */ static ScattererConfiguration* from_binary(std::string file_name, std::string mode = "LEGACY"); /*! \brief Build scatterer configuration from legacy configuration input file. * * To allow for consistency tests and backward compatibility, ScattererConfiguration * objects can be built from legacy configuration files. This function replicates * the approach implemented by the FORTRAN EDFB code, but using a C++ oriented * work-flow. * * \param file_name: `string` Name of the legacy configuration data file. * \return config: `ScattererConfiguration*` Pointer to object containing the * scatterer configuration data. */ static ScattererConfiguration* from_dedfb(std::string file_name); /*! \brief Print the contents of the configuration object to terminal. * * In case of quick debug testing, `ScattererConfiguration.print()` allows printing * a formatted summary of the configuration data to terminal. */ void print(); /*! \brief Write the scatterer configuration data to binary output. * * The execution work-flow may be split in a configuration step and one or more * calculation steps. In case the calculation is not being run all-in-one, it can * be useful to save the configuration data. `ScattererConfiguration.write_binary()` * performs the operation of saving the configuration in binary format. This function * can work in legacy mode, to write backward compatible configuration files, as well * as by wrapping the data into common scientific formats (NB: this last option still * needs to be implemented). * * \param file_name: `string` Name of the file to be written. * \param mode: `string` Binary encoding. Can be one of "LEGACY", ... . Optional * (default is "LEGACY"). */ void write_binary(std::string file_name, std::string mode = "LEGACY"); /*! \brief Write the scatterer configuration data to formatted text output. * * Writing configuration to formatted text is an optional operation, which may turn * out to be useful for consistency checks. As a matter of fact, formatted configuration * output is not read back by the FORTRAN code work-flow and it can be safely omitted, * unless there is a specific interest in assessing that the legacy code and the * updated one are doing the same thing. * * \param file_name: `string` Name of the file to be written. */ void write_formatted(std::string file_name); }; #endif