BEM++  2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
extended_bem_cluster.hpp
1 // Copyright (C) 2011-2012 by the BEM++ Authors
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef bempp_extended_bem_cluster_hpp
22 #define bempp_extended_bem_cluster_hpp
23 
24 #include "bempp/common/config_ahmed.hpp"
25 
26 #ifdef WITH_AHMED
27 
28 #include "../common/common.hpp"
29 #include "ahmed_aux_fwd.hpp"
30 
31 #include <bbxbemcluster.h>
32 
33 namespace Bempp
34 {
35 
36 template <typename T>
37 class ExtendedBemCluster : public bbxbemcluster<T>
38 {
39 private:
40  typedef bbxbemcluster<T> Base;
41  enum { Dim = 3 }; // in future we might make this configurable
42 
43  // xminmax (inherited from cluster_bbx) is the bounding box of the
44  // *reference points* of DOFs. In contrast, extMinmax is the bounding box
45  // of the *bounding boxes* of DOFs. The former is used in cluster splitting;
46  // the latter to determine the distance between clusters and check the
47  // admissibility condition
48 
49 protected:
50  double extMinmax[2 * Dim];
51 
52 public:
53  // cluster with entries k <= i < l
54  ExtendedBemCluster(T* dofs, unsigned* op_perm, unsigned k, unsigned l,
55  unsigned int maximumBlockSize =
56  std::numeric_limits<unsigned int>::max(),
57  bool strongAdmissibility = false) :
58  Base(dofs, k, l),
59  m_maximumBlockSize(maximumBlockSize),
60  m_strongAdmissibility(strongAdmissibility) {
61 
62  this->xminmax = new double[2*Dim];
63 
64  for (int i = 0; i < Dim; ++i)
65  this->xminmax[i] = std::numeric_limits<double>::max();
66  for (int i = 0; i < Dim; ++i)
67  this->xminmax[Dim + i] = -std::numeric_limits<double>::max();
68 
69  for (int i = 0; i < Dim; ++i)
70  this->extMinmax[i] = std::numeric_limits<double>::max();
71  for (int i = 0; i < Dim; ++i)
72  this->extMinmax[Dim + i] = -std::numeric_limits<double>::max();
73 
74  // Compute the bounding box
75  for (unsigned j = this->nbeg; j < this->nend; ++j) {
76  const T* v = this->dofs + op_perm[j];
77  for (int i = 0; i < Dim; ++i) {
78  this->xminmax[i] = std::min<double>(this->xminmax[i], v->getcenter(i));
79  this->xminmax[Dim + i] =
80  std::max<double>(this->xminmax[Dim + i], v->getcenter(i));
81  this->extMinmax[i] = std::min<double>(this->extMinmax[i], v->getlbound(i));
82  this->extMinmax[Dim + i] =
83  std::max<double>(this->extMinmax[Dim + i], v->getubound(i));
84  }
85  }
86 
87  // Calculate diam2 and main direction
88  this->diam2 = 0.;
89  this->maindir = 0;
90  double maxExtent = 0.;
91  for (int i = 0; i < Dim; ++i) {
92  const double e = this->xminmax[Dim + i] - this->xminmax[i];
93  this->diam2 += e * e;
94  if (e > maxExtent) {
95  maxExtent = e;
96  this->maindir = i;
97  }
98  }
99 
100  // Calculate cntrdir
101  this->cntrdir = 0.5 * (this->xminmax[this->maindir] +
102  this->xminmax[Dim + this->maindir]);
103 
104  // Compute the index of the dof clostest to centre of mass.
105  // Code copied from (patched) bemcluster.h.
106 
107  this->seticom(op_perm[this->nbeg]); // original index. Will be replaced by permuted
108  // index in createClusterTree()
109 
110  double smin = 0.;
111  for (int j = 0; j < Dim; ++j) {
112  const double e = this->getcom(j) - dofs[op_perm[this->nbeg]].getcenter(j);
113  smin += e * e;
114  }
115 
116  for (int i = this->nbeg + 1; i < this->nend; ++i) {
117  double s = 0.;
118  for (int j = 0; j < Dim; ++j) {
119  const double e = this->getcom(j) - dofs[op_perm[i]].getcenter(j);
120  s += e * e;
121  }
122  if (s < smin) {
123  this->seticom(op_perm[i]);
124  smin = s;
125  }
126  }
127  }
128 
129  virtual ExtendedBemCluster* clone(unsigned int* op_perm,
130  unsigned int beg,
131  unsigned int end) const {
132  return new ExtendedBemCluster(this->dofs, op_perm, beg, end,
133  m_maximumBlockSize, m_strongAdmissibility);
134  }
135 
136  virtual unsigned dim() const { return Dim; }
137 
138  virtual bool isadm(double eta2, cluster* cl, bl_info& info) {
139  if (this->size() > m_maximumBlockSize ||
140  cl->size() > m_maximumBlockSize)
141  return (info.is_adm = false);
142  else
143  {
144  ExtendedBemCluster<T>* p = dynamic_cast<ExtendedBemCluster<T>*>(cl);
145  assert(p != NULL);
146  info.is_sep = false;
147 
148  const double d2 = std::min(this->diam2, p->diam2);
149 
150  bool strongAdmissibility = m_strongAdmissibility ||
151  p->usingStrongAdmissibilityCondition();
152  if (d2 < eta2 * centerToCenterDist2(p) &&
153  (!strongAdmissibility || 0 < this->extDist2(p)))
154  return (info.is_adm = true);
155  else
156  return (info.is_adm = false);
157  }
158  }
159 
160  // once all descendants are created (so that the array po_perm[nbeg...nend)
161  // won't change any more), set icom to the permuted index of the centroid
162  virtual void createClusterTree(const unsigned bmin,
163  unsigned* op_perm, unsigned* po_perm) {
164  Base::createClusterTree(bmin, op_perm, po_perm);
165  this->seticom(po_perm[this->geticom()]);
166  }
167 
168  double getcom(unsigned i) const {
169  return (this->xminmax[i + 3] + this->xminmax[i]) / 2.;
170  }
171 
174  double extDist2(const ExtendedBemCluster* cl) const {
175  double d = 0.;
176  const unsigned n = dim();
177 
178  for (unsigned i = 0; i<n; ++i) {
179  const double e = cl->extMinmax[i] - extMinmax[i+n];
180  if (e > 0.)
181  d += e * e;
182  else {
183  const double e1 = extMinmax[i] - cl->extMinmax[i+n];
184  if (e1 > 0.)
185  d += e1 * e1;
186  }
187  }
188  return d;
189  }
190 
193  {
194  double d2 = 0.0;
195  const unsigned n = cl->dim();
196 
197  for (unsigned j=0; j<n; ++j) {
198  const double d = this->getcom(j) - cl->getcom(j);
199  d2 += d*d;
200  }
201  return d2;
202  }
203 
205  void printBboxes() const {
206  std::cout << "Cluster with " << this->nend - this->nbeg
207  << " dofs;\nbbox: ";
208  for (int i = 0; i < Dim; ++i)
209  std::cout << this->xminmax[i] << " -- "
210  << this->xminmax[i + Dim] << "; ";
211  std::cout << "\nexterior bbox: ";
212  for (int i = 0; i < Dim; ++i)
213  std::cout << this->extMinmax[i] << " -- "
214  << this->extMinmax[i + Dim] << "; ";
215  std::cout << std::endl;
216  }
217 
218  unsigned int maximumBlockSize() const {
219  return m_maximumBlockSize;
220  }
221 
222  bool usingStrongAdmissibilityCondition() const {
223  return m_strongAdmissibility;
224  }
225 
226  void useStrongAdmissibilityCondition(bool value = true) {
227  m_strongAdmissibility = value;
228  for (int i = 0; i < this->getns(); ++i) {
229  cluster* son = this->getson(i);
230  if (ExtendedBemCluster* exbemson =
231  dynamic_cast<ExtendedBemCluster*>(son))
232  exbemson->useStrongAdmissibilityCondition(value);
233  }
234  }
235 
236  void clearDofPointers() {
237  this->dofs = 0;
238  for (int i = 0; i < this->getns(); ++i) {
239  cluster* son = this->getson(i);
240  if (ExtendedBemCluster* exbemson =
241  dynamic_cast<ExtendedBemCluster*>(son))
242  exbemson->clearDofPointers();
243  }
244  }
245 
246 private:
247  unsigned int m_maximumBlockSize;
248  bool m_strongAdmissibility;
249 };
250 
251 } // namespace Bempp
252 
253 #endif // WITH_AHMED
254 
255 #endif
Definition: extended_bem_cluster.hpp:37
double extDist2(const ExtendedBemCluster *cl) const
Definition: extended_bem_cluster.hpp:174
double centerToCenterDist2(const ExtendedBemCluster *cl)
returns square of the distance between centres of this cluster and cl
Definition: extended_bem_cluster.hpp:192
void printBboxes() const
debug routine: print bounding boxes of all dofs contained in this cluster
Definition: extended_bem_cluster.hpp:205