22 std::vector<chi_math::QuadraturePointPhiTheta> new_abscissae;
23 std::vector<double> new_weights;
24 std::vector<chi_mesh::Vector3> new_omegas;
26 const size_t num_dirs =
omegas_.size();
27 double weight_sum = 0.0;
28 for (
size_t d=0; d<num_dirs; ++d)
32 new_weights.emplace_back(
weights_[d]);
33 new_omegas.emplace_back(
omegas_[d]);
37 if (normalization > 0.0)
38 for (
double& w : new_weights)
39 w *= normalization/weight_sum;
43 omegas_ = std::move(new_omegas);
52 m_to_ell_em_map_.clear();
55 for (
int ell=0; ell<=scattering_order; ell++)
56 m_to_ell_em_map_.emplace_back(ell, 0);
57 else if (dimension == 2)
58 for (
int ell=0; ell<=scattering_order; ell++)
59 for (
int m=-ell; m<=ell; m+=2)
60 m_to_ell_em_map_.emplace_back(ell, m);
61 else if (dimension == 3)
62 for (
int ell=0; ell<=scattering_order; ell++)
63 for (
int m=-ell; m<=ell; m++)
64 m_to_ell_em_map_.emplace_back(ell, m);
72 if (d2m_op_built_)
return;
75 MakeHarmonicIndices(scattering_order,dimension);
77 const size_t num_angles = abscissae_.size();
78 const size_t num_moms = m_to_ell_em_map_.size();
80 for (
const auto& ell_em : m_to_ell_em_map_)
82 std::vector<double> cur_mom;
83 cur_mom.reserve(num_angles);
85 for (
int n=0; n<num_angles; n++)
87 const auto& cur_angle = abscissae_[n];
91 double w = weights_[n];
92 cur_mom.push_back(value*w);
95 d2m_op_.push_back(cur_mom);
100 std::stringstream outs;
102 <<
"\nQuadrature d2m operator:\n";
103 for (
int n=0; n<num_angles; n++)
105 outs << std::setw(5) << n;
106 for (
int m=0; m<num_moms; m++)
109 << std::setw(15) << std::left << std::fixed
110 << std::setprecision(10) << d2m_op_[m][n] <<
" ";
123 if (m2d_op_built_)
return;
126 MakeHarmonicIndices(scattering_order,dimension);
128 const size_t num_angles = abscissae_.size();
129 const size_t num_moms = m_to_ell_em_map_.size();
131 const auto normalization =
132 std::accumulate(weights_.begin(), weights_.end(), 0.0);
134 for (
const auto& ell_em : m_to_ell_em_map_)
136 std::vector<double> cur_mom;
137 cur_mom.reserve(num_angles);
139 for (
int n=0; n<num_angles; n++)
141 const auto& cur_angle = abscissae_[n];
142 double value = ((2.0*ell_em.ell+1.0)/normalization)*
146 cur_mom.push_back(value);
149 m2d_op_.push_back(cur_mom);
151 m2d_op_built_ =
true;
154 std::stringstream outs;
157 <<
"\nQuadrature m2d operator:\n";
158 for (
int n=0; n<num_angles; n++)
160 outs << std::setw(5) << n;
161 for (
int m=0; m<num_moms; m++)
164 << std::setw(15) << std::left << std::fixed
165 << std::setprecision(10) << m2d_op_[m][n] <<
" ";
178std::vector<std::vector<double>>
const&
181 const std::string fname = __FUNCTION__;
182 if (not d2m_op_built_)
183 throw std::logic_error(fname +
": Called but D2M operator not yet built. "
184 "Make a call to BuildDiscreteToMomentOperator before using this.");
193std::vector<std::vector<double>>
const&
196 const std::string fname = __FUNCTION__;
197 if (not m2d_op_built_)
198 throw std::logic_error(fname +
": Called but M2D operator not yet built. "
199 "Make a call to BuildMomentToDiscreteOperator before using this.");
206const std::vector<chi_math::AngularQuadrature::HarmonicIndices>&
209 const std::string fname = __FUNCTION__;
210 if (not (d2m_op_built_ or m2d_op_built_))
211 throw std::logic_error(fname +
": Called but map not yet built. "
212 "Make a call to either BuildDiscreteToMomentOperator or"
213 "BuildMomentToDiscreteOperator before using this.");
214 return m_to_ell_em_map_;
221 std::vector<double> &polar,
222 std::vector<double> &in_weights,
bool verbose)
224 size_t Na = azimuthal.size();
225 size_t Np = polar.size();
226 size_t Nw = in_weights.size();
228 if ((Na-Np != 0) or (Na-Nw != 0))
231 <<
"chi_math::AngularQuadrature::InitializeWithCustom: supplied"
232 " vectors need to be of equal length.";
237 std::stringstream ostr;
238 double weight_sum = 0.0;
240 for (
unsigned int i=0; i<Na; i++)
242 const auto abscissa =
245 abscissae_.push_back(abscissa);
247 const double weight = in_weights[i];
248 weights_.push_back(weight);
249 weight_sum += weight;
254 snprintf(buf,200,
"Varphi=%.2f Theta=%.2f Weight=%.3e\n",
255 abscissa.phi*180.0/M_PI,
256 abscissa.theta*180.0/M_PI,
263 for (
const auto& qpoint : abscissae_)
266 new_omega.
x = sin(qpoint.theta)*cos(qpoint.phi);
267 new_omega.
y = sin(qpoint.theta)*sin(qpoint.phi);
268 new_omega.
z = cos(qpoint.theta);
270 omegas_.push_back(new_omega);
276 << ostr.str() <<
"\n"
277 <<
"Weight sum=" << weight_sum;
static void Exit(int error_code)
LogStream Log(LOG_LVL level=LOG_0)
AngularQuadratureCustom(std::vector< double > &azimuthal, std::vector< double > &polar, std::vector< double > &in_weights, bool verbose)
std::vector< std::vector< double > > const & GetMomentToDiscreteOperator() const
const std::vector< HarmonicIndices > & GetMomentToHarmonicsIndexMap() const
std::vector< double > weights_
virtual void MakeHarmonicIndices(unsigned int scattering_order, int dimension)
std::vector< chi_math::QuadraturePointPhiTheta > abscissae_
virtual void OptimizeForPolarSymmetry(double normalization)
std::vector< std::vector< double > > const & GetDiscreteToMomentOperator() const
virtual void BuildDiscreteToMomentOperator(unsigned int scattering_order, int dimension)
virtual void BuildMomentToDiscreteOperator(unsigned int scattering_order, int dimension)
std::vector< chi_mesh::Vector3 > omegas_
double Ylm(unsigned int ell, int m, double varphi, double theta)