Class documentation of Concepts

Loading...
Searching...
No Matches
implicitResidual.hh
1#ifndef implicitResidual_hh
2#define implicitResidual_hh
3
4#include "estimator.hh"
5
6//TODO: Precise the includes
7#include "hp2D.hh"
8#include "formula.hh"
10
11#define COMPUTE_D 0
12
13using concepts::Real;
14
15namespace estimator{
16
17
18
36template<class F>
37class ImplicitResidual: public LocalEstimator<F>{
38
39public:
40
41
42
43 virtual ImplicitResidual<F>* clone() const = 0;
44
66 {
67 // DEBUGL(1, " add boundary data");
68 g_.push_back(&g);
69 gAttrbs_.push_back(nSet);
70
71 //eAttrbs_ = eAttrbs_ || nSet;
72 //DEBUGL(1, "all used attributes : " << eAttrbs_);
73 //DEBUGL(1, " done... ");
74 }
75
76
77
78
79
101 {
102 throw conceptsException(concepts::MissingFeature("Not Supported"));
103 }
104
105
106
107protected:
108
109
126 const concepts::Vector<F>& sol):
127 LocalEstimator<F>(spc, sol){};
128
129 virtual std::ostream& info(std::ostream& os) const{
130 return os << "Implicit Residual Error Estimator()";
131 }
132
133 //structure for the billinearforms of the local problems, with multiplikatives constant
134 //concepts::Sequence< concepts::BilinearForm<F>* > bforms_;
135 //const coeffs of the bforms
136 //concepts::Sequence< F > c_bforms_;
137
138 //local reference to the residual
139 //const concepts::ElementFormula<F>& res_;
140
141 //Neumann formulas
143 //Neumann Attributes
145
146
147 //all used edge attributes on that error estimates are placed.
148 concepts::Set<uint> eAttrbs_;
149
150 //map from edge attribute to the corresponding boundary formula, i.e. the neumann rhs
151 //concepts::HashMap<const concepts::ElementFormula<F>* > g_;
152
153
154};
155
156
157
158
159
160
161
162
163
164
165
166
214template<class F>
216
217
218
219public:
220
221
235 const concepts::Vector<F>& sol,
236 const concepts::ElementFormula<F>* a = 0):
237 ImplicitResidual<F>(spc, sol), a_(a), sol_(sol){
238
239
240
241 }
242
243 //starts the error computation
244 void compute(){
245 computeError_();
246 }
247
248
249 void addRhs(concepts::LinearForm<F>& lform, Real w = 1.0){
250 lforms_.push_back(&lform);
251 lws_.push_back(w);
252 //DEBUGL(1, "lforms updated : " << lforms_);
253 }
254
255 void addLhs(concepts::BilinearForm<F>& bform, Real w = 1.0){
256 bforms_.push_back(&bform);
257 ws_.push_back(w);
258 //DEBUGL(1, "bforms updated : " << bforms_);
259 }
260
261
262 //add information on how to compute the norm of local problem,
263 //e.g. energynorm, h1norm
264
265 // if no weight is given, it is assumed to be constant 1
266
267 //up to now everything in L2 norm
268 //
269 // example 1)
270 // func = Grad, w = 0 , s = 1.0
271 // implies norm contribution
272 // || Grad[u_{hp}] ||_{L^2(K)}
273 // on each element K.
274 //
275 // example 2)
276 // func = Value, w = ParsedFormula("(1/sqrt(x^2+y^2))") s = lambda
277 // implies the contribution
278 // lambda * || w * u_{hp} ||_{L^2(K)}
279 // on each element K where u_h is the approximate solution
280 void setErrorNorm(concepts::ElementFunction<F>& func, const concepts::ElementFormula<F>* w = 0, Real s = 1.0){
281 norm_fs_.push_back(&func);
282 norm_ws_.push_back(w);
283 norm_s_.push_back(s);
284
285 if( dynamic_cast<hp2D::Value<F>* >(&func))
286 norm_d_.push_back(1);
287 else if( dynamic_cast<hp2D::Grad<F>* >(&func) )
288 norm_d_.push_back(2);
289 else{
290 //easy extendable for Curl in 2d add dim = 2, for laplace 1 etc...
291 throw conceptsException(concepts::MissingFeature("Other function types currently not setted"));
292 }
293
294 //DEBUGL(1, "functions updated : "<< norm_fs_)
295 }
296
297
298
299
300
301 virtual const Real operator()() const {return this->operator()();}
302
303 virtual ImplicitResidual2D<F>* clone() const{return new ImplicitResidual2D<F>(*this);}
304
305
306protected:
307 virtual std::ostream& info(std::ostream& os) const {
308 return os << "Implicit Residual Error Estimator 2D()";
309 }
310
311private:
312
313 //isotropic scalar coefficient function in higest derivative operator
315
316 //the needed information to build local problems, i.e. the lfhs consisting of billinearforms
319
320
323
324
325
326
327// //norm construction stuff
332
333
334
335
336
337
338
339 const concepts::Vector<F>& sol_;
340
341 virtual void computeError_(){
342
343 //mean should be multiplied, thats all from inside
344 //the billinearforms must be builded from outside anyway
345 if(a_)
346 throw conceptsException(concepts::MissingFeature("Coefficient not supported"));
347
348
349 //set up needed size fore errors
350 LocalEstimator<F>::locError_.resize(this->spc_.nelm());
351 concepts::Set<uint> zero; zero.insert(0);
352
353
354 //at this time we assume all inner edges have attribute 0.
355 hp2D::NeumannTraceSpace ntspc(this->spc_, zero , concepts::EdgeTraceType::MEAN);
356 concepts::ElementFormulaVector<1> apprxMean(ntspc,this->sol_, hp2D::Value<Real>());
357 //l form due to the apprx Mean
358 hp1D::Riesz<Real> lform_mean(apprxMean);
359
360
361
362 const hp2D::hpAdaptiveSpaceH1* spc =dynamic_cast<const hp2D::hpAdaptiveSpaceH1*> (&(this->spc_));
364
365 const concepts::BoundaryConditions& bc = *(spc->helper().bc());
366
367 DEBUGL(COMPUTE_D, "start iteration");
368
369 std::auto_ptr<hp2D::hpAdaptiveSpaceH1::Scan> sc(spc->scan());
370 while (!sc->eos()) {
371 concepts::ElementWithCell<Real>& element = (*sc)++;
372 const hp2D::Quad<Real>* quad = dynamic_cast<const hp2D::Quad<Real>*> (&element);
374
376 msh.addCell(&quad->cell(),false);
377
378 uint K = quad->support().key();
379
380
382
383 //flag that marks cell intersects a boundary part that is free in sense
384 //of dof, i.e no Dirichlet Boundary, but for example a Neumann Boundary
385 //bool bnd_free = false; // <=> below set is non empty
386 //attributes of edges intersection those boundaries
387 concepts::Set<uint> bnd_free_attrb;
388
389 const concepts::Edge* edge = 0;
390 for(uint i = 0 ; (edge = quad->support().edge(i)) != 0; ++i){
391
392 //edge has a non default attribute, e.g. a setted boundary edge
393 // that is free in sense of dof, or a setted inner edge
394 if(edge->attrib().attrib() != 0){
395 //edge is free, so no dirichlet
396 if(bc(edge->attrib()).type() != concepts::Boundary::DIRICHLET)
397 bnd_free_attrb.insert(edge->attrib().attrib());
398 //copy global boundary conditions to the local
399 bc_K.add(edge->attrib().attrib(), bc( edge->attrib()).type());
400 //FIXME: if inner edges are not zero attributed,
401 // on the local problem this inner edge, as boundary edge
402 // is marked as FREE, this is ok in the freedom of dofs
403 // on that edge, but may lack in consistency
404 }
405 //edge is a default inner edge
406 else{
407 //we add neumann condition, as local problems will be defined as
408 bc_K.add(edge->attrib().attrib(), concepts::Boundary::NEUMANN);
409 }
410 }//for edges
411
412 //the local polynomial degree, by default + 2
413 uint lP = 3;
414 const ushort* p = spc->prebuild().innerDof(quad->support());
415 if(p){
416 conceptsAssert( p[0] == p[1] , concepts::Assertion());
417 lP = p[0] + lP - 1 ;
418 }
419
420 DEBUGL(COMPUTE_D, "on Cell K = " << K << " +++++++++++");
421
422 //all neumann conditions
423 hp2D::hpAdaptiveSpaceH1 lSpc(msh, 0, lP, &bc_K);
424 lSpc.rebuild();
425
426 //the current solution vector
427 concepts::Vector<Real> sol(lSpc.dim());
428 //the rhs vector
429 concepts::Vector<Real> rhs(lSpc.dim());
430
431
432 DEBUGL(COMPUTE_D, "start build system matrix ");
433
434 concepts::SparseMatrix<F> A(lSpc.dim());
435 //build local system matrix
436 for(uint k = 0 ; k < bforms_.size(); ++k){
437 concepts::SparseMatrix<F> A_k(lSpc,*bforms_[k]);
438 A_k.addInto(A, ws_[k]);
439 }
440
441 DEBUGL(COMPUTE_D, "done ...");
442
443 //build rhs due to weak residual
444 for(uint l = 0 ; l < lforms_.size(); ++l)
445 rhs += (concepts::Vector<F>(lSpc, *(lforms_[l])) * lws_[l] );
446
447 DEBUGL(COMPUTE_D, "rhs weak residual = " << rhs);
448
449 //complete rhs with integral about the neumann part.
450
451 if(ntspc.nelm()){
452 //tracespace on bdn edges, with attribute 0;
453 hp2D::TraceSpace tspc_mean(lSpc, zero);
454 DEBUGL(COMPUTE_D, " mean tracespace = " << tspc_mean);
455 concepts::Vector<F> rhs_mean(tspc_mean.dim());
456 std::auto_ptr<hp2D::TraceSpace::Scan> tsc(tspc_mean.scan());
457 while ( *(tsc.get()) ) {
458
459 hp1D::BaseElement<F>& elm = (*tsc)++;
460
461 DEBUGL(COMPUTE_D, " scan " << elm);
462 //hp space and therefore traceSpace are Real
463 const concepts::TMatrixBase<Real>& T = elm.T();
464 if (T.m() > 0) {
465 DEBUGL(COMPUTE_D, " T.m() > 0 ");
466 //key of first underlying element
467 //DEBUGL(COMPUTE_D, " uelm : " << ntspc.uelm(elm.support()));
468
469 bool isFirst = ntspc.isFirstUelm(elm.support(), K);
470 DEBUGL(COMPUTE_D, "is First = " << isFirst);
471
472 //uint K1 = ntspc.uelm(elm.support())[0].elm->support().key();
473 //scalar for the mean, depends on the first underlying element
474 Real s = (isFirst) ? 1.0 : -1.0;
475 DEBUGL(COMPUTE_D, " s = " << s);
478 DEBUGL(COMPUTE_D, " compute mean application");
479 lform_mean(elm, A);
480 DEBUGL(COMPUTE_D, " transpose and write into B");
481 A.transpose(); T(A, B); B.transpose();
482 DEBUGL(COMPUTE_D, " done ...");
483 DEBUGL(COMPUTE_D, " B = " << B);
484 for(int i = T.n(); i--;){
485 DEBUGL(COMPUTE_D, "write into rhs at " << T.index(i) << " while size = "<< rhs_mean.size());
486 rhs_mean[T.index(i)] += s * B(i,0);
487 }
488 }
489 DEBUGL(COMPUTE_D, "current contribution done ...");
490 }
491
492
493 DEBUGL(COMPUTE_D, "rhs mean residual = " << rhs_mean);
494 //update rhs;
495 rhs += rhs_mean;
496 }//if neumanntrace elements
497
498 //Cell boundary intersects Domain boundary, e.g. dirichlet/neumann Boundary
499 //or a edge is inner edge, but setted with non-zero attribute
500 if(bnd_free_attrb.size()){
501 //neumann boundary data or sth else must be added
502 conceptsAssert(this->g_.size(), concepts::Assertion());
503
504 for(uint i = 0 ; i < this->gAttrbs_.size(); ++i){
505 //cell has an edge for which neumann contribution must be taken into account
506 if((bnd_free_attrb&&this->gAttrbs_[i]).size()){
507
508 //DEBUGL(1, "Found Neumann Cell, compute on it");
509
510 hp2D::TraceSpace tspc_g(lSpc, this->gAttrbs_[i]);
511 hp1D::Riesz<F> lform_g(*(this->g_[i]));
512 //add local neumann data contribution
513 rhs += concepts::Vector<F>(tspc_g, lform_g);
514 }
515 }
516 }
517
518 DEBUGL(COMPUTE_D, "final rhs = " << rhs);
519
520
521 //solve the problem
522 try {
523 // Solver
524 std::auto_ptr<concepts::Operator<F> > solver(0);
526 solver.reset(new concepts::Mumps<F>(A));
527 conceptsAssert(solver.get(), concepts::Assertion());
528 (*solver)(rhs, sol);
529 } catch (concepts::ExceptionBase& e) {
530 std::cout << e << std::endl;
531 throw conceptsException(concepts::MissingFeature("Local problem seems not to be solveable, not supported"));
532 return;
533 }
534
535 //DEBUGL(1, "sol = " << sol);
536
537 //set the error of the solution in the requested norm
538 Real error_K = 0;
539 for(uint n = 0; n < norm_fs_.size(); ++n){
540 const uint dim = norm_d_[n];
541 if(dim == 1){
542 concepts::ElementFormulaVector<1> sol_frm(lSpc, sol, *(norm_fs_[n]));
543 if(norm_ws_[n]){
544 Real contr = norm_s_[n] * concepts::L2product(lSpc, *(norm_ws_[n]) * sol_frm);
545 //DEBUGL(1, " contr(1) = " << contr << " s = " << norm_s_[n]);
546 error_K += contr;
547 }
548 else
549 error_K += norm_s_[n] * concepts::L2product(lSpc, sol_frm);
550 }
551 if(dim == 2){
552 concepts::ElementFormulaVector<2> sol_frm(lSpc, sol, *(norm_fs_[n]));
553 if(norm_ws_[n])
554 error_K += norm_s_[n] * concepts::L2product(lSpc, *(norm_ws_[n]) * sol_frm);
555 else{
556 Real contr = norm_s_[n] * concepts::L2product(lSpc, sol_frm);
557 //DEBUGL(1, " contr(2) = " << contr);
558 error_K += contr;
559 }
560 }
561 //DEBUGL(1, "current error : "<< error_K);
562 }
563
564 //add current error squared
565 this->globError_ += error_K;
566
567 //here the global error must be increased and later square rooted
568 LocalEstimator<F>::locError_[K] = std::sqrt(error_K);
569 DEBUGL(COMPUTE_D, "estimated error on K = " << K << " : " << LocalEstimator<F>::locError_[K])
570
571 }//while
572
573 // n^2 = sum n_K^2
574 this->globError_ = std::sqrt(this->globError_);
575 }
576};
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592//namespace hp3D{
593//
594//class ExplicitResidual3D: concepts::ExplicitResidual{
595//public:
596//
597// template<typename F>
598// ExplicitResidual3D(const concepts::SpaceOnCells<F>& spc, const concepts::Vector<F>& sol, const concepts::ElementFormula<F>& res);
599//
600//protected:
601// virtual std::ostream& info(std::ostream& os) const{
602// return os << "Explicit Residual Error Estimator()";
603// }
604//
605//
606//private:
607// virtual void computeError_(const concepts::ElementFormula<F>& res, concepts::HashMap<Real>& jumpResidual);
608// virtual void computeJumpPart_(concepts::HashMap<Real>& jumpResidual) const;
609//};
610//
611//}
612
613
614
615
616
617
618} // namespace estimator
619
620#endif // implicitResidual_hh
#define conceptsException(exc)
uint attrib() const
Returns the attribute.
Definition connector.hh:38
void add(const Set< Attribute > &attrib, const Boundary &bcObject)
Adds boundary condition for a set of attributes.
const Key & key() const
Returns the key of the connector.
Definition connector.hh:105
const Attribute & attrib() const
Returns the attribute of the connector.
Definition connector.hh:108
virtual const TMatrixBase< F > & T() const =0
Returns the T matrix of the element.
virtual void addCell(Cell *cell, bool holding=true)
Timer and resource monitor.
uint m() const
Returns the number of rows.
Definition tmatrix.hh:388
uint n() const
Returns the number of columns.
Definition tmatrix.hh:393
virtual uint index(const uint i) const =0
ImplicitResidual2D(const concepts::SpaceOnCells< F > &spc, const concepts::Vector< F > &sol, const concepts::ElementFormula< F > *a=0)
void addBoundaryData(const concepts::Set< uint > &nSet, const concepts::ElementFormula< F > &g)
ImplicitResidual(const concepts::SpaceOnCells< F > &spc, const concepts::Vector< F > &sol)
void addBoundaryData(const concepts::Set< uint > &rSet, const concepts::ElementFormula< F > &h1, const concepts::ElementFormula< F > &h2)
virtual const concepts::Quad & support() const
Definition quad.hh:194
virtual const concepts::QuadNd & cell() const
Returns the cell on which the element is built.
Definition quad.hh:196
virtual Scan * scan() const
Returns a scanner to iterate over the elements of the space.
virtual const ushort * innerDof(const concepts::Connector2 &cntr) const
#define conceptsAssert(cond, exc)
#define DEBUGL(doit, msg)
Definition debug.hh:40
double Real
Definition typedefs.hh:39
Set< F > makeSet(uint n, const F &first,...)
Definition set.hh:320
Real L2product(const ElementWithCell< G > &elm, const ElementFormula< F, G > &u, const ElementFormula< Real > *c=0, const Real t=0.0, IntegrationCell::intFormType form=IntegrationCell::ZERO)
Definition integral.hh:214
unsigned short ushort
Abbreviation for unsigned short.
Definition typedefs.hh:51