From 50a311fab0b405928ed694f504ccc442f7eba7ba Mon Sep 17 00:00:00 2001 From: Giovanni La Mura <giovanni.lamura@inaf.it> Date: Thu, 26 Oct 2023 15:24:27 +0200 Subject: [PATCH] Initiate sph work-flow migration to C++ --- src/nptm.cpp | 23 ++++ src/sphere.cpp | 279 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 src/nptm.cpp create mode 100644 src/sphere.cpp diff --git a/src/nptm.cpp b/src/nptm.cpp new file mode 100644 index 00000000..0d74bb33 --- /dev/null +++ b/src/nptm.cpp @@ -0,0 +1,23 @@ +/*! \file nptm.cpp + */ + +#include <cstdio> +#include <string> +#include "include/Configuration.h" + +using namespace std; + +extern void sphere(); + +/*! \brief Main program entry point. + * + * This is the starting point of the execution flow. Here we may choose + * how to configure the code, e.g. by loading a legacy configuration file + * or some otherwise formatted configuration data set. The code can be + * linked to a luncher script or to a GUI oriented application that performs + * the configuration and runs the main program. + */ +int main(int argc, char **argv) { + sphere(); + return 0; +} diff --git a/src/sphere.cpp b/src/sphere.cpp new file mode 100644 index 00000000..1220ddbf --- /dev/null +++ b/src/sphere.cpp @@ -0,0 +1,279 @@ +#include <cstdio> +#include <fstream> +#include <string> +#include <complex> +#include "include/Configuration.h" +#include "include/sph_subs.h" + +using namespace std; + +//! \brief C++ implementation of SPH +void sphere() { + //complex<double> dc0[5]; + //complex<double> dc0m[2][4]; + complex<double> arg, s0, tfsas; + printf("INFO: making legacy configuration ...\n"); + ScattererConfiguration *conf = ScattererConfiguration::from_dedfb("../../test_data/sphere/DEDFB"); + conf->write_formatted("c_OEDFB"); + conf->write_binary("c_TEDF"); + delete conf; + printf("INFO: reading binary configuration ...\n"); + ScattererConfiguration *sconf = ScattererConfiguration::from_binary("c_TEDF"); + GeometryConfiguration *gconf = GeometryConfiguration::from_legacy("../../test_data/sphere/DSPH"); + if (sconf->number_of_spheres == gconf->number_of_spheres) { + int nsph = gconf->number_of_spheres; + C1 *c1 = new C1; + for (int i = 0; i < nsph; i++) { + c1->iog[i] = sconf->iog_vec[i]; + c1->nshl[i] = sconf->nshl_vec[i]; + c1->ros[i] = sconf->radii_of_spheres[i]; + } + for (int i = 0; i < gconf->l_max; i++) { + c1->rmi[i][0] = complex<double>(0.0, 0.0); + c1->rmi[i][1] = complex<double>(0.0, 0.0); + c1->rei[i][0] = complex<double>(0.0, 0.0); + c1->rei[i][1] = complex<double>(0.0, 0.0); + } + C2 *c2 = new C2; + FILE *output = fopen("c_OSPH", "w"); + fprintf(output, " READ(IR,*)NSPH,LM,INPOL,NPNT,NPNTTS,ISAM\n"); + fprintf( + output, + " %5d%5d%5d%5d%5d%5d\n", + gconf->number_of_spheres, + gconf->l_max, + gconf->in_pol, + gconf->npnt, + gconf->npntts, + gconf->meridional_type + ); + fprintf(output, " READ(IR,*)TH,THSTP,THLST,THS,THSSTP,THSLST\n"); + fprintf( + output, + " %9.3lE %9.3lE %9.3lE %9.3lE %9.3lE %9.3lE\n", + gconf->in_theta_start, + gconf->in_theta_step, + gconf->in_theta_end, + gconf->sc_theta_start, + gconf->sc_theta_step, + gconf->sc_theta_end + ); + fprintf(output, " READ(IR,*)PH,PHSTP,PHLST,PHS,PHSSTP,PHSLST\n"); + fprintf( + output, + " %9.3lE %9.3lE %9.3lE %9.3lE %9.3lE %9.3lE\n", + gconf->in_phi_start, + gconf->in_phi_step, + gconf->in_phi_end, + gconf->sc_phi_start, + gconf->sc_phi_step, + gconf->sc_phi_end + ); + fprintf(output, " READ(IR,*)JWTM\n"); + fprintf( + output, + " %5d\n", + gconf->jwtm + ); + fprintf(output, " READ(ITIN)NSPHT\n"); + fprintf(output, " READ(ITIN)(IOG(I),I=1,NSPH)\n"); + fprintf(output, " READ(ITIN)EXDC,WP,XIP,IDFC,NXI\n"); + fprintf(output, " READ(ITIN)(XIV(I),I=1,NXI)\n"); + fprintf(output, " READ(ITIN)NSHL(I),ROS(I)\n"); + fprintf(output, " READ(ITIN)(RCF(I,NS),NS=1,NSH)\n \n"); + double sml = 1.0e-3; + int nth = 0, nph = 0; + if (gconf->in_theta_step != 0.0) + nth = int((gconf->in_theta_end - gconf->in_theta_start) / gconf->in_theta_step + sml); + nth += 1; + if (gconf->in_phi_step != 0.0) + nph = int((gconf->in_phi_end - gconf->in_phi_start) / gconf->in_phi_step + sml); + nph += 1; + int nths = 0, nphs = 0; + double thsca; + if (gconf->meridional_type > 1) { // ISAM > 1, fixed scattering angle + nths = 1; + thsca = gconf->sc_theta_start - gconf->in_theta_start; + } else { //ISAM <= 1 + if (gconf->in_theta_step != 0.0) + nths = int((gconf->sc_theta_end - gconf->sc_theta_start) / gconf->sc_theta_step + sml); + nths += 1; + if (gconf->meridional_type == 1) { // ISAM = 1 + nphs = 1; + } else { // ISAM < 1 + if (gconf->sc_phi_step != 0.0) + nphs = int((gconf->sc_phi_end - gconf->sc_phi_start) / gconf->sc_phi_step + sml); + nphs += 1; + } + } + int nk = nth * nph; + int nks = nths * nphs; + int nkks = nk * nks; + int th1 = gconf->in_theta_start; + int ph1 = gconf->in_phi_start; + int ths1 = gconf->sc_theta_start; + int phs1 = gconf->sc_phi_start; + const double half_pi = acos(0.0); + const double pi = 2.0 * half_pi; + double gcs = 0.0; + for (int i116 = 1; i116 <= nsph; i116++) { + int iogi = c1->iog[i116 - 1]; + if (iogi >= i116) { + double gcss = pi * c1->ros[i116 - 1] * c1->ros[i116 - 1]; + c1->gcsv[i116 - 1] = gcss; + int nsh = c1->nshl[i116 - 1]; + for (int j115 = 1; j115 <= nsh; j115++) { + c1->rc[i116 - 1][j115 - 1] = sconf->rcf[i116 - 1][j115 - 1] * c1->ros[i116 - 1]; + } + } + gcs += c1->gcsv[iogi - 1]; + } + double ****zpv = new double***[gconf->l_max]; //[gconf->l_max][3][2][2]; // Matrix: dim[LM x 3 x 2 x 2] + for (int zi = 0; zi < gconf->l_max; zi++) { + zpv[zi] = new double**[3]; + for (int zj = 0; zj < 3; zj++) { + zpv[zi][zj] = new double*[2]; + for (int zk = 0; zk < 2; zk++) { + zpv[zi][zj][zk] = new double[2]; + } + } + } + thdps(gconf->l_max, zpv); + //DEBUG CODE + /* + for (int zi = 0; zi < gconf->l_max; zi++) { + for (int zj = 0; zj < 3; zj++) { + for (int zk = 0; zk < 2; zk++) { + if (zpv[zi][zj][zk][0] != 0.0) + printf( + "DEBUG: zpv[%d][%d][%d][0] = %.3lE\n", + zi, zj, zk, zpv[zi][zj][zk][0] + ); + if (zpv[zi][zj][zk][1] != 0.0) + printf( + "DEBUG: zpv[%d][%d][%d][1] = %.3lE\n", + zi, zj, zk, zpv[zi][zj][zk][1] + ); + } + } + } + */ + //END OF DEBUG CODE + double exri = sqrt(sconf->exdc); + fprintf(output, " REFR. INDEX OF EXTERNAL MEDIUM=%15.7lE\n", exri); + fstream tppoan; + tppoan.open("c_TPPOAN", ios::binary|ios::out); + if (tppoan.is_open()) { + int imode = 10; + tppoan.write(reinterpret_cast<char *>(&imode), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&(gconf->meridional_type)), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&(gconf->in_pol)), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&(sconf->number_of_scales)), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&nth), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&nph), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&nths), sizeof(int)); + tppoan.write(reinterpret_cast<char *>(&nphs), sizeof(int)); + + for (int nsi = 0; nsi < nsph; nsi++) + tppoan.write(reinterpret_cast<char *>(&(sconf->iog_vec[nsi])), sizeof(int)); + if (gconf->in_pol == 0) fprintf(output, " LIN\n"); + else fprintf(output, " CIRC\n"); + fprintf(output, " \n"); + double wn = sconf->wp / 3.0e8; + double sqsfi = 1.0; + double vk, vkarg; + if (sconf->idfc < 0) { + vk = sconf->xip * wn; + fprintf(output, " VK=%15.7lE, XI IS SCALE FACTOR FOR LENGTHS\n", vk); + fprintf(output, " \n"); + } + for (int jxi488 = 1; jxi488 <= sconf->number_of_scales; jxi488++) { + fprintf(output, "========== JXI =%3d ====================\n", jxi488); + double xi = sconf->scale_vec[jxi488 - 1]; + if (sconf->idfc >= 0) { + vk = xi * wn; + vkarg = vk; + fprintf(output, " VK=%15.7lE, XI=%15.7lE\n", xi, vk); + } else { // IDFC < 0 + vkarg = xi * vk; + sqsfi = 1.0 / (xi * xi); + fprintf(output, " XI=%15.7lE\n", xi); + } + tppoan.write(reinterpret_cast<char *>(&vk), sizeof(double)); + for (int i132 = 1; i132 <= nsph; i132++) { + int iogi = sconf->iog_vec[i132 - 1]; + if (iogi != i132) { + for (int l123 = 1; l123 <= gconf->l_max; l123++) { + // QUESTION: aren't RMI and REI still empty? + c1->rmi[l123 - 1][i132 - 1] = c1->rmi[l123 - 1][iogi - 1]; + c1->rei[l123 - 1][i132 - 1] = c1->rei[l123 - 1][iogi - 1]; + } + continue; // i132 + } + int nsh = sconf->nshl_vec[i132 - 1]; + int ici = (nsh + 1) / 2; + if (sconf->idfc == 0) { + for (int ic = 0; ic < ici; ic++) + c2->dc0[ic] = sconf->dc0_matrix[ic][i132 - 1][0]; // WARNING: IDFC=0 is not tested! + } else { // IDFC != 0 + if (jxi488 == 1) { + for (int ic = 0; ic < ici; ic++) { + c2->dc0[ic] = sconf->dc0_matrix[ic][i132 - 1][jxi488 - 1]; + } + } + } + if (nsh % 2 == 0) c2->dc0[ici] = sconf->exdc; + int jer = 0; + int lcalc = 0; + dme( + gconf->l_max, i132, gconf->npnt, gconf->npntts, vkarg, + sconf->exdc, exri, c1, c2, jer, lcalc, arg + ); + if (jer != 0) { + fprintf(output, " STOP IN DME\n"); + fprintf(output, " AT %1d LCALC=%3d TOO SMALL WITH ARG=%15.7lE+i(%15.7lE)\n", jer, lcalc, arg.real(), arg.imag()); + tppoan.close(); + fclose(output); + return; + } + } // i132 + if (sconf->idfc >= 0 and nsph == 1 and jxi488 == gconf->jwtm) { + // This is the condition that writes the transition matrix to output. + int is = 1111; + fstream ttms; + ttms.open("c_TTMS", ios::binary | ios::out); + if (ttms.is_open()) { + ttms.write(reinterpret_cast<char *>(&is), sizeof(int)); + ttms.write(reinterpret_cast<char *>(&(gconf->l_max)), sizeof(int)); + ttms.write(reinterpret_cast<char *>(&vk), sizeof(double)); + ttms.write(reinterpret_cast<char *>(&exri), sizeof(double)); + for (int lmi = 0; lmi < gconf->l_max; lmi++) { + complex<double> element1 = -1.0 / c1->rmi[0][lmi]; + complex<double> element2 = -1.0 / c1->rei[0][lmi]; + ttms.write(reinterpret_cast<char *>(&element1), sizeof(complex<double>)); + ttms.write(reinterpret_cast<char *>(&element2), sizeof(complex<double>)); + } + ttms.write(reinterpret_cast<char *>(&(sconf->radii_of_spheres[0])), sizeof(double)); + ttms.close(); + } else { // Failed to open output file. Should never happen. + printf("ERROR: could not open TTMS file.\n"); + tppoan.close(); + fclose(output); + } + } + // We are at line 271 of SPH.f + double cs0 = 0.25 * vk * vk * vk / half_pi; + sscr0(tfsas, nsph, gconf->l_max, vk, exri, c1); + printf("DEBUG: TFSAS = (%lE,%lE)\n", tfsas.real(), tfsas.imag()); + } //jxi488 + tppoan.close(); + } else { // In case TPPOAN could not be opened. Should never happen. + printf("ERROR: failed to open TPPOAN file.\n"); + } + fclose(output); + } else { // NSPH mismatch between geometry and scatterer configurations. + throw UnrecognizedConfigurationException( + "Inconsistent geometry and scatterer configurations." + ); + } +} -- GitLab