27 auto polar_quad(quad_polar);
32 const auto eps = std::numeric_limits<double>::epsilon();
34 if (polar_quad.weights_.size() == 0)
35 throw std::invalid_argument(
"chi_math::SphericalAngularQuadrature::Initialize : "
36 "invalid polar quadrature size = "
37 +std::to_string(polar_quad.weights_.size()));
42 const double polar_quad_sum_weights = 2;
43 const auto polar_quad_span = std::pair<double, double>(-1, +1);
46 const auto integral_weights =
47 std::accumulate(polar_quad.weights_.begin(), polar_quad.weights_.end(), 0.0);
48 if (std::abs(integral_weights) > 0)
50 const auto fac = polar_quad_sum_weights / integral_weights;
51 if (std::abs(fac - 1) > eps)
52 for (
auto& w : polar_quad.weights_)
56 throw std::invalid_argument(
"chi_math::SphericalAngularQuadrature::Initialize : "
57 "polar quadrature weights sum to zero.");
60 if (std::abs(polar_quad.GetRange().first - polar_quad_span.first) > eps ||
61 std::abs(polar_quad.GetRange().second- polar_quad_span.second) > eps)
62 polar_quad.SetRange(polar_quad_span);
67 {
return qp0[0] < qp1[0]; };
68 if (!std::is_sorted(polar_quad.qpoints_.begin(), polar_quad.qpoints_.end(), lt_qp))
69 throw std::invalid_argument(
"chi_math::SphericalAngularQuadrature::Initialize : "
70 "polar quadrature abscissae not in ascending order.");
73 if (std::abs(polar_quad.weights_.front()) > eps &&
74 std::abs(polar_quad.qpoints_.front()[0] - polar_quad_span.first) > eps)
76 polar_quad.weights_.emplace(polar_quad.weights_.begin(), 0);
77 polar_quad.qpoints_.emplace(polar_quad.qpoints_.begin(), polar_quad_span.first);
79 if (std::abs(polar_quad.weights_.back()) > eps &&
80 std::abs(polar_quad.qpoints_.back()[0] - polar_quad_span.second) > eps)
82 polar_quad.weights_.emplace(polar_quad.weights_.end(), 0);
83 polar_quad.qpoints_.emplace(polar_quad.qpoints_.end(), polar_quad_span.second);
95 for (
size_t p = 0; p < polar_quad.weights_.size(); ++p)
97 const auto pol_wei = polar_quad.weights_[p];
98 const auto pol_abs = polar_quad.qpoints_[p][0];
99 const auto pol_com = std::sqrt(1 - pol_abs * pol_abs);
101 const auto weight = pol_wei;
105 weights_.emplace_back(weight);
106 abscissae_.emplace_back(abscissa);
107 omegas_.emplace_back(omega);
109 weights_.shrink_to_fit();
110 abscissae_.shrink_to_fit();
111 omegas_.shrink_to_fit();
114 map_directions_.clear();
115 for (
size_t p = 0; p < polar_quad.weights_.size(); ++p)
117 std::vector<unsigned int> vec_directions_p;
118 vec_directions_p.emplace_back(p);
119 map_directions_.emplace(p, vec_directions_p);
125 InitializeParameters();
133 for (
const auto& dir : map_directions_)
135 Chi::log.
Log() <<
"polar level " << dir.first <<
" : ";
136 for (
const auto& q : dir.second)
140 Chi::log.
Log() <<
"curvilinear product quadrature : spherical" << std::endl;
141 for (
size_t k = 0; k < weights_.size(); ++k)
143 <<
"angle index " << k <<
": weight = " << weights_[k]
144 <<
", (phi, theta) = (" << abscissae_[k].phi <<
", " << abscissae_[k].theta <<
")"
145 <<
", omega = " << omegas_[k].PrintStr()
146 <<
", fac_diamond_difference = " << fac_diamond_difference_[k]
147 <<
", fac_streaming_operator = " << fac_streaming_operator_[k]
149 const auto sum_weights =
150 std::accumulate(weights_.begin(), weights_.end(), 0.0);
151 Chi::log.
Log() <<
"sum(weights) = " << sum_weights << std::endl;
159 fac_diamond_difference_.resize(weights_.size(), 1);
160 fac_streaming_operator_.resize(weights_.size(), 0);
163 double alpha_interface = 0;
164 std::vector<double> mu_interface(2, omegas_[map_directions_[0].front()].z);
167 for (
size_t p = 1; p < map_directions_.size() - 1; ++p)
169 const auto k = map_directions_[p][0];
170 const auto w_p = weights_[k];
171 const auto mu_p = omegas_[k].z;
173 alpha_interface -= w_p * mu_p;
175 mu_interface[0] = mu_interface[1];
176 mu_interface[1] += w_p;
178 const auto tau = (mu_p - mu_interface[0]) / (mu_interface[1] - mu_interface[0]);
180 fac_diamond_difference_[k] = tau;
181 fac_streaming_operator_[k] = alpha_interface / (w_p * tau) + mu_p;
182 fac_streaming_operator_[k] *= 2;
190 if (m_to_ell_em_map_.empty())
193 for (
unsigned int l = 0; l <= scattering_order; ++l)
194 m_to_ell_em_map_.emplace_back(l, 0);
196 throw std::invalid_argument(
"chi_math::SphericalAngularQuadrature::MakeHarmonicIndices : "
197 "invalid dimension.");
LogStream Log(LOG_LVL level=LOG_0)
void InitializeParameters()
void Initialize(const chi_math::Quadrature &quad_polar, const bool verbose=false)
SphericalAngularQuadrature(const chi_math::Quadrature &quad_polar, const bool verbose=false)
void MakeHarmonicIndices(unsigned int scattering_order, int dimension) override