Commit 9c447a2d authored by Giacomo Mulas's avatar Giacomo Mulas
Browse files

Merge branch 'sphere' into 'master'

Sphere

See merge request giacomo.mulas/np_tmcode!6
parents f6a3008c 8aeb080d
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -3,3 +3,4 @@ build/cluster/*
build/sphere/*
build/sphere/*
build/trapping/*
build/trapping/*
doc/build/*
doc/build/*
+8 −1
Original line number Original line Diff line number Diff line
SUBDIRS := cluster sphere trapping
SUBDIRS := cluster sphere trapping
BUILDDIR=../build
SRCDIR=$(PWD)
BUILDDIR=$(SRCDIR)/../build
DOCSDIR=$(SRCDIR)/../doc


all: $(SUBDIRS)
all: $(SUBDIRS)


docs:
	cd $(DOCSDIR)/src; doxygen config.dox

$(SUBDIRS):
$(SUBDIRS):
	$(MAKE) -C $@
	$(MAKE) -C $@


@@ -15,5 +20,7 @@ wipe:
	rm -f $(BUILDDIR)/cluster/*
	rm -f $(BUILDDIR)/cluster/*
	rm -f $(BUILDDIR)/sphere/*
	rm -f $(BUILDDIR)/sphere/*
	rm -f $(BUILDDIR)/trapping/*
	rm -f $(BUILDDIR)/trapping/*
	if [ -d $(DOCSDIR)/build/html ]; then rm -r $(DOCSDIR)/build/html; fi
	if [ -d $(DOCSDIR)/build/latex ]; then rm -r $(DOCSDIR)/build/latex; fi


.PHONY: all $(SUBDIRS)
.PHONY: all $(SUBDIRS)
+24 −0
Original line number Original line Diff line number Diff line
@@ -7,3 +7,27 @@ This directory collects the source code of the original programs and the develop
The original code is contained in the folders named `cluster`, `sphere` and `trapping`. Each folder contains a `Makefile` to compile either the whole program set or the single programs. A global `Makefile`, which contains instructions to build all the original source code, is available directly in the `src` folder.
The original code is contained in the folders named `cluster`, `sphere` and `trapping`. Each folder contains a `Makefile` to compile either the whole program set or the single programs. A global `Makefile`, which contains instructions to build all the original source code, is available directly in the `src` folder.


In all cases, build commands executed through `make` will output the object files and the linked binaries in the proper folders under the build directory.
In all cases, build commands executed through `make` will output the object files and the linked binaries in the proper folders under the build directory.

## FORTRAN code setup and execution (requires `gfortran` and GNU `make`)

1. cd to the `src` folder
2. run `make`

   > make

3. cd to the `build/sphere` folder
4. run `sph` following the instructions given in `build\README.md`

## C++ code setup and execution (requires `g++` and GNU `make`)

1. cd to the `src` folder
2. run `make np_sphere`

   > make np_sphere

3. cd to the `build/sphere` folder
4. run `np_sphere`

   > ./np_sphere

5. check the consistency between the text files named `OSPH` and `c_OSPH`

src/include/Commons.h

0 → 100644
+131 −0
Original line number Original line Diff line number Diff line
/*! \file Commons.h
 *
 * \brief C++ porting of common data structures.
 *
 * Many functions of the original FORTRAN code share complex data blocks in
 * form of COMMON blocks. This poses the limit of freezing the structure of
 * the data blocks in the code, therefore implying the necessity to modify
 * the code to adapt it to the input and to recompile before running. C++,
 * on the contrary, offers the possibility to represent the necessary data
 * structures as classes that can dinamically instantiate the shared information
 * in the most convenient format for the current configuration. This approach
 * adds an abstraction layer that lifts the need to modify and recompile the
 * code depending on the input.
 *
 */

#ifndef SRC_INCLUDE_COMMONS_
#define SRC_INCLUDE_COMMONS_

#include <complex>

