series_expansion_aux.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <climits>
00033
00034
00035 #include "series_expansion_aux.h"
00036
00037 const Vector& SeriesExpansionAux::get_inv_multiindex_factorials() const {
00038 return inv_multiindex_factorials_;
00039 }
00040
00041 int SeriesExpansionAux::get_max_total_num_coeffs() const {
00042 return list_total_num_coeffs_[max_order_];
00043 }
00044
00045 const ArrayList < int > *SeriesExpansionAux::get_lower_mapping_index() const {
00046 return lower_mapping_index_.begin();
00047 }
00048
00049 int SeriesExpansionAux::get_max_order() const {
00050 return max_order_;
00051 }
00052
00053 const ArrayList < int > &SeriesExpansionAux::get_multiindex(int pos) const {
00054 return multiindex_mapping_[pos];
00055 }
00056
00057 const ArrayList < int > *SeriesExpansionAux::get_multiindex_mapping() const {
00058 return multiindex_mapping_.begin();
00059 }
00060
00061 const Vector& SeriesExpansionAux::get_neg_inv_multiindex_factorials() const {
00062 return neg_inv_multiindex_factorials_;
00063 }
00064
00065 double SeriesExpansionAux::get_n_choose_k(int n, int k) const {
00066 return n_choose_k_.get(n, (int) math::ClampNonNegative(k));
00067 }
00068
00069 double SeriesExpansionAux::get_n_multichoose_k_by_pos(int n, int k) const {
00070 return multiindex_combination_.get(n, k);
00071 }
00072
00073 int SeriesExpansionAux::get_total_num_coeffs(int order) const {
00074
00075 return list_total_num_coeffs_[order];
00076 }
00077
00078 const ArrayList < int > *SeriesExpansionAux::get_upper_mapping_index() const {
00079 return upper_mapping_index_.begin();
00080 }
00081
00082 int SeriesExpansionAux::ComputeMultiindexPosition
00083 (const ArrayList<int> &multiindex) const {
00084
00085 int dim = multiindex.size();
00086 int mapping_sum = 0;
00087 int index = 0;
00088
00089 for(index_t j = 0; j < dim; j++) {
00090
00091
00092 if(multiindex[j] < 0) {
00093 index = -1;
00094 break;
00095 }
00096
00097 mapping_sum += multiindex[j];
00098 }
00099 if(index >= 0) {
00100 for(index_t j = 0; j < dim; j++) {
00101 index += (int) get_n_choose_k(mapping_sum + dim - j - 1, dim - j);
00102 mapping_sum -= multiindex[j];
00103 }
00104 }
00105
00106 return index;
00107 }
00108
00109 double SeriesExpansionAux::FarFieldEvaluationCost(int order) const {
00110 return pow(dim_, order + 1);
00111 }
00112
00113 double SeriesExpansionAux::FarFieldToLocalTranslationCost(int order) const {
00114 return pow(dim_, 2 * order + 1);
00115 }
00116
00117 double SeriesExpansionAux::DirectLocalAccumulationCost(int order) const {
00118 return pow(dim_, order + 1);
00119 }
00120
00121 void SeriesExpansionAux::Init(int max_order, int dim) {
00122
00123 int p, k, t, tail, i, j;
00124 ArrayList<int> heads;
00125 ArrayList<int> cinds;
00126
00127
00128 dim_ = dim;
00129 max_order_ = max_order;
00130
00131
00132 int limit = 2 * max_order + 1;
00133 list_total_num_coeffs_.Init(limit);
00134 for(p = 0; p < limit; p++) {
00135 list_total_num_coeffs_[p] = (int) math::BinomialCoefficient(p + dim, dim);
00136 }
00137
00138
00139 ComputeFactorials();
00140
00141
00142
00143
00144 inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit - 1]);
00145 neg_inv_multiindex_factorials_.Init(list_total_num_coeffs_[limit - 1]);
00146 multiindex_mapping_.Init(list_total_num_coeffs_[limit - 1]);
00147 (multiindex_mapping_[0]).Init(dim_);
00148 for(j = 0; j < dim; j++) {
00149 (multiindex_mapping_[0])[j] = 0;
00150 }
00151 n_choose_k_.Init((limit - 1) + dim + 1, (limit - 1) + dim + 1);
00152 n_choose_k_.SetZero();
00153
00154
00155 heads.Init(dim + 1);
00156 cinds.Init(list_total_num_coeffs_[limit - 1]);
00157
00158 for(i = 0; i < dim; i++) {
00159 heads[i] = 0;
00160 }
00161 heads[dim] = INT_MAX;
00162 cinds[0] = 0;
00163
00164
00165
00166 inv_multiindex_factorials_[0] = 1.0;
00167 neg_inv_multiindex_factorials_[0] = 1.0;
00168 for(k = 1, t = 1, tail = 1; k <= 2 * max_order_; k++, tail = t) {
00169 for(i = 0; i < dim; i++) {
00170 int head = (int) heads[i];
00171 heads[i] = t;
00172 for(j = head; j < tail; j++, t++) {
00173 cinds[t] = (j < heads[i + 1]) ? cinds[j] + 1 : 1;
00174 inv_multiindex_factorials_[t] =
00175 inv_multiindex_factorials_[j] / cinds[t];
00176 neg_inv_multiindex_factorials_[t] =
00177 -neg_inv_multiindex_factorials_[j] / cinds[t];
00178
00179 (multiindex_mapping_[t]).InitCopy(multiindex_mapping_[j]);
00180 (multiindex_mapping_[t])[i] = (multiindex_mapping_[t])[i] + 1;
00181 }
00182 }
00183 }
00184
00185
00186 for(j = 0; j <= 2 * max_order + dim; j++) {
00187 for(k = 0; k <= 2 * max_order + dim; k++) {
00188 n_choose_k_.set(j, k, math::BinomialCoefficient(j, k));
00189 }
00190 }
00191
00192
00193 ComputeMultiindexCombination();
00194
00195
00196
00197 ComputeLowerMappingIndex();
00198 ComputeUpperMappingIndex();
00199 }
00200
00201 void SeriesExpansionAux::PrintDebug(const char *name, FILE *stream) const {
00202
00203 fprintf(stream, "----- SERIESEXPANSIONAUX %s ------\n", name);
00204 fprintf(stream, "Max order: %d, dimension: %d\n", max_order_, dim_);
00205
00206 fprintf(stream, "Multiindex mapping: ");
00207 for (index_t i = 0; i < multiindex_mapping_.size(); i++) {
00208
00209 DEBUG_ASSERT_MSG(ComputeMultiindexPosition(multiindex_mapping_[i]) == i,
00210 "REIMPLEMENT ComputeMultiindexPosition function!");
00211 fprintf(stream, "( ");
00212 for(index_t j = 0; j < dim_; j++) {
00213 fprintf(stream, "%d ", multiindex_mapping_[i][j]);
00214 }
00215 fprintf(stream, "): %g %g ", inv_multiindex_factorials_[i],
00216 neg_inv_multiindex_factorials_[i]);
00217 }
00218 fprintf(stream, "\n");
00219 }