Select Git revision
w-stacking-fftw.c
-
Claudio Gheller authoredClaudio Gheller authored
Commons.h 20.43 KiB
/* Copyright (C) 2024 INAF - Osservatorio Astronomico di Cagliari
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
A copy of the GNU General Public License is distributed along with
this program in the COPYING file. If not, see: <https://www.gnu.org/licenses/>.
*/
/*! \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 dynamically 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 INCLUDE_COMMONS_H_
#define INCLUDE_COMMONS_H_
#ifdef USE_MPI
#include <mpi.h>
#endif
class mixMPI;
/*! \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 Contiguous RMI vector.
dcomplex *vec_rmi;
//! \brief Contiguous REI vector.
dcomplex *vec_rei;
//! \brief Contiguous W vector.
dcomplex *vec_w;
//! \brief Contiguous VINTS vector
dcomplex *vec_vints;
public:
//! \brief NLMMT = 2 * LM * (LM + 2).
int nlmmt;
//! \brief Number of configurations
int configurations;
//! \brief QUESTION: definition?
dcomplex **rmi;
//! \brief QUESTION: definition?
dcomplex **rei;
//! \brief QUESTION: definition?
dcomplex **w;
//! \brief QUESTION: definition?
dcomplex *fsas;
//! \brief QUESTION: definition?
dcomplex *vint;
//! \brief QUESTION: definition?
dcomplex **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?
dcomplex ***sas;
/*! \brief C1 instance constructor.
*
* \param gconf: `GeometryConfiguration *` Pointer to a geometry configuration object.
* \param sconf: `ScattererConfiguration *` Pointer to a scatterer configuration object.
*/
C1(GeometryConfiguration *gconf, ScattererConfiguration *sconf);
/*! \brief C1 instance constructor copying all contents from a preexisting template
*
* \param rhs: `C1` preexisting template.
*/
C1(const C1& rhs);
#ifdef MPI_VERSION
/*! \brief C1 instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C1(const mixMPI *mpidata);
/*! \brief send C1 instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
//! \brief C1 instance destroyer.
~C1();
};
/*! \brief Representation of the FORTRAN C2 blocks.
*
*/
class C2 {
protected:
//! \brief Number of spheres.
int nsph;
//! \brief Number of required orders.
int nhspo;
//! \brief QUESTION: what is nl?
int nl;
public:
//! \brief QUESTION: definition?
dcomplex *ris;
//! \brief QUESTION: definition?
dcomplex *dlri;
//! \brief QUESTION: definition?
dcomplex *dc0;
//! \brief QUESTION: definition?
dcomplex *vkt;
//! Vector of scaled sizes. QUESTION: correct?
double *vsz;
/*! \brief C2 instance constructor.
*
* \param gconf: `GeometryConfiguration*` Pointer to a GeometryConfiguration instance.
* \param sconf: `ScattererConfiguration*` Pointer to a ScattererConfiguration instance.
*/
C2(GeometryConfiguration *gconf, ScattererConfiguration *sconf);
/*! \brief C2 instance constructor copying its contents from preexisting instance.
*
* \param rhs: `C2` object to copy contents from
*/
C2(const C2& rhs);
//! \brief C2 instance destroyer.
~C2();
#ifdef MPI_VERSION
/*! \brief C2 instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C2(const mixMPI *mpidata);
/*! \brief send C2 instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
/*! \brief Representation of the FORTRAN C3 blocks.
*/
class C3 {
public:
//! \brief QUESTION: definition?
dcomplex tfsas;
//! \brief QUESTION: definition?
dcomplex **tsas;
//! \brief QUESTION: definition?
double gcs;
//! \brief QUESTION: definition?
double scs;
//! \brief QUESTION: definition?
double ecs;
//! \brief QUESTION: definition?
double acs;
/*! \brief C3 instance constructor.
*/
C3();
/*! \brief C3 instance constructor copying its contents from a preexisting object.
*/
C3(const C3& rhs);
/*! \brief C3 instance destroyer.
*/
~C3();
#ifdef MPI_VERSION
/*! \brief C3 instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C3(const mixMPI *mpidata);
/*! \brief send C3 instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
/*! \brief Representation of the FORTRAN C4 blocks.
*/
class C4 {
public:
//! \brief LITPO = 2 * LI + 1.
int litpo;
//! \brief LITPOS = LITPO * LITPO
int litpos;
//! \brief LMPO = LM + 1.
int lmpo;
//! \brief LMTPO = 2 * LM + 1.
int lmtpo;
//! \brief LMTPOS = LMTPO * LMTPO.
int lmtpos;
//! \brief Internal field expansion order.
int li;
//! \brief QUESTION: definition?
int nlim;
//! \brief External field expansion order.
int le;
//! \brief QUESTION: definition?
int nlem;
//! \brief Maximum field expansion order.
int lm;
//! \brief Number of spheres.
int nsph;
//! \brief QUESTION: definition?
int nv3j;
/*! \brief C4 instance constructor.
*
* \param gconf: `GeometryConfiguration*` Pointer to a GeometryConfiguration instance.
*/
C4(GeometryConfiguration *gconf);
/*! \brief C4 instance constructor copying its contents from a preexisting object.
*
* \param rhs: `C4&` Reference of the object to be copied.
*/
C4(const C4& rhs);
/*! \brief C4 instance destroyer.
*/
~C4();
#ifdef MPI_VERSION
/*! \brief C4 instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C4(const mixMPI *mpidata);
/*! \brief send C4 instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
/*! \brief Vectors and matrices that are specific to cluster C1 blocks.
*
*/
class C1_AddOns {
protected:
//! \brief Number of spheres.
int nsph;
//! \brief QUESTION: definition?
int nlemt;
//! \brief Maximum expansion order plus one. QUESTION: correct?
int lmpo;
//! \brief QUESTION: definition?
int litpo;
//! \brief QUESTION: definition?
int lmtpo;
//! \brief QUESTION: definition?
int litpos;
//! \brief QUESTION: definition?
int lmtpos;
//! \brief QUESTION: definition?
int nv3j;
//! \brief QUESTION: definition?
int lm;
public:
//! \brief QUESTION: definition?
dcomplex *vh;
//! \brief QUESTION: definition?
dcomplex *vj0;
//! \brief QUESTION: definition?
dcomplex *vj;
//! \brief QUESTION: definition?
dcomplex *vyhj;
//! \brief QUESTION: definition?
dcomplex *vyj0;
//! \brief QUESTION: definition?
dcomplex **am0m;
//! \brief QUESTION: definition?
dcomplex *am0v;
//! \brief QUESTION: definition?
dcomplex *vintm;
//! \brief QUESTION: definition?
dcomplex *vintt;
//! \brief QUESTION: definition?
dcomplex **fsac;
//! \brief QUESTION: definition?
dcomplex **sac;
//! \brief QUESTION: definition?
dcomplex **fsacm;
//! \brief QUESTION: definition?
double *scsc;
//! \brief QUESTION: definition?
dcomplex *scscp;
//! \brief QUESTION: definition?
double *ecsc;
//! \brief QUESTION: definition?
double *ecscm;
//! \brief QUESTION: definition?
double *scscm;
//! \brief QUESTION: definition?
dcomplex *ecscp;
//! \brief QUESTION: definition?
dcomplex *scscpm;
//! \brief QUESTION: definition?
dcomplex *ecscpm;
//! \brief QUESTION: definition?
double *v3j0;
//! \brief QUESTION: definition?
double *sscs;
//! \brief QUESTION: definition?
int **ind3j;
/*! \brief C1_AddOns instance constructor.
*
* \param c4: `C4 *` Pointer to a C4 structure.
*/
C1_AddOns(C4 *c4);
/*! \brief C1_AddOns instance constructor copying contents from a preexisting object.
*
* \param rhs: `C1_AddOns` preexisting object to copy from.
*/
C1_AddOns(const C1_AddOns& rhs);
//! \brief C1_AddOns instance destroyer.
~C1_AddOns();
#ifdef MPI_VERSION
/*! \brief C1_AddOns instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C1_AddOns(const mixMPI *mpidata);
/*! \brief send C1_AddOns instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
/*! \brief Representation of the FORTRAN C6 blocks.
*/
class C6 {
public:
//! \brief LMTPO = 2 * LM + 1.
int lmtpo;
//! \brief QUESTION: definition?
double *rac3j;
/*! \brief C6 instance constructor.
*
* \param lmtpo: `int` QUESTION: definition?
*/
C6(int lmtpo);
/*! \brief C6 instance constructor copying contents from preexisting object.
*
* \param lmtpo: `int` QUESTION: definition?
*/
C6(const C6& rhs);
/*! \brief C6 instance destroyer.
*/
~C6();
#ifdef MPI_VERSION
/*! \brief C6 instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C6(const mixMPI *mpidata);
/*! \brief send C6 instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
/*! \brief Representation of the FORTRAN C9 blocks.
*/
class C9 {
protected:
//! \brief Number of rows in the GIS and GLS matrices
int gis_size_0;
//! \brief Number of rows in the SAM matrix
int sam_size_0;
//! \brief QUESTION: definition?
int nlem;
//! \brief QUESTION: definition?
int nlemt;
public:
//! \brief QUESTION: definition?
dcomplex **gis;
//! \brief QUESTION: definition?
dcomplex **gls;
//! \brief QUESTION: definition?
dcomplex **sam;
/*! \brief C9 instance constructor.
*
* \param ndi: `int` QUESTION: definition?
* \param nlem: `int` QUESTION: definition?
* \param ndit: `int` QUESTION: definition?
* \param nlemt: `int` QUESTION: definition?
*/
C9(int ndi, int nlem, int ndit, int nlemt);
/*! \brief C9 instance constructor copying contents from preexisting object.
*
* \param rhs: `C9` preexisting object to copy from
*/
C9(const C9& rhs);
/*! \brief C9 instance destroyer.
*/
~C9();
#ifdef MPI_VERSION
/*! \brief C9 instance constructor copying all contents off MPI broadcast from MPI process 0
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
C9(const mixMPI *mpidata);
/*! \brief send C9 instance from MPI process 0 via MPI broadcasts to all other processes
*
* \param mpidata: `mixMPI *` pointer to MPI data structure.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
/*! \brief structure with essential MPI data.
*/
class mixMPI {
public:
//! \brief was MPI initialised?
bool mpirunning;
//! \brief MPI rank
int rank;
//! \brief MPI nprocs
int nprocs;
/*! \brief empty mixMPI instance constructor.
*/
mixMPI();
/*! \brief mixMPI instance constructor from an actual MPI communicator.
*/
#ifdef MPI_VERSION
mixMPI(MPI_Comm comm);
#endif
/*! \brief mixMPI instance constructor copying its contents from a preexisting object.
*/
mixMPI(const mixMPI& rhs);
/*! \brief mixMPI instance destroyer.
*/
~mixMPI();
};
/*! \brief A data structure representing the information used for a single scale
* of the CLUSTER case.
*/
class ClusterIterationData {
public:
//! \brief Pointer to a C1 structure.
C1 *c1;
//! \brief Pointer to a C1_AddOns structure.
C1_AddOns *c1ao;
//! \brief Pointer to a C2 structure.
C2 *c2;
//! \brief Pointer to a C3 structure.
C3 *c3;
//! brief Pointer to a C4 structure.
C4 *c4;
//! \brief Pointer to a C6 structure.
C6 *c6;
//! \brief Pointer to a C9 structure.
C9 *c9;
//! \brief Pointer to a formatted output file.
double *gaps;
double **tqse;
dcomplex **tqspe;
double **tqss;
dcomplex **tqsps;
double ****zpv;
double **gapm;
dcomplex **gappm;
double *argi;
double *args;
double **gap;
dcomplex **gapp;
double **tqce;
dcomplex **tqcpe;
double **tqcs;
dcomplex **tqcps;
double *duk;
double **cextlr;
double **cext;
double **cmullr;
double **cmul;
double *gapv;
double *tqev;
double *tqsv;
double *u;
double *us;
double *un;
double *uns;
double *up;
double *ups;
double *unmp;
double *unsmp;
double *upmp;
double *upsmp;
double scan;
double cfmp;
double sfmp;
double cfsp;
double sfsp;
double qsfi;
double sqsfi;
dcomplex *am_vector;
dcomplex **am;
dcomplex arg;
//! \brief Wave vector.
double vk;
//! \brief Wave number.
double wn;
double xip;
int number_of_scales;
int xiblock;
int firstxi;
int lastxi;
ClusterIterationData(GeometryConfiguration *gconf, ScattererConfiguration *sconf, const mixMPI *mpidata);
ClusterIterationData(const ClusterIterationData& rhs);
#ifdef MPI_VERSION
ClusterIterationData(const mixMPI *mpidata);
/*! \brief Broadcast over MPI the ClusterIterationData instance from MPI process 0 to all others.
*
* When using MPI, the initial ClusterIterationData instance created by MPI process 0
* needs to be replicated on all other processes. This function sends it using
* MPI broadcast calls. The MPI broadcast calls in this function must match those
* in the constructor using the mixMPI pointer.
*
* \param mpidata: `mixMPI *` Pointer to the mpi structure used to do the MPI broadcast.
*/
void mpibcast(const mixMPI *mpidata);
#endif
~ClusterIterationData();
};
/*! \brief A data structure representing the angles to be evaluated in the problem.
*
*/
class ScatteringAngles {
protected:
//! \brief Number of incident field azimuth angles.
int _nth;
//! \brief Number of scattered field azimuth angles.
int _nths;
//! \brief Number of incident field elevation angles.
int _nph;
//! \brief Number of scattered field elevation angles.
int _nphs;
//! \brief Number of incident field propagation angles.
int _nk;
//! \brief Number of scattered field propagation angles.
int _nks;
//! \brief Total number of field propagation angles.
int _nkks;
//! \brief First incident field azimuth angle.
double _th;
//! \brief Incident field azimuth angle increment.
double _thstp;
//! \brief Last incident field azimuth angle.
double _thlst;
//! \brief First scattered field azimuth angle.
double _ths;
//! \brief Scattered field azimuth angle increment.
double _thsstp;
//! \brief Last scattered field azimuth angle.
double _thslst;
//! \brief First incident field elevation angle.
double _ph;
//! \brief Incident field elevation angle increment.
double _phstp;
//! \brief Last incident field elevation angle.
double _phlst;
//! \brief First scattered field elevation angle.
double _phs;
//! \brief Scattered field elevation angle increment.
double _phsstp;
//! \brief Last scattered field elevation angle.
double _phslst;
//! \brief Azimuth scattering deflection.
double _thsca;
public:
//! \brief Read only view of `_nth`.
const int& nth = _nth;
//! \brief Read only view of `_nths`.
const int& nths = _nths;
//! \brief Read only view of `_nph`.
const int& nph = _nph;
//! \brief Read only view of `_nphs`.
const int& nphs = _nphs;
//! \brief Read only view of `_nk`.
const int& nk = _nk;
//! \brief Read only view of `_nks`.
const int& nks = _nks;
//! \brief Read only view of `_nkks`.
const int& nkks = _nkks;
//! \brief Read only view of `_th`.
const double& th = _th;
//! \brief Read only view of `_thstp`.
const double& thstp = _thstp;
//! \brief Read only view of `_thlst`.
const double& thlst = _thlst;
//! \brief Read only view of `_ths`.
const double& ths = _ths;
//! \brief Read only view of `_thsstp`.
const double& thsstp = _thsstp;
//! \brief Read only view of `_thslst`.
const double& thslst = _thslst;
//! \brief Read only view of `_ph`.
const double& ph = _ph;
//! \brief Read only view of `_phstp`.
const double& phstp = _phstp;
//! \brief Read only view of `_phlst`.
const double& phlst = _phlst;
//! \brief Read only view of `_phs`.
const double& phs = _phs;
//! \brief Read only view of `_phsstp`.
const double& phsstp = _phsstp;
//! \brief Read only view of `_phslst`.
const double& phslst = _phslst;
//! \brief Read only view of `_thsca`.
const double& thsca = _thsca;
/*! \brief ScatteringAngles instance constructor.
*
* \param gconf: `GeometryConfiguration*` Pointer to a GeometryConfiguration object.
*/
ScatteringAngles(GeometryConfiguration *gconf);
/*! \brief ScatteringAngles copy constructor.
*
* \param rhs: `ScatteringAngles&` Reference to the ScatteringAngles object to be copied.
*/
ScatteringAngles(const ScatteringAngles &rhs);
#ifdef MPI_VERSION
/*! \brief ScatteringAngles copy from MPI broadcast.
*
* \param mpidata: `mixMPI *` Pointer to the mpidata instance used to copy the data.
*/
ScatteringAngles(const mixMPI *mpidata);
/*! \brief Broadcast over MPI the ScatteringAngles instance from MPI process 0 to all others.
*
* When using MPI, the initial ScatteringAngles instance created by MPI process 0
* needs to be replicated on all other processes. This function sends it using
* MPI broadcast calls. The MPI broadcast calls in this function must match those
* in the constructor using the mixMPI pointer.
*
* \param mpidata: `mixMPI *` Pointer to the mpi structure used to do the MPI broadcast.
*/
void mpibcast(const mixMPI *mpidata);
#endif
};
#endif