/*! \brief Representation of the FORTRAN C1 common blocks.
 *
 * C1 common blocks are used to store vector field expansions and geometric
 * properties, such as sphere sizes, positions and cross-sections. These are
 * used by functions such as `aps`, `diel`, `pwma`, `rabas`, `sscr0`, `sscr2`,
 * `wmamp`, `wmasp` and `dme`. QUESTION: correct?
 *
 * Due to the necessity to share the class contents with many functions that
 * need to read and update various fields, all shared members of C1 are declared
 * public (i.e., the class is just a structure with more advanced constructor
 * and destroyer). Further development may go in the direction of creating
 * a better encapsulation, either by unpacking the contents (recommended) or
 * by creating public methods to access protected fields (standard way, but not
 * recommended for HPC applications).
 */
class C1 {
protected:
	//! \brief Number of spheres.
	int nsph;
	//! \brief Maximum order of field expansion.
	int lm;
	//! \brief NLMMT. QUESTION: definition?
	int nlmmt;
public:
	//! \brief QUESTION: definition?
	std::complex<double> **rmi;
	//! \brief QUESTION: definition?
	std::complex<double> **rei;
	//! \brief QUESTION: definition?
	std::complex<double> **w;
	//! \brief QUESTION: definition?
	std::complex<double> *fsas;
	//! \brief QUESTION: definition?
	std::complex<double> **vints;
	//! \brief QUESTION: definition?
	double *sscs;
	//! \brief QUESTION: definition?
	double *sexs;
	//! \brief QUESTION: definition?
	double *sabs;
	//! \brief QUESTION: definition?
	double *sqscs;
	//! \brief QUESTION: definition?
	double *sqexs;
	//! \brief QUESTION: definition?
	double *sqabs;
	//! \brief QUESTION: definition?
	double *gcsv;
	//! \brief Vector of sphere X coordinates.
	double *rxx;
	//! \brief Vector of sphere X coordinates.
	double *ryy;
	//! \brief Vector of sphere X coordinates.
	double *rzz;
	//! \brief Vector of sphere radii.
	double *ros;
	//! \brief Matrix of spherical layer break radii. QUESTION: correct?
	double **rc;
	//! \brief Vector of spherical component identifiers.
	int *iog;
	//! \brief Vector of numbers of spherical layers.
	int *nshl;
	//! \brief QUESTION: definition?
	std::complex<double> ***sas;

	/*! \brief C1 instance constructor.
	 *
	 * \param ns: `int` Number of spheres.
	 * \param l_max: `int` Maximum order of field expansion.
	 */
	C1(int ns, int l_max);

	//! \brief C1 instance destroyer.
	~C1();
};

/*! \brief Representation of the FORTRAN C2 blocks.
 *
 */
class C2 {
	//! \brief Number of spheres.
	int nsph;
	//! \brief Number of required orders.
	int nhspo;
public:
	//! \brief QUESTION: definition?
	std::complex<double> *ris;
	//! \brief QUESTION: definition?
	std::complex<double> *dlri;
	//! \brief QUESTION: definition?
	std::complex<double> *dc0;
	//! \brief QUESTION: definition?
	std::complex<double> *vkt;
	//! Vector of scaled sizes. QUESTION: correct?
	double *vsz;

	/*! \brief C2 instance constructor.
	 *
	 * \param ns: `int` Number of spheres.
	 * \param nl: `int`
	 * \param npnt: `int`
	 * \param npntts: `int`
	 */
	C2(int ns, int nl, int npnt, int npntts);

	//! \brief C2 instance destroyer.
	~C2();
};

#endif
+321 −0
Original line number Original line Diff line number Diff line
/*! \file Configuration.h
 */

#ifndef INCLUDE_CONFIGURATION_H_
#define INCLUDE_CONFIGURATION_H_

#include <complex>
#include <exception>
#include <string>

/**
 * \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<double> ***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<double> ***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
Loading