Medusa  1.1
Coordinate Free Mehless Method implementation
ImplicitOperators_fwd.hpp
Go to the documentation of this file.
1 #ifndef MEDUSA_BITS_OPERATORS_IMPLICITOPERATORS_FWD_HPP_
2 #define MEDUSA_BITS_OPERATORS_IMPLICITOPERATORS_FWD_HPP_
3 
11 #include <medusa/Config.hpp>
14 
15 namespace mm {
16 
39 template <class shape_storage_type, class matrix_type, class rhs_type>
41  public:
42  typedef shape_storage_type shape_storage_t;
43  typedef matrix_type matrix_t;
44  typedef rhs_type rhs_t;
45  typedef typename shape_storage_t::vector_t vector_t;
46  typedef typename matrix_t::Scalar scalar_t;
51 
52  private:
57  int row_offset;
58  int col_offset;
59 
64  void addToM(int i, int j, scalar_t v);
69  void addToRhs(int i, scalar_t v);
70 
71  template <typename derived_t> class OpBase; // Forward declaration needed.
72 
79  class RowOp {
80  friend class ImplicitOperators;
81  protected:
83  int row_;
84  RowOp(ImplicitOperators& op, int row) : op(op), row_(row) {}
87  int row() const { return op.row_offset + row_; }
88  public:
95  RowOp operator+(const RowOp& other) const {
96  assert_msg(row() == other.row(),
97  "Cannot add together terms for different matrix rows %d and %d.",
98  row(), other.row());
99  return *this;
100  }
102  template <typename derived_t>
103  RowOp operator+(const OpBase<derived_t>& right) { return *this + right.eval(); }
104 
107  op.addToRhs(row_, value);
108  }
109  };
110 
118  template <typename derived_t>
119  class OpBase {
120  protected:
122  int node;
123  int row;
124  OpBase(ImplicitOperators& op, int node, int row)
126  : op(op), node(node), row(row) {}
127  public:
133  RowOp eval(scalar_t alpha) const {
134  return static_cast<const derived_t &>(*this).eval(alpha);
135  }
137  RowOp eval() const { return eval(1.0); }
139  void operator=(scalar_t x) { eval() = x; }
141  RowOp operator*(scalar_t alpha) { return eval(alpha); }
143  RowOp operator+(RowOp right) { return eval() + right; }
145  RowOp operator-() { return eval(-1.0); }
147  template <typename other_derived_t>
148  RowOp operator+(const OpBase<other_derived_t>& right) { return eval() + right.eval(); }
150  friend RowOp operator*(scalar_t alpha, const OpBase& o) { return o.eval(alpha); }
151  };
152 
154 #define USE_BASE(Name) \
155  private: \
156  using OpBase<Name>::op; \
157  using OpBase<Name>::node; \
158  using OpBase<Name>::row; \
159  using OpBase<Name>::OpBase; \
160  friend class ImplicitOperators; \
161  public: \
162  using OpBase<Name>::eval; \
163  using OpBase<Name>::operator=;
164 
166  class ValueOp : public OpBase<ValueOp> {
169  RowOp eval(scalar_t alpha) const {
170  op.addToM(row, node, alpha);
171  return RowOp(op, row);
172  }
173  };
175  template <typename op_family_t>
176  class BasicOp : public OpBase<BasicOp<op_family_t>> {
178  private:
179  typename op_family_t::operator_t o;
180  public:
182  BasicOp(ImplicitOperators& op, int node, int row, typename op_family_t::operator_t o) :
183  OpBase<BasicOp<op_family_t>>(op, node, row), o(o) {}
185  RowOp eval(scalar_t alpha) const {
186  // There is some room for minor optimization here: the index does not need to be
187  // computed for 1-element families. A special Op could be added for that,
188  // but is probably not worth the code complexity.
189  int idx = op_family_t::index(o);
190  for (int i = 0; i < op.ss->supportSize(node); ++i) {
191  op.addToM(row, op.ss->support(node, i), alpha *
192  op.ss->template get<op_family_t>(idx, node, i));
193  }
194  return RowOp(op, row);
195  }
196  };
202  class GradOp : public OpBase<GradOp> {
205 
208  OpBase<GradOp>(op, node, row), vec(vec) {}
209  public:
211  RowOp eval(scalar_t alpha) const {
212  for (int i = 0; i < op.ss->supportSize(node); ++i) {
213  scalar_t value = 0;
214  for (int var = 0; var < op.dim; ++var) {
215  value += vec[var] * op.ss->d1(var, node, i);
216  }
217  op.addToM(row, op.ss->support(node, i), alpha * value);
218  }
219  return RowOp(op, row);
220  }
221  };
222 
223  public:
225  ImplicitOperators() : ss(nullptr), M(nullptr), rhs(nullptr), row_offset(0), col_offset(0) {}
227  explicit ImplicitOperators(const shape_storage_t& ss) : ss(&ss), M(nullptr), rhs(nullptr),
228  row_offset(0), col_offset(0) {}
245  int row_offset = 0, int col_offset = 0);
246 
248  void setProblem(matrix_t& M, rhs_t& rhs, int row_offset = 0, int col_offset = 0) {
253  }
256  assert_msg(0 <= row_offset, "Row offset cannot be negative, got %d.", row_offset);
258  }
261  assert_msg(0 <= col_offset, "Col offset cannot be negative, got %d.", col_offset);
263  }
264 
266  bool hasShapes() const { return ss != nullptr; }
268  bool hasMatrix() const { return M != nullptr; }
270  bool hasRhs() const { return rhs != nullptr; }
271 
287  ValueOp value(int node, int row) { return ValueOp(*this, node, row); }
289  ValueOp value(int node) { return value(node, node); }
290 
309  BasicOp<Lap<dim>> lap(int node, int row) { return BasicOp<Lap<dim>>(*this, node, row, {}); }
311  BasicOp<Lap<dim>> lap(int node) { return lap(node, node); }
312 
335  GradOp grad(int node, const vector_t& v, int row) { return GradOp(*this, node, row, v); }
337  GradOp grad(int node, const vector_t& v) { return grad(node, v, node); }
338 
355  GradOp neumann(int node, const vector_t& unit_normal, int row) {
356  assert_msg(std::abs(unit_normal.norm() - 1.0) < 1e-13,
357  "Normal %s is not of unit length, got %.16f.", unit_normal, unit_normal.norm());
358  return grad(node, unit_normal, row);
359  }
361  GradOp neumann(int node, const vector_t& n) { return neumann(node, n, node); }
362 
382  BasicOp<Der1s<dim>> der1(int node, int var, int row) {
383  return BasicOp<Der1s<dim>>(*this, node, row, {var});
384  }
386  BasicOp<Der1s<dim>> der1(int node, int var) { return der1(node, var, node); }
387 
409  BasicOp<Der2s<dim>> der2(int node, int varmin, int varmax, int row) {
410  return BasicOp<Der2s<dim>>(*this, node, row, {varmin, varmax});
411  }
413  BasicOp<Der2s<dim>> der2(int node, int varmin, int varmax) {
414  return der2(node, varmin, varmax, node);
415  }
416 
417 
426  template <typename op_family_t>
427  BasicOp<op_family_t> apply(int node, typename op_family_t::operator_t o, int row) {
428  return BasicOp<op_family_t>(*this, node, row, o);
429  }
430 
432  template <typename op_family_t>
433  BasicOp<op_family_t> apply(int node, typename op_family_t::operator_t o) {
434  return apply<op_family_t>(node, o, node);
435  }
436 
438  template <typename op_family_t>
439  BasicOp<op_family_t> apply(int node) { return apply<op_family_t>(node, {}, node); }
440 
441 
443  template <typename S, typename M, typename R>
444  friend std::ostream& operator<<(std::ostream& os, const ImplicitOperators<S, M, R>& op);
445 };
446 
447 } // namespace mm
448 
449 #endif // MEDUSA_BITS_OPERATORS_IMPLICITOPERATORS_FWD_HPP_
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
mm::ImplicitOperators::rhs_t
rhs_type rhs_t
Right hand side type.
Definition: ImplicitOperators_fwd.hpp:44
mm::ImplicitOperators::RowOp::row
int row() const
Return absolute index of this row operation.
Definition: ImplicitOperators_fwd.hpp:87
mm::ImplicitOperators::grad
GradOp grad(int node, const vector_t &v)
Same as grad with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:337
mm::ImplicitOperators::GradOp
Class representing the directional derivative (gradient) operation.
Definition: ImplicitOperators_fwd.hpp:202
mm::ImplicitOperators::ss
const shape_storage_t * ss
Shape storage, but name is shortened for readability.
Definition: ImplicitOperators_fwd.hpp:54
mm::ImplicitOperators::RowOp::row_
int row_
Index of the row to which this operation refers.
Definition: ImplicitOperators_fwd.hpp:83
mm::ImplicitOperators::OpBase::eval
RowOp eval() const
Eval with alpha = 1.0.
Definition: ImplicitOperators_fwd.hpp:137
mm::ImplicitOperators::OpBase
Base class for all elementary implicit operations.
Definition: ImplicitOperators_fwd.hpp:71
mm::ImplicitOperators::addToRhs
void addToRhs(int i, scalar_t v)
Adds v to rhs[i].
Definition: ImplicitOperators.hpp:54
mm::ImplicitOperators::scalar_t
matrix_t::Scalar scalar_t
Scalar type of matrix elements.
Definition: ImplicitOperators_fwd.hpp:48
mm::ImplicitOperators::vector_t
shape_storage_t::vector_t vector_t
Vector type.
Definition: ImplicitOperators_fwd.hpp:45
mm::ImplicitOperators::grad
GradOp grad(int node, const vector_t &v, int row)
Sets implicit equation that gradient of a field at node-th point along v is equal to some value.
Definition: ImplicitOperators_fwd.hpp:335
mm::ImplicitOperators::OpBase::eval
RowOp eval(scalar_t alpha) const
Write appropriate coefficients for this operation to the matrix.
Definition: ImplicitOperators_fwd.hpp:133
dim
@ dim
Number of elements of this matrix.
Definition: MatrixBaseAddons.hpp:14
mm::ImplicitOperators::ImplicitOperators
ImplicitOperators()
Default constructor sets offset to 0 and pointers to nullptr.
Definition: ImplicitOperators_fwd.hpp:225
mm::ImplicitOperators::rhs
rhs_t * rhs
Pointer to right hand side.
Definition: ImplicitOperators_fwd.hpp:56
mm::ImplicitOperators::RowOp::operator+
RowOp operator+(const RowOp &other) const
Add two row operations together.
Definition: ImplicitOperators_fwd.hpp:95
mm::ImplicitOperators::neumann
GradOp neumann(int node, const vector_t &unit_normal, int row)
Sets neumann boundary conditions in node node.
Definition: ImplicitOperators_fwd.hpp:355
assert_msg
#define assert_msg(cond,...)
Assert with better error reporting.
Definition: assert.hpp:75
mm::ImplicitOperators::hasMatrix
bool hasMatrix() const
Returns true if operators have a non-null pointer to problem matrix.
Definition: ImplicitOperators_fwd.hpp:268
mm::ImplicitOperators::lap
BasicOp< Lap< dim > > lap(int node, int row)
Sets implicit equation that Laplacian of a field at node-th point is equal to some value.
Definition: ImplicitOperators_fwd.hpp:309
mm::ImplicitOperators::OpBase::operator+
RowOp operator+(RowOp right)
Combine this operation with another row operation.
Definition: ImplicitOperators_fwd.hpp:143
Config.hpp
mm::ImplicitOperators::OpBase::operator*
friend RowOp operator*(scalar_t alpha, const OpBase &o)
Multiply with scalar from the left.
Definition: ImplicitOperators_fwd.hpp:150
mm::ImplicitOperators::OpBase::operator-
RowOp operator-()
Multiply this operation by -1.
Definition: ImplicitOperators_fwd.hpp:145
mm::ImplicitOperators::BasicOp::o
op_family_t::operator_t o
Basic operator with precomputed shape functions.
Definition: ImplicitOperators_fwd.hpp:179
mm::ImplicitOperators::M
matrix_t * M
Pointer to problem matrix.
Definition: ImplicitOperators_fwd.hpp:55
mm::ImplicitOperators::OpBase::operator+
RowOp operator+(const OpBase< other_derived_t > &right)
Combine tho operation with another operation. Both operations are evaluated.
Definition: ImplicitOperators_fwd.hpp:148
mm::ImplicitOperators::hasShapes
bool hasShapes() const
Returns true if operators have a non-null pointer to storage.
Definition: ImplicitOperators_fwd.hpp:266
mm::ImplicitOperators::RowOp::operator+
RowOp operator+(const OpBase< derived_t > &right)
Add normal operation to a row operation by evaluating the former and adding normally.
Definition: ImplicitOperators_fwd.hpp:103
mm::ImplicitOperators::operator<<
friend std::ostream & operator<<(std::ostream &os, const ImplicitOperators< S, M, R > &op)
Output basic info about given operators.
Definition: ImplicitOperators.hpp:65
mm::ImplicitOperators::setProblem
void setProblem(matrix_t &M, rhs_t &rhs, int row_offset=0, int col_offset=0)
Sets current matrix and right hand side.
Definition: ImplicitOperators_fwd.hpp:248
mm::ImplicitOperators::dim
@ dim
Dimensionality of the function domain.
Definition: ImplicitOperators_fwd.hpp:50
mm::ImplicitOperators::apply
BasicOp< op_family_t > apply(int node, typename op_family_t::operator_t o)
Same as apply with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:433
mm::ImplicitOperators::matrix_t
matrix_type matrix_t
Matrix type.
Definition: ImplicitOperators_fwd.hpp:43
mm::ImplicitOperators::der2
BasicOp< Der2s< dim > > der2(int node, int varmin, int varmax, int row)
Sets implicit equation that second derivative of a field at node-th point with respect to varmin and...
Definition: ImplicitOperators_fwd.hpp:409
mm::ImplicitOperators::der2
BasicOp< Der2s< dim > > der2(int node, int varmin, int varmax)
Same as der2 with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:413
Operators_fwd.hpp
mm::ImplicitOperators::GradOp::vec
vector_t vec
Vector representing the direction of differentiation.
Definition: ImplicitOperators_fwd.hpp:204
mm::ImplicitOperators::setRowOffset
void setRowOffset(int row_offset)
Sets row offset for given matrix, treating it as is the first row had index row_offset.
Definition: ImplicitOperators_fwd.hpp:255
mm::ImplicitOperators::OpBase::operator=
void operator=(scalar_t x)
Evaluates *this and sets rhs to x.
Definition: ImplicitOperators_fwd.hpp:139
mm::ImplicitOperators::OpBase::op
ImplicitOperators & op
Reference to underlying operators.
Definition: ImplicitOperators_fwd.hpp:121
mm::ImplicitOperators
This class represents implicit operators that fill given matrix M and right hand side rhs with approp...
Definition: ImplicitOperators_fwd.hpp:40
mm::ImplicitOperators::OpBase::OpBase
OpBase(ImplicitOperators &op, int node, int row)
Construct operation for a given node.
Definition: ImplicitOperators_fwd.hpp:125
assert.hpp
mm::ImplicitOperators::RowOp::RowOp
RowOp(ImplicitOperators &op, int row)
Construct a row operation for a given row.
Definition: ImplicitOperators_fwd.hpp:85
mm::ImplicitOperators::BasicOp::eval
RowOp eval(scalar_t alpha) const
Evaluate this operator.
Definition: ImplicitOperators_fwd.hpp:185
mm::ImplicitOperators::BasicOp::BasicOp
BasicOp(ImplicitOperators &op, int node, int row, typename op_family_t::operator_t o)
Construct given basic operator 'o'.
Definition: ImplicitOperators_fwd.hpp:182
mm::ImplicitOperators::OpBase::row
int row
Matrix row to which the operation should be applied (without offset).
Definition: ImplicitOperators_fwd.hpp:123
mm::ImplicitOperators::der1
BasicOp< Der1s< dim > > der1(int node, int var, int row)
Sets implicit equation that derivative of a field at node-th point with respect to var is equal to s...
Definition: ImplicitOperators_fwd.hpp:382
mm::ImplicitOperators::setColOffset
void setColOffset(int col_offset)
Sets col offset for given matrix, treating it as is the first column had index col_offset.
Definition: ImplicitOperators_fwd.hpp:260
mm::ImplicitOperators::row_offset
int row_offset
Row offset to be used when accessing matrix or rhs coefficients.
Definition: ImplicitOperators_fwd.hpp:57
mm::ImplicitOperators::value
ValueOp value(int node, int row)
Sets implicit equation that value of a field is equal to some other value.
Definition: ImplicitOperators_fwd.hpp:287
mm::ImplicitOperators::lap
BasicOp< Lap< dim > > lap(int node)
Same as lap with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:311
mm::ImplicitOperators::GradOp::eval
RowOp eval(scalar_t alpha) const
Evaluate this operator.
Definition: ImplicitOperators_fwd.hpp:211
mm::ImplicitOperators::hasRhs
bool hasRhs() const
Returns true if operators have a non-null pointer to problem right hand side.
Definition: ImplicitOperators_fwd.hpp:270
mm::ImplicitOperators::ImplicitOperators
ImplicitOperators(const shape_storage_t &ss)
Set only shape storage, the rest as default constructor.
Definition: ImplicitOperators_fwd.hpp:227
mm::ImplicitOperators::der1
BasicOp< Der1s< dim > > der1(int node, int var)
Same as der1 with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:386
mm::ImplicitOperators::addToM
void addToM(int i, int j, scalar_t v)
Add v to M(i, j).
Definition: ImplicitOperators.hpp:41
mm::ImplicitOperators::apply
BasicOp< op_family_t > apply(int node)
Overload for default-constructible operator.
Definition: ImplicitOperators_fwd.hpp:439
mm::ImplicitOperators::neumann
GradOp neumann(int node, const vector_t &n)
Same as neumann with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:361
mm::ImplicitOperators::RowOp::op
ImplicitOperators & op
Reference to underlying operators.
Definition: ImplicitOperators_fwd.hpp:82
mm::ImplicitOperators::shape_storage_t
shape_storage_type shape_storage_t
Type of shape storage.
Definition: ImplicitOperators_fwd.hpp:42
mm::ImplicitOperators::col_offset
int col_offset
Column offset to be used when accessing matrix coefficients.
Definition: ImplicitOperators_fwd.hpp:58
mm::ImplicitOperators::OpBase::operator*
RowOp operator*(scalar_t alpha)
Multiply this operation by a scalar.
Definition: ImplicitOperators_fwd.hpp:141
mm::ImplicitOperators::RowOp
Class representing an operation on a specific row of the matrix.
Definition: ImplicitOperators_fwd.hpp:79
mm::ImplicitOperators::RowOp::operator=
void operator=(scalar_t value)
Assigns given value to the right hand side.
Definition: ImplicitOperators_fwd.hpp:106
mm::ImplicitOperators::apply
BasicOp< op_family_t > apply(int node, typename op_family_t::operator_t o, int row)
Add the weights for operator o to the appropriate elements in the matrix.
Definition: ImplicitOperators_fwd.hpp:427
mm::ImplicitOperators::OpBase::node
int node
Index of the point for which to apply the operation.
Definition: ImplicitOperators_fwd.hpp:122
mm::ImplicitOperators::BasicOp
Class representing Basic operators i.e. Der1, Der2, Lap or user defined custom operators.
Definition: ImplicitOperators_fwd.hpp:176
mm::ImplicitOperators::ValueOp
Class representing the "evaluate" operation, i.e. the zero-th derivative.
Definition: ImplicitOperators_fwd.hpp:166
mm::ImplicitOperators::value
ValueOp value(int node)
Same as value with row equal to current node.
Definition: ImplicitOperators_fwd.hpp:289
USE_BASE
#define USE_BASE(Name)
Macro that inherits appropriate members from parent OpBase class.
Definition: ImplicitOperators_fwd.hpp:154