diff --git a/src/cluster/cluster.cpp b/src/cluster/cluster.cpp index f3e9141dd5567e96a0155c03099870a1f6d7fcd8..77a149a4234063dad795003cbf874ccd6f9447ff 100644 --- a/src/cluster/cluster.cpp +++ b/src/cluster/cluster.cpp @@ -19,6 +19,7 @@ * \brief Implementation of the calculation for a cluster of spheres. */ #include <chrono> +#include <cmath> #include <cstdio> #include <exception> #include <fstream> @@ -228,6 +229,10 @@ void cluster(const string& config_file, const string& data_file, const string& o int nsph = gconf->number_of_spheres; // Sanity check on number of sphere consistency, should always be verified if (s_nsph == nsph) { + char virtual_line[256]; + sprintf(virtual_line, "%.5g.\n", sconf->get_particle_radius(gconf)); + message = "INFO: particle radius is " + (string)virtual_line; + logger->log(message); ScatteringAngles *p_scattering_angles = new ScatteringAngles(gconf); double wp = sconf->wp; // ClusterOutputInfo : Thread 0 of MPI process 0 allocates the memory to @@ -240,7 +245,7 @@ void cluster(const string& config_file, const string& data_file, const string& o logger->log("INFO: Size of matrices to invert: " + to_string((int64_t)ndit) + " x " + to_string((int64_t)ndit) +".\n"); time_logger->log("INFO: Size of matrices to invert: " + to_string((int64_t)ndit) + " x " + to_string((int64_t)ndit) +".\n"); - str(sconf, cid->c1); + str(sconf->_rcf, cid->c1); thdps(cid->c1->lm, cid->zpv); double exdc = sconf->exdc; double exri = sqrt(exdc); @@ -676,10 +681,14 @@ void cluster(const string& config_file, const string& data_file, const string& o #endif } -int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConfiguration *gconf, ScatteringAngles *sa, ClusterIterationData *cid, ClusterOutputInfo *output, const string& output_path, VirtualBinaryFile *vtppoanp) -{ +int cluster_jxi488_cycle( + int jxi488, ScattererConfiguration *sconf, GeometryConfiguration *gconf, + ScatteringAngles *sa, ClusterIterationData *cid, ClusterOutputInfo *output, + const string& output_path, VirtualBinaryFile *vtppoanp +) { int nxi = sconf->number_of_scales; const dcomplex cc0 = 0.0 + I * 0.0; + const double pi = acos(-1.0); char virtual_line[256]; string message = "INFO: running scale iteration " + to_string(jxi488) + " of " + to_string(nxi) + ".\n"; Logger *logger = new Logger(LOG_DEBG); @@ -689,24 +698,19 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf int jer = 0; int lcalc = 0; int jaw = 1; - int li = gconf->li; - int le = gconf->le; - int lm = 0; - if (le > lm) lm = le; - if (li > lm) lm = li; - int nsph = sconf->number_of_spheres; - np_int mxndm = gconf->mxndm; - int iavm = gconf->iavm; - int inpol = gconf->in_pol; - int npnt = gconf->npnt; - int npntts = gconf->npntts; - int isam = gconf->isam; - int jwtm = gconf->jwtm; - np_int ndit = 2 * nsph * cid->c1->nlim; + bool is_first_scale = (jxi488 == 1); + const int nsph = sconf->number_of_spheres; + const np_int mxndm = gconf->mxndm; + const int iavm = gconf->iavm; + const int inpol = gconf->in_pol; + const int npnt = gconf->npnt; + const int npntts = gconf->npntts; + const int isam = gconf->isam; + const int jwtm = gconf->jwtm; int isq, ibf; int last_configuration; - int num_configs = sconf->configurations; - int ndirs = sa->nkks; + const int num_configs = sconf->configurations; + const int ndirs = sa->nkks; int oindex = -1; int jindex = jxi488 - output->first_xi + 1; @@ -716,7 +720,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf double xi = sconf->get_scale(jxi488 - 1); double exdc = sconf->exdc; double exri = sqrt(exdc); - int idfc = (int)sconf->idfc; + const int idfc = (int)sconf->idfc; double vkarg = 0.0; if (idfc >= 0) { cid->vk = xi * cid->wn; @@ -729,6 +733,49 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf output->vec_vk[jindex - 1] = cid->vk; output->vec_xi[jindex - 1] = xi; } + // Dynamic order check + const int max_li = gconf->li; + const int max_le = gconf->le; + const double alamb = 2.0 * pi / cid->vk; + double size_par_li = 2.0 * pi * sqrt(exdc) * sconf->get_max_radius() / alamb; + int recommended_li = 4 + (int)ceil(size_par_li + 4.05 * pow(size_par_li, 1.0 / 3.0)); + double size_par_le = 2.0 * pi * sqrt(exdc) * sconf->get_particle_radius(gconf) / alamb; + int recommended_le = 1 + (int)ceil(size_par_le + 11.0 * pow(size_par_le, 1.0 / 3.0)); + if (recommended_li != cid->c1->li || recommended_le != cid->c1->le) { + if (recommended_li > cid->c1->li) { + message = "WARNING: internal order " + to_string(cid->c1->li) + " for scale iteration " + + to_string(jxi488) + " too low (recommended order is " + to_string(recommended_li) + + ").\n"; + logger->log(message, LOG_WARN); + } else if (recommended_li < cid->c1->li) { + message = "INFO: lowering internal order from " + to_string(cid->c1->li) + " to " + + to_string(recommended_li) + " for scale iteration " + to_string(jxi488) + ".\n"; + logger->log(message, LOG_INFO); + } + if (recommended_le > cid->c1->le) { + message = "WARNING: external order " + to_string(cid->c1->le) + " for scale iteration " + + to_string(jxi488) + " too low (recommended order is " + to_string(recommended_le) + + ").\n"; + logger->log(message, LOG_WARN); + } else if (recommended_le < cid->c1->le) { + message = "INFO: lowering external order from " + to_string(cid->c1->le) + " to " + + to_string(recommended_le) + " for scale iteration " + to_string(jxi488) + ".\n"; + logger->log(message, LOG_INFO); + } + if (recommended_li < max_li || recommended_le < max_le) { + int new_li = (recommended_li < max_li) ? recommended_li : max_li; + int new_le = (recommended_le < max_le) ? recommended_le : max_le; + cid->update_orders(sconf->_rcf, new_li, new_le); + is_first_scale = true; + jaw = 1; + cid->refinemode = 2; + } + } + int li = cid->c1->li; + int le = cid->c1->le; + int lm = cid->c1->lm; + np_int ndit = 2 * nsph * cid->c1->nlim; + // End of dynamic order check hjv(exri, vkarg, jer, lcalc, cid->arg, cid->c1); if (jer != 0) { output->vec_ier[jindex - 1] = 1; @@ -754,7 +801,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf for (int ic = 0; ic < ici; ic++) cid->c1->dc0[ic] = sconf->get_dielectric_constant(ic, i132 - 1, jxi488 - 1); } else { - if (jxi488 == 1) { + if (is_first_scale) { for (int ic = 0; ic < ici; ic++) cid->c1->dc0[ic] = sconf->get_dielectric_constant(ic, i132 - 1, 0); } @@ -837,6 +884,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf } } #endif + cid->refinemode = 0; #ifdef DEBUG_AM VirtualAsciiFile *outam2 = new VirtualAsciiFile(); string outam2_name = output_path + "/c_AM2_JXI" + to_string(jxi488) + ".txt"; @@ -972,7 +1020,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf double cost = 0.0, sint = 0.0, cosp = 0.0, sinp = 0.0; for (int jph484 = 1; jph484 <= sa->nph; jph484++) { int jw = 0; - if (sa->nk != 1 || jxi488 <= 1) { + if (sa->nk != 1 || is_first_scale) { upvmp(th, ph, 0, cost, sint, cosp, sinp, cid->u, cid->upmp, cid->unmp); if (isam >= 0) { wmamp( @@ -984,7 +1032,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf raba(cid->c1->le, cid->c1->am0m, cid->c1->w, cid->tqce, cid->tqcpe, cid->tqcs, cid->tqcps); jw = 1; } - } else { // label 180, NK == 1 AND JXI488 == 1 + } else { // label 180, NK == 1 AND JXI488 > 1 if (isam >= 0) { // label 182 apc(cid->zpv, cid->c1->le, cid->c1->am0m, cid->c1->w, sqk, cid->gap, cid->gapp); @@ -1015,7 +1063,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf if (phs > 360.0) phs -= 360.0; } // label 188 - bool goto190 = (sa->nks == 1 && (jxi488 > 1 || jth486 > 1 || jph484 > 1)); + bool goto190 = (sa->nks == 1 && (!(is_first_scale) || jth486 > 1 || jph484 > 1)); if (!goto190) { upvmp(ths, phs, icspnv, costs, sints, cosps, sinps, cid->us, cid->upsmp, cid->unsmp); if (isam >= 0) @@ -1025,7 +1073,7 @@ int cluster_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConf ); } // label 190 - if (sa->nkks != 1 || jxi488 <= 1) { + if (sa->nkks != 1 || is_first_scale) { upvsp( cid->u, cid->upmp, cid->unmp, cid->us, cid->upsmp, cid->unsmp, cid->up, cid->un, cid->ups, cid->uns, cid->duk, isq, ibf, cid->scan, cid->cfmp, cid->sfmp, cid->cfsp, cid->sfsp @@ -2062,4 +2110,43 @@ ClusterIterationData::~ClusterIterationData() { delete[] cmullr; delete[] cmul; } + +int ClusterIterationData::update_orders(double **rcf, int inner_order, int outer_order) { + int result = 0; + int old_lm = c1->lm; + np_int old_ndit = 2 * c1->nsph * c1->nlim; + ((ParticleDescriptorCluster *)c1)->update_orders(inner_order, outer_order); + const int ndi = c1->ndi; + const np_int ndit = (np_int)c1->ndit; + for (int zi = 0; zi < old_lm; zi++) { + for (int zj = 0; zj < 3; zj++) { + for (int zk = 0; zk < 2; zk++) { + delete[] zpv[zi][zj][zk]; + } + delete[] zpv[zi][zj]; + } + delete[] zpv[zi]; + } + delete[] zpv; + zpv = new double***[c1->lm]; + for (int zi = 0; zi < c1->lm; 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](); + } + } + } + str(rcf, c1); + thdps(c1->lm, zpv); + delete[] am; + delete[] am_vector; + am_vector = new dcomplex[ndit * ndit](); + am = new dcomplex*[ndit]; + for (int ai = 0; ai < ndit; ai++) { + am[ai] = am_vector + ai * ndit; + } + return result; +} // >>> END OF ClusterIterationData CLASS IMPLEMENTATION <<< diff --git a/src/include/Commons.h b/src/include/Commons.h index 31efcc39feb264b0b62b275076477b9402a5e475..54f062e5d35adc5a808193ed6b1441d23ecac927 100644 --- a/src/include/Commons.h +++ b/src/include/Commons.h @@ -451,6 +451,14 @@ public: * \return descriptor_type: `string` The descriptor type name. */ std::string get_descriptor_type() override { return "cluster descriptor"; } + + /*! \brief Update the field expansion orders. + * + * \param inner_order: `int` The new inner expansion order to be set. + * \param outer_order: `int` The new outer expansion order to be set. + * \return result: `int` An exit code (0 if successful). + */ + int update_orders(int inner_order, int outer_order); }; /*! \brief The data structure describing a particle model for a sphere with inclusions. @@ -493,6 +501,14 @@ public: * \return descriptor_type: `string` The descriptor type name. */ std::string get_descriptor_type() override { return "inclusion descriptor"; } + + /*! \brief Update the field expansion orders. + * + * \param inner_order: `int` The new inner expansion order to be set. + * \param outer_order: `int` The new outer expansion order to be set. + * \return result: `int` An exit code (0 if successful). + */ + int update_orders(int inner_order, int outer_order); }; /*! \brief The data structure describing a spherical particle model. @@ -535,6 +551,13 @@ public: * \return descriptor_type: `string` The descriptor type name. */ std::string get_descriptor_type() override { return "sphere descriptor"; } + + /*! \brief Update the field expansion order. + * + * \param order: `int` The new field expansion order to be set. + * \return result: `int` An exit code (0 if successful). + */ + int update_order(int order); }; /*! \brief A data structure representing the angles to be evaluated in the problem. diff --git a/src/include/Configuration.h b/src/include/Configuration.h index d23aa6ff178ee60c8f251ab9b88a86349b6e1762..4235f56d9d42cb4849380282f66b90871b5bf1cb 100644 --- a/src/include/Configuration.h +++ b/src/include/Configuration.h @@ -288,11 +288,9 @@ protected: dcomplex ***_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]. + //! \brief Vector of layer numbers for every sphere, with size [CONFIGURATIONS]. int *_nshl_vec; //! \brief Vector of scale parameters, with size [N_SCALES]. double *_scale_vec; @@ -383,6 +381,8 @@ public: const int& max_layers = _max_layers; //! \brief Read only view on flag to control whether to add an external layer. const bool& use_external_sphere = _use_external_sphere; + //! \brief Matrix of fractional transition radii with size [CONFIGURATIONS x LAYERS]. + double **_rcf; /*! \brief Build a scatterer configuration structure. * @@ -511,6 +511,12 @@ public: */ int get_iog(int index) { return _iog_vec[index]; } + /*! \brief Get the maximum radius of the sphere components. + * + * \return radius: `double` The radius of the largest sphere. + */ + double get_max_radius(); + /*! \brief Get the number of layers for a given configuration. * * This is a specialized function to get the number of layers in a specific @@ -521,6 +527,13 @@ public: */ int get_nshl(int index) { return _nshl_vec[index]; } + /*! \brief Get the radius of the smallest sphere containing the particle. + * + * \param gc: `GeometryConfiguration *` Pointer to a `GeometryConfiguration` instance. + * \return radius: `double` The radius of the sphere containing the particle. + */ + double get_particle_radius(GeometryConfiguration *gc); + /*! \brief Get the radius of a sphere by its index. * * This is a specialized function to get the radius of a sphere through its diff --git a/src/include/IterationData.h b/src/include/IterationData.h index bf38b033096cfd0329dd53ddf075a2f70f36ec26..4fe1d250ddd847e5a812e0fb1933ec1b367789c2 100644 --- a/src/include/IterationData.h +++ b/src/include/IterationData.h @@ -178,6 +178,15 @@ public: /*! \brief `ClusterIterationData` instance destroyer. */ ~ClusterIterationData(); + + /*! \brief Update field expansion orders. + * + * \param rcf: `double **` Matrix of sphere fractional radii. + * \param inner_order: `int` The new inner expansion order to be set. + * \param outer_order: `int` The new outer expansion order to be set. + * \return result: `int` An exit code (0 if successful). + */ + int update_orders(double** rcf, int inner_order, int outer_order); }; // >>> END OF ClusterIterationData CLASS DEFINITION <<< @@ -345,6 +354,15 @@ public: /*! \brief `InclusionIterationData` instance destroyer. */ ~InclusionIterationData(); + + /*! \brief Update field expansion orders. + * + * \param rcf: `double **` Matrix of sphere fractional radii. + * \param inner_order: `int` The new inner expansion order to be set. + * \param outer_order: `int` The new outer expansion order to be set. + * \return result: `int` An exit code (0 if successful). + */ + int update_orders(double** rcf, int inner_order, int outer_order); }; // >>> END OF InclusionIterationData CLASS DEFINITION <<< // @@ -503,6 +521,13 @@ public: /*! \brief `SphereIterationData` instance destroyer. */ ~SphereIterationData(); + + /*! \brief Update field expansion order. + * + * \param order: `int` The new expansion order to be set. + * \return result: `int` An exit code (0 if successful). + */ + int update_order(int order); }; // >>> END OF SphereIterationData CLASS DEFINITION <<< diff --git a/src/include/clu_subs.h b/src/include/clu_subs.h index 9c5feffe260086c5b8a42fa7608a5bb82585f35a..40c5f0e322702b1a3e3c7801cdaf400fc792e852 100644 --- a/src/include/clu_subs.h +++ b/src/include/clu_subs.h @@ -369,10 +369,10 @@ void scr2( * to radial coordinates, then it calls `sphar()` to calculate the vector of spherical * harmonics of the incident field. * - * \param sconf: `ScattererConfiguration *` Pointer to scatterer configuration object. + * \param rcf: `double **` Matrix of sphere configuration fractional radii. * \param c1: `ParticleDescriptor *` Pointer to a ParticleDescriptor instance. */ -void str(ScattererConfiguration *sconf, ParticleDescriptor *c1); +void str(double **rcf, ParticleDescriptor *c1); /*! \brief Compute radiation torques on particles on a k-vector oriented system. * diff --git a/src/include/inclu_subs.h b/src/include/inclu_subs.h index 64e5a1f3da5d11fc060f709b60ac50d4d2055554..c7af5e26c70594e4a0d9184acf33fffc1de9113e 100644 --- a/src/include/inclu_subs.h +++ b/src/include/inclu_subs.h @@ -75,10 +75,10 @@ void indme( /*! \brief C++ porting of INSTR. * - * \param sconf: `ScattererConfiguration *` Pointer to a ScattererConfiguration instance. + * \param rcf: `double **` Pointer to matrix of fractional radii. * \param c1: `ParticleDescriptor *` Pointer to a ParticleDescriptor instance. */ -void instr(ScattererConfiguration *sconf, ParticleDescriptor *c1); +void instr(double **rcf, ParticleDescriptor *c1); /*! \brief C++ porting of OSPV. * diff --git a/src/inclusion/inclusion.cpp b/src/inclusion/inclusion.cpp index 0b0033c4a20f7609c5fd5e9dc940efdf8f7509df..7d6d4ae38b3403862747b80dc9ac3e310e05d101 100644 --- a/src/inclusion/inclusion.cpp +++ b/src/inclusion/inclusion.cpp @@ -19,6 +19,7 @@ * \brief Implementation of the calculation for a sphere with inclusions. */ #include <chrono> +#include <cmath> #include <cstdio> #include <exception> #include <fstream> @@ -233,12 +234,10 @@ void inclusion(const string& config_file, const string& data_file, const string& // Open empty virtual ascii file for output InclusionOutputInfo *p_output = new InclusionOutputInfo(sconf, gconf, mpidata); InclusionIterationData *cid = new InclusionIterationData(gconf, sconf, mpidata, device_count); - const np_int ndi = cid->c1->nsph * cid->c1->nlim; - const np_int ndit = 2 * ndi; logger->log("INFO: Size of matrices to invert: " + to_string((int64_t)cid->c1->ndm) + " x " + to_string((int64_t)cid->c1->ndm) +".\n"); time_logger->log("INFO: Size of matrices to invert: " + to_string((int64_t)cid->c1->ndm) + " x " + to_string((int64_t)cid->c1->ndm) +".\n"); - instr(sconf, cid->c1); + instr(sconf->_rcf, cid->c1); thdps(cid->c1->lm, cid->zpv); double exdc = sconf->exdc; double exri = sqrt(exdc); @@ -537,6 +536,7 @@ void inclusion(const string& config_file, const string& data_file, const string& time_logger->log(message); fclose(timing_file); delete time_logger; + delete logger; } // end instructions block of MPI process 0 //=============================== @@ -673,8 +673,9 @@ void inclusion(const string& config_file, const string& data_file, const string& } int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryConfiguration *gconf, ScatteringAngles *sa, InclusionIterationData *cid, InclusionOutputInfo *output, const string& output_path, VirtualBinaryFile *vtppoanp) { - const dcomplex cc0 = 0.0 + I * 0.0; int nxi = sconf->number_of_scales; + const dcomplex cc0 = 0.0 + I * 0.0; + const double pi = acos(-1.0); char virtual_line[256]; string message = "INFO: running scale iteration " + to_string(jxi488) + " of " + to_string(nxi) + ".\n"; Logger *logger = new Logger(LOG_DEBG); @@ -684,24 +685,24 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo int jer = 0; int lcalc = 0; int jaw = 1; - int li = cid->c1->li; - int le = cid->c1->le; - int lm = cid->c1->lm; - int nsph = cid->c1->nsph; + bool is_first_scale = (jxi488 == 1); + // int li = cid->c1->li; + // int le = cid->c1->le; + // int lm = cid->c1->lm; + const int nsph = cid->c1->nsph; np_int mxndm = gconf->mxndm; - int iavm = gconf->iavm; - int inpol = gconf->in_pol; - int npnt = cid->c1->npnt; - int npntts = cid->c1->npntts; - int isam = gconf->iavm; - int jwtm = gconf->jwtm; - np_int ndit = cid->c1->ndit; + const int iavm = gconf->iavm; + const int inpol = gconf->in_pol; + const int npnt = cid->c1->npnt; + const int npntts = cid->c1->npntts; + const int isam = gconf->iavm; + const int jwtm = gconf->jwtm; int isq, ibf; int last_configuration; dcomplex ent, entn; double enti; - int num_configs = sconf->configurations; - int ndirs = sa->nkks; + const int num_configs = sconf->configurations; + const int ndirs = sa->nkks; int oindex = -1; int jindex = jxi488 - output->first_xi + 1; @@ -725,6 +726,48 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo output->vec_vk[jindex - 1] = cid->vk; output->vec_xi[jindex - 1] = xi; } + // Dynamic order check + const int max_li = gconf->li; + const int max_le = gconf->le; + const double alamb = 2.0 * pi / cid->vk; + double size_par_li = 2.0 * pi * sqrt(exdc) * sconf->get_max_radius() / alamb; + int recommended_li = 4 + (int)ceil(size_par_li + 4.05 * pow(size_par_li, 1.0 / 3.0)); + double size_par_le = 2.0 * pi * sqrt(exdc) * sconf->get_particle_radius(gconf) / alamb; + int recommended_le = 1 + (int)ceil(size_par_le + 11.0 * pow(size_par_le, 1.0 / 3.0)); + if (recommended_li != cid->c1->li || recommended_le != cid->c1->le) { + if (recommended_li > cid->c1->li) { + message = "WARNING: internal order " + to_string(cid->c1->li) + " for scale iteration " + + to_string(jxi488) + " too low (recommended order is " + to_string(recommended_li) + + ").\n"; + logger->log(message, LOG_WARN); + } else if (recommended_li < cid->c1->li) { + message = "INFO: lowering internal order from " + to_string(cid->c1->li) + " to " + + to_string(recommended_li) + " for scale iteration " + to_string(jxi488) + ".\n"; + logger->log(message, LOG_INFO); + } + if (recommended_le > cid->c1->le) { + message = "WARNING: external order " + to_string(cid->c1->le) + " for scale iteration " + + to_string(jxi488) + " too low (recommended order is " + to_string(recommended_le) + + ").\n"; + logger->log(message, LOG_WARN); + } else if (recommended_le < cid->c1->le) { + message = "INFO: lowering external order from " + to_string(cid->c1->le) + " to " + + to_string(recommended_le) + " for scale iteration " + to_string(jxi488) + ".\n"; + logger->log(message, LOG_INFO); + } + if (recommended_li < max_li || recommended_le < max_le) { + int new_li = (recommended_li < max_li) ? recommended_li : max_li; + int new_le = (recommended_le < max_le) ? recommended_le : max_le; + cid->update_orders(sconf->_rcf, new_li, new_le); + is_first_scale = true; + jaw = 1; + cid->refinemode = 2; + } + } + int li = cid->c1->li; + int le = cid->c1->le; + int lm = cid->c1->lm; + // End of dynamic order check // label 120 double sze = vkarg * cid->extr; last_configuration = 0; @@ -745,7 +788,7 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo cid->c1->dc0[ic] = sconf->get_dielectric_constant(ic, i133 - 1, jxi488 - 1); // goes to 129 } else { // label 127 - if (jxi488 == 1) { + if (is_first_scale) { for (int ic = 0; ic < ici; ic++) { cid->c1->dc0[ic] = sconf->get_dielectric_constant(ic, i133 - 1, 0); } @@ -921,7 +964,7 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo double cost = 0.0, sint = 0.0, cosp = 0.0, sinp = 0.0; for (int jph484 = 1; jph484 <= sa->nph; jph484++) { int jw = 0; - if (sa->nk != 1 || jxi488 <= 1) { + if (sa->nk != 1 || is_first_scale) { upvmp(th, ph, 0, cost, sint, cosp, sinp, cid->u, cid->upmp, cid->unmp); if (isam >= 0) { wmamp( @@ -964,7 +1007,7 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo if (phs > 360.0) phs -= 360.0; } // label 188 - bool goto190 = (sa->nks == 1 && (jxi488 > 1 || jth486 > 1 || jph484 > 1)); + bool goto190 = (sa->nks == 1 && (!(is_first_scale) || jth486 > 1 || jph484 > 1)); if (!goto190) { upvmp(ths, phs, icspnv, costs, sints, cosps, sinps, cid->us, cid->upsmp, cid->unsmp); if (isam >= 0) @@ -974,7 +1017,7 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo ); } // label 190 - if (sa->nkks != 1 || jxi488 <= 1) { + if (sa->nkks != 1 || is_first_scale) { upvsp( cid->u, cid->upmp, cid->unmp, cid->us, cid->upsmp, cid->unsmp, cid->up, cid->un, cid->ups, cid->uns, cid->duk, isq, ibf, cid->scan, cid->cfmp, cid->sfmp, cid->cfsp, cid->sfsp @@ -1390,8 +1433,6 @@ int inclusion_jxi488_cycle(int jxi488, ScattererConfiguration *sconf, GeometryCo // >>> IMPLEMENTATION OF InclusionIterationData CLASS <<< // InclusionIterationData::InclusionIterationData(GeometryConfiguration *gconf, ScattererConfiguration *sconf, const mixMPI *mpidata, const int device_count) { c1 = new ParticleDescriptorInclusion(gconf, sconf); - const int ndi = c1->nsph * c1->nlim; - const np_int ndit = 2 * ndi; gaps = new double[c1->nsph](); tqev = new double[3](); tqsv = new double[3](); @@ -1502,8 +1543,6 @@ InclusionIterationData::InclusionIterationData(GeometryConfiguration *gconf, Sca InclusionIterationData::InclusionIterationData(const InclusionIterationData& rhs) { c1 = new ParticleDescriptorInclusion(reinterpret_cast<ParticleDescriptorInclusion &>(*(rhs.c1))); - const int ndi = c1->nsph * c1->nlim; - const np_int ndit = 2 * ndi; gaps = new double[c1->nsph](); for (int gi = 0; gi < c1->nsph; gi++) gaps[gi] = rhs.gaps[gi]; tqev = new double[3](); @@ -1654,8 +1693,6 @@ InclusionIterationData::InclusionIterationData(const InclusionIterationData& rhs #ifdef MPI_VERSION InclusionIterationData::InclusionIterationData(const mixMPI *mpidata, const int device_count) { c1 = new ParticleDescriptorInclusion(mpidata); - const int ndi = c1->nsph * c1->nlim; - const np_int ndit = 2 * ndi; gaps = new double[c1->nsph](); MPI_Bcast(gaps, c1->nsph, MPI_DOUBLE, 0, MPI_COMM_WORLD); tqev = new double[3](); @@ -1792,8 +1829,6 @@ InclusionIterationData::InclusionIterationData(const mixMPI *mpidata, const int void InclusionIterationData::mpibcast(const mixMPI *mpidata) { c1->mpibcast(mpidata); - const int ndi = c1->nsph * c1->nlim; - const np_int ndit = 2 * ndi; MPI_Bcast(gaps, c1->nsph, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(tqev, 3, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(tqsv, 3, MPI_DOUBLE, 0, MPI_COMM_WORLD); @@ -1927,4 +1962,40 @@ InclusionIterationData::~InclusionIterationData() { delete[] cmullr; delete[] cmul; } + +int InclusionIterationData::update_orders(double **rcf, int inner_order, int outer_order) { + int result = 0; + int old_lm = c1->lm; + ((ParticleDescriptorInclusion *)c1)->update_orders(inner_order, outer_order); + for (int zi = 0; zi < old_lm; zi++) { + for (int zj = 0; zj < 3; zj++) { + for (int zk = 0; zk < 2; zk++) { + delete[] zpv[zi][zj][zk]; + } + delete[] zpv[zi][zj]; + } + delete[] zpv[zi]; + } + delete[] zpv; + zpv = new double***[c1->lm]; + for (int zi = 0; zi < c1->lm; 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](); + } + } + } + instr(rcf, c1); + thdps(c1->lm, zpv); + delete[] am; + delete[] am_vector; + am_vector = new dcomplex[c1->ndm * c1->ndm](); + am = new dcomplex*[c1->ndm]; + for (int ai = 0; ai < c1->ndm; ai++) { + am[ai] = am_vector + ai * c1->ndm; + } + return result; +} // >>> END OF InclusionIterationData CLASS IMPLEMENTATION <<< diff --git a/src/libnptm/Commons.cpp b/src/libnptm/Commons.cpp index 29bf18b637b149e7d3d6b9fa71ae8433c7e135cd..b93abab2ce2fa19c341256ed4a9847901eb99f4c 100644 --- a/src/libnptm/Commons.cpp +++ b/src/libnptm/Commons.cpp @@ -83,10 +83,12 @@ ParticleDescriptor::ParticleDescriptor(GeometryConfiguration *gconf, ScattererCo _ndm = 0; gcs = 0.0; _num_configurations = sconf->configurations; - _num_layers = (sconf->use_external_sphere) ? 1 : 0; + // _num_layers = (sconf->use_external_sphere) ? 1 : 0; + _num_layers = 0; _max_layers = 1; for (int nli = 0; nli < num_configurations; nli++) { int nl = sconf->get_nshl(nli); + if (nli == 0 && sconf->use_external_sphere) nl++; _num_layers += nl; if (nl > _max_layers) _max_layers = nl; } @@ -136,8 +138,6 @@ ParticleDescriptor::ParticleDescriptor(GeometryConfiguration *gconf, ScattererCo _npntts = gconf->npntts; int max_n = (npnt > npntts) ? npnt : npntts; _nhspo = 2 * max_n - 1; - // _nl = sconf->configurations; - // if (_nsph == 1 && _nl == 1) _nl = 5; ris = new dcomplex[_nhspo](); dlri = new dcomplex[_nhspo](); vkt = new dcomplex[_nsph](); @@ -310,7 +310,6 @@ ParticleDescriptor::ParticleDescriptor(const ParticleDescriptor &rhs) { tfsas = 0.0 + I * 0.0; vec_tsas = NULL; tsas = NULL; - gcs = 0.0; scs = 0.0; ecs = 0.0; acs = 0.0; @@ -982,6 +981,91 @@ ParticleDescriptorCluster::ParticleDescriptorCluster(const mixMPI *mpidata) : Pa MPI_Bcast(rac3j, _lmtpo, MPI_DOUBLE, 0, MPI_COMM_WORLD); } #endif // MPI_VERSION + +int ParticleDescriptorCluster::update_orders(int inner_order, int outer_order) { + int result = 0; + bool changed_li = false; + bool changed_le = false; + if (inner_order != _li) { + _li = inner_order; + changed_li = true; + delete[] vec_rmi; + delete[] rmi; + vec_rmi = new dcomplex[_li * _nsph](); + rmi = new dcomplex*[_li]; + delete[] vec_rei; + delete[] rei; + vec_rei = new dcomplex[_li * _nsph](); + rei = new dcomplex*[_li]; + for (int ri = 0; ri < _li; ri++) { + rmi[ri] = vec_rmi + (_nsph * ri); + rei[ri] = vec_rei + (_nsph * ri); + } + _litpo = _li + _li + 1; + _litpos = _litpo * _litpo; + delete[] vh; + vh = new dcomplex[_ncou * _litpo](); + delete[] vyhj; + vyhj = new dcomplex[_ncou * _litpos](); + _nlim = _li * (_li + 2); + _ndi = _nsph * _nlim; + _ndit = 2 * _nsph * _nlim; + } + if (outer_order != _le) { + _le = outer_order; + changed_le = true; + _nlem = _le * (_le + 2); + _nlemt = 2 * _nlem; + delete[] vec_am0m; + vec_am0m = new dcomplex[_nlemt * _nlemt](); + delete[] am0m; + am0m = new dcomplex*[_nlemt]; + for (int ai = 0; ai < _nlemt; ai++) am0m[ai] = vec_am0m + (ai * _nlemt); + delete[] vec_w; + delete[] w; + vec_w = new dcomplex[_nlemt * 4](); + w = new dcomplex*[nlemt]; + for (int wi = 0; wi < nlemt; wi++) w[wi] = vec_w + (4 * wi); + } + if (changed_li || changed_le) { + _lm = (_li > _le) ? _li : _le; + _lmpo = _lm + 1; + _lmtpo = _li + _le + 1; + _lmtpos = _lmtpo * _lmtpo; + _nv3j = (_lm * (_lm + 1) * (2 * _lm + 7)) / 6; + delete[] vec_ind3j; + vec_ind3j = new int[(_lm + 1) * _lm](); + delete[] ind3j; + ind3j = new int*[_lm + 1]; + for (int ii = 0; ii <= _lm; ii++) ind3j[ii] = vec_ind3j + (_lm * ii); + delete[] vj0; + vj0 = new dcomplex[_nsph * _lmtpo](); + delete[] vyj0; + vyj0 = new dcomplex[_nsph * _lmtpos](); + delete[] v3j0; + v3j0 = new double[_nv3j](); + delete[] rac3j; + rac3j = new double[_lmtpo](); + delete[] vec_gis; + vec_gis = new dcomplex[_ndi * _nlem](); + delete[] gis; + gis = new dcomplex*[_ndi]; + delete[] vec_gls; + vec_gls = new dcomplex[_ndi * _nlem](); + delete[] gls; + gls = new dcomplex*[_ndi]; + for (int gi = 0; gi < _ndi; gi++) { + gis[gi] = vec_gis + (gi * _nlem); + gls[gi] = vec_gls + (gi * _nlem); + } + delete[] vec_sam; + vec_sam = new dcomplex[_ndit * _nlemt](); + delete[] sam; + sam = new dcomplex*[_ndit]; + for (int si = 0; si < _ndit; si++) sam[si] = vec_sam + (si * _nlemt); + } + return result; +} // >>> End of ParticleDescriptorCluster class implementation. <<< // // >>> ParticleDescriptorInclusion class implementation. <<< // @@ -1066,6 +1150,8 @@ ParticleDescriptorInclusion::ParticleDescriptorInclusion(const ParticleDescripto vec_ind3j = new int[(_lm + 1) * _lm]; np_int vec_ind3j_size = (_lm + 1) * _lm; for (np_int ii = 0; ii < vec_ind3j_size; ii++) vec_ind3j[ii] = rhs.vec_ind3j[ii]; + ind3j = new int*[_lm + 1]; + for (int ii = 0; ii <= _lm; ii++) ind3j[ii] = vec_ind3j + (_lm * ii); vh = new dcomplex[_ncou * _litpo]; for (int hi = 0; hi < _ncou * _litpo; hi++) vh[hi] = rhs.vh[hi]; @@ -1106,9 +1192,7 @@ ParticleDescriptorInclusion::ParticleDescriptorInclusion(const ParticleDescripto ecscm[ci] = rhs.ecscm[ci]; } v3j0 = new double[_nv3j]; - for (int vj = 0; vj < _nv3j; vj++) v3j0[vj] = rhs.v3j0[_nv3j]; - ind3j = new int*[_lm + 1]; - for (int ii = 0; ii <= _lm; ii++) ind3j[ii] = vec_ind3j + (_lm * ii); + for (int vj = 0; vj < _nv3j; vj++) v3j0[vj] = rhs.v3j0[vj]; rac3j = new double[_lmtpo]; for (int ri = 0; ri < _lmtpo; ri++) rac3j[ri] = rhs.rac3j[ri]; // >>> NEEDED BY INCLU <<< // @@ -1217,6 +1301,96 @@ ParticleDescriptorInclusion::ParticleDescriptorInclusion(const mixMPI *mpidata) for (int ai = 0; ai < _nlemt; ai++) at[ai] = vec_at + (ai * _ndm); } #endif // MPI_VERSION + +int ParticleDescriptorInclusion::update_orders(int inner_order, int outer_order) { + int result = 0; + bool changed_li = false; + bool changed_le = false; + if (inner_order != _li) { + _li = inner_order; + changed_li = true; + _nlim = _li * (_li + 2); + _litpo = _li + _li + 1; + _litpos = _litpo * _litpo; + _ndi = _nsph * _nlim; + _ndit = 2 * _nsph * _nlim; + delete[] rmi; + delete[] vec_rmi; + delete[] rei; + delete[] vec_rei; + vec_rmi = new dcomplex[_li * _nsph](); + rmi = new dcomplex*[_li]; + vec_rei = new dcomplex[_li * _nsph](); + rei = new dcomplex*[_li]; + for (int ri = 0; ri < _li; ri++) { + rmi[ri] = vec_rmi + (_nsph * ri); + rei[ri] = vec_rei + (_nsph * ri); + } + delete[] vh; + vh = new dcomplex[_ncou * _litpo](); + delete[] vyhj; + vyhj = new dcomplex[_ncou * _litpos](); + } + if (outer_order != le) { + _le = outer_order; + changed_le = true; + _nlem = _le * (_le + 2); + _nlemt = 2 * _nlem; + delete[] w; + delete[] vec_w; + vec_w = new dcomplex[_nlemt * 4](); + w = new dcomplex*[_nlemt]; + for (int wi = 0; wi < _nlemt; wi++) w[wi] = vec_w + (4 * wi); + delete[] am0m; + delete[] vec_am0m; + vec_am0m = new dcomplex[_nlemt * _nlemt](); + am0m = new dcomplex*[_nlemt]; + for (int ai = 0; ai < _nlemt; ai++) am0m[ai] = vec_am0m + (ai * _nlemt); + delete[] rm0; + rm0 = new dcomplex[_le](); + delete[] re0; + re0 = new dcomplex[_le](); + delete[] rmw; + rmw = new dcomplex[_le](); + delete[] rew; + rew = new dcomplex[_le](); + delete[] tm; + tm = new dcomplex[_le](); + delete[] te; + te = new dcomplex[_le](); + delete[] tm0; + tm0 = new dcomplex[_le](); + delete[] te0; + te0 = new dcomplex[_le](); + } + if (changed_li || changed_le) { + _lm = (_li > _le) ? _li : _le; + _lmpo = _lm + 1; + _lmtpo = _li + _le + 1; + _lmtpos = _lmtpo * _lmtpo; + _nv3j = (_lm * (_lm + 1) * (2 * _lm + 7)) / 6; + _ndm = 2 * (_nsph * _nlim + _nlem); + delete[] ind3j; + delete[] vec_ind3j; + vec_ind3j = new int[(_lm + 1) * _lm](); + ind3j = new int*[_lm + 1]; + for (int ii = 0; ii <= _lm; ii++) ind3j[ii] = vec_ind3j + (_lm * ii); + delete[] vj0; + vj0 = new dcomplex[_nsph * _lmtpo](); + delete[] vyj0; + vyj0 = new dcomplex[_nsph * _lmtpos](); + delete[] v3j0; + v3j0 = new double[_nv3j](); + delete[] rac3j; + rac3j = new double[_lmtpo](); + delete[] at; + delete[] vec_at; + vec_at = new dcomplex[_nlemt * _ndm](); + at = new dcomplex*[_nlemt]; + for (int ai = 0; ai < _nlemt; ai++) at[ai] = vec_at + (ai * _ndm); + } + return result; +} // >>> End of ParticleDescriptorInclusion class implementation. <<< // // >>> ParticleDescriptorSphere class implementation. <<< // @@ -1312,6 +1486,33 @@ ParticleDescriptorSphere::ParticleDescriptorSphere(const mixMPI *mpidata) : Part } } #endif // MPI_VERSION + +int ParticleDescriptorSphere::update_order(int order) { + int result = 0; + if (order != _lm) { + _lm = order; + _li = order; + delete[] rmi; + delete[] vec_rmi; + delete[] rei; + delete[] vec_rei; + vec_rmi = new dcomplex[_li * _nsph](); + rmi = new dcomplex*[_li]; + vec_rei = new dcomplex[_li * _nsph](); + rei = new dcomplex*[_li]; + for (int ri = 0; ri < _li; ri++) { + rmi[ri] = vec_rmi + (_nsph * ri); + rei[ri] = vec_rei + (_nsph * ri); + } + int nlmmt = 2 * _nsph * _li * (_li + 2); + delete[] w; + delete[] vec_w; + vec_w = new dcomplex[nlmmt * 4](); + w = new dcomplex*[nlmmt]; + for (int wi = 0; wi < nlmmt; wi++) w[wi] = vec_w + (4 * wi); + } + return result; +} // >>> End of ParticleDescriptorSphere class implementation. <<< // // >>> ScatteringAngles class implementation. <<< // diff --git a/src/libnptm/Configuration.cpp b/src/libnptm/Configuration.cpp index 68e076630b26c5eb8bb91b2a1dcd5d8b392392d5..2aa61343aaf91e99294d2d786c72ddae2f290c5b 100644 --- a/src/libnptm/Configuration.cpp +++ b/src/libnptm/Configuration.cpp @@ -971,6 +971,40 @@ ScattererConfiguration* ScattererConfiguration::from_legacy(const std::string& f return conf; } +double ScattererConfiguration::get_max_radius() { + double result = 0.0; + for (int ci = 0; ci < _configurations; ci++) { + if (_radii_of_spheres[ci] > result) + result = _radii_of_spheres[ci]; + } + return result; +} + +double ScattererConfiguration::get_particle_radius(GeometryConfiguration *gc) { + double result = 0.0; + if (_use_external_sphere) { + result = _radii_of_spheres[0] * _rcf[0][_nshl_vec[0] - 1]; + } else { + double x, y, z; + int far_index = -1; + double dist2, max_dist; + double max_dist2 = 0.0; + for (int si = 0; si < _number_of_spheres; si++) { + x = gc->get_sph_x(si); + y = gc->get_sph_y(si); + z = gc->get_sph_z(si); + dist2 = x * x + y * y + z * z; + if (dist2 > max_dist2) { + max_dist2 = dist2; + far_index = si; + } + } + max_dist = sqrt(max_dist2); + result = max_dist + _radii_of_spheres[far_index]; + } + return result; +} + void ScattererConfiguration::print() { int ies = (_use_external_sphere)? 1 : 0; printf("### CONFIGURATION DATA ###\n"); diff --git a/src/libnptm/clu_subs.cpp b/src/libnptm/clu_subs.cpp index 0199f31a96dd9d759be40f90c07d70cef76c7e0b..3548af3d656cff48a18fddafafb2e61a04542852 100644 --- a/src/libnptm/clu_subs.cpp +++ b/src/libnptm/clu_subs.cpp @@ -2442,7 +2442,7 @@ void scr2( #endif } -void str(ScattererConfiguration *sconf, ParticleDescriptor *c1) { +void str(double **rcf, ParticleDescriptor *c1) { dcomplex *ylm; const double pi = acos(-1.0); int last_configuration; @@ -2457,7 +2457,7 @@ void str(ScattererConfiguration *sconf, ParticleDescriptor *c1) { c1->gcsv[i18 - 1] = gcss; int nsh = c1->nshl[last_configuration - 1]; for (int j16 = 1; j16 <= nsh; j16++) { - c1->rc[last_configuration - 1][j16 - 1] = sconf->get_rcf(last_configuration - 1, j16 - 1) * c1->ros[last_configuration - 1]; + c1->rc[last_configuration - 1][j16 - 1] = rcf[last_configuration - 1][j16 - 1] * c1->ros[last_configuration - 1]; } // j16 loop } c1->gcs += gcss; diff --git a/src/libnptm/inclu_subs.cpp b/src/libnptm/inclu_subs.cpp index e2eede6927f1701ca34656ba8cd1a6051baeecdc..12859ab2a1953eb2387fa5d3c9eb804fbb8c4f0b 100644 --- a/src/libnptm/inclu_subs.cpp +++ b/src/libnptm/inclu_subs.cpp @@ -493,7 +493,7 @@ void indme( delete[] dref; } -void instr(ScattererConfiguration *sconf, ParticleDescriptor *c1) { +void instr(double **rcf, ParticleDescriptor *c1) { const int ylm_size = (c1->litpos > c1->lmtpos) ? c1->litpos : c1->lmtpos; dcomplex *ylm = new dcomplex[ylm_size](); double rx, ry, rz, rr, crth, srth, crph, srph; @@ -503,7 +503,7 @@ void instr(ScattererConfiguration *sconf, ParticleDescriptor *c1) { if (c1->iog[i18] >= i) { int nsh = c1->nshl[i18]; for (int j = 0; j < nsh; j++) - c1->rc[i18][j] = sconf->get_rcf(i18, j) * c1->ros[i18]; + c1->rc[i18][j] = rcf[i18][j] * c1->ros[i18]; } } // i18 loop int i = 0; diff --git a/src/libnptm/outputs.cpp b/src/libnptm/outputs.cpp index 48791dc9a947ef24f9183d974b5855d7ebe24602..8c4ecf7df21e3ed3d04320eeac8ec58666d2c510 100644 --- a/src/libnptm/outputs.cpp +++ b/src/libnptm/outputs.cpp @@ -4281,22 +4281,22 @@ int InclusionOutputInfo::write_legacy(const std::string &output) { if (isam >= 0) { fprintf( p_outfile, " UNI=(%12.5lE,%12.5lE,%12.5lE)\n", - vec_dir_un[done_dirs], - vec_dir_un[done_dirs + 1], - vec_dir_un[done_dirs + 2] + vec_dir_un[3 * done_dirs], + vec_dir_un[3 * done_dirs + 1], + vec_dir_un[3 * done_dirs + 2] ); fprintf( p_outfile, " UNS=(%12.5lE,%12.5lE,%12.5lE)\n", - vec_dir_uns[done_dirs], - vec_dir_uns[done_dirs + 1], - vec_dir_uns[done_dirs + 2] + vec_dir_uns[3 * done_dirs], + vec_dir_uns[3 * done_dirs + 1], + vec_dir_uns[3 * done_dirs + 2] ); } else { // label 214 fprintf( p_outfile, " UN=(%12.5lE,%12.5lE,%12.5lE)\n\n", - vec_dir_un[done_dirs], - vec_dir_un[done_dirs + 1], - vec_dir_un[done_dirs + 2] + vec_dir_un[3 * done_dirs], + vec_dir_un[3 * done_dirs + 1], + vec_dir_un[3 * done_dirs + 2] ); } fprintf(p_outfile, " SINGLE SCATTERER\n"); @@ -5644,7 +5644,7 @@ int SphereOutputInfo::write_legacy(const std::string &file_name) { int done_dirs = 0; fprintf(p_outfile, "========== JXI =%3d ====================\n", jxi + 1); if (idfc >= 0) { - fprintf(p_outfile, " VK=%15.7lE, XI=%15.7lE\n", vec_xi[jxi], vec_vk[jxi]); + fprintf(p_outfile, " VK=%15.7lE, XI=%15.7lE\n", vec_vk[jxi], vec_xi[jxi]); } else { // IDFC < 0 fprintf(p_outfile, " XI=%15.7lE\n", vec_xi[jxi]); } diff --git a/src/sphere/sphere.cpp b/src/sphere/sphere.cpp index 288c259f4aee6b48efe3b6980af1e87f01e6dbd8..d123b0ff3927e89da061c1c946190575d19afa9c 100644 --- a/src/sphere/sphere.cpp +++ b/src/sphere/sphere.cpp @@ -542,11 +542,13 @@ int sphere_jxi488_cycle( const double pi = 2.0 * half_pi; int jer = 0; Logger *logger = new Logger(LOG_INFO); + string message = "INIT"; int oindex = 0; int jxi = jxi488 + 1; int jxindex = jxi - oi->first_xi; + bool is_first_scale = (jxi == 1); int nsph = gconf->number_of_spheres; - int l_max = gconf->l_max; + //int l_max = gconf->l_max; int in_pol = gconf->in_pol; int npnt = gconf->npnt; int npntts = gconf->npntts; @@ -576,6 +578,30 @@ int sphere_jxi488_cycle( oi->vec_vk[jxindex] = vk; oi->vec_xi[jxindex] = xi; } + // Dynamic order check + const int max_lm = gconf->l_max; + int l_max = gconf->l_max; + const double alamb = 2.0 * pi / vk; + double size_par_lm = 2.0 * pi * sqrt(exdc) * sconf->get_max_radius() / alamb; + int recommended_lm = 4 + (int)ceil(size_par_lm + 4.05 * pow(size_par_lm, 1.0 / 3.0)); + if (recommended_lm != l_max) { + if (recommended_lm > max_lm) { + message = "WARNING: internal order " + to_string(max_lm) + " for scale iteration " + + to_string(jxi488) + " too low (recommended order is " + to_string(recommended_lm) + + ").\n"; + logger->log(message, LOG_WARN); + } else if (recommended_lm < max_lm) { + int new_lm = recommended_lm; + message = "INFO: lowering internal order from " + to_string(max_lm) + " to " + + to_string(recommended_lm) + " for scale iteration " + to_string(jxi488) + ".\n"; + logger->log(message, LOG_INFO); + sid->update_order(new_lm); + is_first_scale = true; + // jw = 1; + l_max = new_lm; + } + } + // End of dynamic order check vtppoanp->append_line(VirtualBinaryLine(vk)); double thsca = (gconf->isam > 1) ? sa->ths - sa->th : 0.0; for (int i132 = 0; i132 < nsph; i132++) { @@ -595,7 +621,7 @@ int sphere_jxi488_cycle( for (int ic = 0; ic < ici; ic++) sid->c1->dc0[ic] = sconf->get_dielectric_constant(ic, i132, jxi488); // WARNING: IDFC=0 is not tested! } else { // IDFC != 0 - if (jxi == 1) { + if (is_first_scale) { for (int ic = 0; ic < ici; ic++) { sid->c1->dc0[ic] = sconf->get_dielectric_constant(ic, i132, jxi488); } @@ -718,7 +744,7 @@ int sphere_jxi488_cycle( double ph = sa->ph; for (int jph484 = 0; jph484 < sa->nph; jph484++) { int jph = jph484 + 1; - bool goto182 = (sa->nk == 1) && (jxi > 1); + bool goto182 = (sa->nk == 1) && (!is_first_scale); if (!goto182) { upvmp(th, ph, 0, sid->cost, sid->sint, sid->cosp, sid->sinp, sid->u, sid->upmp, sid->unmp); } @@ -753,14 +779,14 @@ int sphere_jxi488_cycle( phs = ph + phsph; if (phs >= 360.0) phs -= 360.0; } - bool goto190 = (nks == 1) && ((jxi > 1) || (jth > 1) || (jph > 1)); + bool goto190 = (nks == 1) && ((!is_first_scale) || (jth > 1) || (jph > 1)); if (!goto190) { upvmp(ths, phs, icspnv, sid->costs, sid->sints, sid->cosps, sid->sinps, sid->us, sid->upsmp, sid->unsmp); if (gconf->isam >= 0) { wmamp(2, sid->costs, sid->sints, sid->cosps, sid->sinps, in_pol, l_max, 0, nsph, sid->args, sid->us, sid->upsmp, sid->unsmp, sid->c1); } } - if (nkks != 0 || jxi == 1) { + if (nkks != 0 || is_first_scale) { upvsp( sid->u, sid->upmp, sid->unmp, sid->us, sid->upsmp, sid->unsmp, sid->up, sid->un, sid->ups, sid->uns, sid->duk, isq, ibf, @@ -1247,4 +1273,34 @@ int SphereIterationData::mpibcast(const mixMPI *mpidata) { return 0; } #endif // MPI_VERSION + +int SphereIterationData::update_order(int order) { + int result = 0; + int old_lm = _lm; + if (order != _lm) { + _lm = order; + ((ParticleDescriptorSphere *)c1)->update_order(order); + for (int zi = 0; zi < old_lm; zi++) { + for (int zj = 0; zj < 3; zj++) { + delete[] zpv[zi][zj]; + } + delete[] zpv[zi]; + } + delete[] zpv; + delete[] vec_zpv; + vec_zpv = new double[_lm * 12](); + zpv = new double***[_lm]; + for (int zi = 0; zi < _lm; zi++) { + zpv[zi] = new double**[3]; + for (int zj = 0; zj < 3; zj++) { + int vec_index = 12 * zi + 4 * zj; + zpv[zi][zj] = new double*[2]; + zpv[zi][zj][0] = (vec_zpv + vec_index); + zpv[zi][zj][1] = (vec_zpv + vec_index + 2); + } + } + thdps(_lm, zpv); + } + return result; +} // >>> END OF SphereIterationData CLASS IMPLEMENTATION <<<