/// @brief Makes the inverse relation, mapping codim_to entities /// to their codim_from neighbours. /// /// Implementation note: The algorithm has been changed /// to a three-pass O(n) algorithm. /// @param inv The OrientedEntityTable void makeInverseRelation(OrientedEntityTable<codim_to, codim_from>& inv) const { // Find the maximum index used. This will give (one less than) the size // of the table to be created. int maxind = -1; for (int i = 0; i < size(); ++i) { EntityRep<codim_from> from_ent(i, true); row_type r = operator[](from_ent); for (int j = 0; j < r.size(); ++j) { EntityRep<codim_to> to_ent = r[j]; int ind = to_ent.index(); maxind = std::max(ind, maxind); } } // Build the new_sizes vector and compute datacount. std::vector<int> new_sizes(maxind + 1); int datacount = 0; for (int i = 0; i < size(); ++i) { EntityRep<codim_from> from_ent(i, true); row_type r = operator[](from_ent); datacount += r.size(); for (int j = 0; j < r.size(); ++j) { EntityRep<codim_to> to_ent = r[j]; int ind = to_ent.index(); ++new_sizes[ind]; } } // Compute the cumulative sizes. std::vector<int> cumul_sizes(new_sizes.size() + 1); cumul_sizes[0] = 0; std::partial_sum(new_sizes.begin(), new_sizes.end(), cumul_sizes.begin() + 1); // Using the cumulative sizes array as indices, we populate new_data. // Note that cumul_sizes[ind] is not kept constant, but incremented so that // it always gives the correct index for new data corresponding to index ind. std::vector<int> new_data(datacount); for (int i = 0; i < size(); ++i) { EntityRep<codim_from> from_ent(i, true); row_type r = operator[](from_ent); for (int j = 0; j < r.size(); ++j) { EntityRep<codim_to> to_ent = r[j]; int ind = to_ent.index(); int data_ind = cumul_sizes[ind]; new_data[data_ind] = to_ent.orientation() ? i : ~i; ++cumul_sizes[ind]; } } inv = OrientedEntityTable<codim_to, codim_from>(new_data.begin(), new_data.end(), new_sizes.begin(), new_sizes.end()); }
/** @brief Prints the relation matrix corresponding to the table. Let the entities of codimensions f and t be given by the sets \f$E^f = { e^f_i } \f$ and \f$E^t = { e^t_j }\f$. A relation matrix R is defined by \f{eqnarray*}{ R_{ij} &=& 0 \mbox{ if } e^f_i \mbox{ and } e^t_j \mbox{ are not neighbours }\\ R_{ij} &=& 1 \mbox{ if they are neighbours with same orientation }\\ R_{ij} &=& -1 \mbox{ if they are neighbours with opposite orientation.} \f} @param os The output stream. */ void printRelationMatrix(std::ostream& os) const { int columns = numberOfColumns(); for (int i = 0; i < size(); ++i) { FromType from_ent(i); row_type r = operator[](from_ent); int cur_col = 0; int next_ent = 0; ToType to_ent = r[next_ent]; int next_print = to_ent.index(); while (cur_col < columns) { if (cur_col == next_print) { if (to_ent.orientation()) { os << " 1"; } else { os << " -1"; } ++next_ent; if (next_ent >= r.size()) { next_print = columns; } else { to_ent = r[next_ent]; next_print = to_ent.index(); } } else { os << " 0"; } ++cur_col; } os << '\n'; } }
int numberOfColumns() const { int maxind = 0; for (int i = 0; i < size(); ++i) { FromType from_ent(i); row_type r = operator[](from_ent); for (int j = 0; j < r.size(); ++j) { maxind = std::max(maxind, r[j].index()); } } return maxind + 1; }
int size() const { return left.size() + right.size(); }