Class documentation of Concepts

Loading...
Searching...
No Matches
implicitEquilibratedAO.hh
Go to the documentation of this file.
1
7#ifndef implicitAO_hh
8#define implicitAO_hh
9
10#include "fluxes.hh"
11//#include "innerResidual.hh"
12//#include "linInnerProd.hh"
13//#include "moments.hh"
14//#include "patches.hh"
15
17//for computing L2Error
18
19namespace concepts{
20
22public:
26 ImplicitEquilibratedA0Error(const std::string& errorMessage) throw () {
27 errorMessage_ = errorMessage;
28 }
29
31 }
32 ;
33protected:
34 virtual std::ostream& info(std::ostream& os) const throw () {
35 return os << concepts::typeOf(*this) << "[" << errorMessage_ << " ]";
36
37 }
38private:
39 std::string errorMessage_;
40};
41}
42
43
44
45
46namespace hp2D{
47
48//class representing the error estimator presented by Ainsworth and Oden in 2d
49// based on equilibrated moments
50
51template<class F>
52class ImplicitEquilibratedA0: public concepts::LocalEstimator<F>{
53
54public:
55
75 ImplicitEquilibratedA0(const concepts::SpaceOnCells<F>& spc,
76 const concepts::Vector<F>& sol,
78 ushort loc_rule = 2 ,
79 const concepts::ElementFormula<F>* a = 0):
80 concepts::LocalEstimator<F>(spc, sol), rule_(loc_rule), f_(f){
81 //insert zero to inner edges attributes since by default inner edges have
82 iAttrbs_.insert(0);
84
85 //the implementation of the function have to be done
86 if(a)
87 throw concepts::MissingFeature("Not implemented");
88 };
89
90
91 virtual ~ImplicitEquilibratedA0(){};
92
104 void addLinearformInfo(concepts::LinearForm<F>& form, const F scalar =1){
105 B_.push_back(&form);
106 scalars_.push_back(scalar);
107 }
108
109 void addBillinearInfo(concepts::BilinearForm<F>& bform, const F scalar = 1){
110 L_.push_back(&bform);
111 scalars_L.push_back(scalar);
112 }
113
120 void addNeumannInfo(concepts::ParsedFormula<F>& frm, const concepts::Set<uint>& attrb){
121 nfrms_.push_back(frm);
122 nAttrbs_.push_back(attrb);
123 for(concepts::Set<uint>::const_iterator iter = attrb.begin(); iter != attrb.end(); ++iter)
124 help_[*iter] = nfrms_.size()-1;
125 }
129 void addDirichletInfo(const concepts::Set<uint>& attrb){
130 // concepts::Set<uint>::const_iterator iter = attrb.begin();
131 // for(;iter != attrb.end();++iter){
132 //union dirichlet data
133 dAttrbs_ = dAttrbs_||attrb;
134 // }
135
136 }
137
141 void addInnerInfo(const concepts::Set<uint>& attrb){
142 iAttrbs_= iAttrbs_||attrb;
143 }
144
145
146 void isunique(bool unique=true){
147 unique_=unique;
148 //TODO: the action is setted
149 }
150
151 //Computes the error with all information, make sure to add information before with
152 void compute(){
153
154 const hp2D::hpAdaptiveSpaceH1* hpSpc =dynamic_cast<const hp2D::hpAdaptiveSpaceH1*> (&(this->spc_));
155 if (hpSpc) {
156
157 const concepts::BoundaryConditions* bcP = hpSpc->helper().bc();
158 //copy to undo const
160 //Patches
161 geometry::VtxToPatchMaps patchMaps(*hpSpc, bc);
162
163 //Build the inner Residual with the help of the added residual information
164 //the Linearforms are just evaluated on boundary basis functions, therefore
165 //the linearforms must be choiceable, i.e. a LinearFormChoice
166 concepts::InnerResidual<F> innerRes(*hpSpc);
168 //add B(u_h,v)
169 for(uint i = 0; i < B_.size(); ++i ){
170 lfc = dynamic_cast<concepts::LinearFormChoice*>(B_[i]);
171 if(lfc){
172 lfc->setBasis(concepts::BND);
173 innerRes.add(*(B_[i]), (-1)*scalars_[i]);
174 }else{
175 throw conceptsException(concepts::ImplicitEquilibratedA0Error("Linearform must be a LinearformChoice"));
176 }
177 }
178 //add f(v)
179 lfc = dynamic_cast<concepts::LinearFormChoice*>(&f_);
180 if(lfc){
181 lfc->setBasis(concepts::BND);
182 innerRes.add(f_, -1);
183 }else
184 throw conceptsException(concepts::ImplicitEquilibratedA0Error("Linearform must be a LinearformChoice"));
185
186
187
188 //Build approximated Moments
189 hp2D::ApproxMoments<F> apprxMoments(*hpSpc, this->sol_);
190 //add Neumann data
191 for(uint i = 0 ; i < nfrms_.size(); ++i)
192 apprxMoments.addNeumann(nfrms_[i],nAttrbs_[i] );
193 //add Dirichlet data
194 if(dAttrbs_.size())
195 apprxMoments.addDirichlet(dAttrbs_);
196
197 apprxMoments.addComplete();
198
199 //compute equilibrated Moments
200 hp2D::EquilibratedMomentsAO<F> moments(*hpSpc, patchMaps, innerRes, apprxMoments);
201
202 //build the Fluxes for local neumannboundary condition
203 hp2D::TraceSpace fluxSpc(*hpSpc,iAttrbs_);
204 hp2D::Fluxes flux(fluxSpc, moments);
205
206
207 //Reset Linearforms to evaluate on all basis functions, use for local problems
208 for(uint i = 0; i < B_.size(); ++i ){
209 //now lfc is ok, was tested before
210 lfc = dynamic_cast<concepts::LinearFormChoice*>(B_[i]);
211 lfc->setBasis(concepts::Default);
212 }
213 lfc = dynamic_cast<concepts::LinearFormChoice*>(&f_);
214 lfc->setBasis(concepts::Default);
215
216 //squared local errors
218 error_2.rehash(hpSpc->nelm());
219
220
221 //if unique local problem compute standard
222 if(unique_) {
223
224 std::unique_ptr<hp2D::hpAdaptiveSpaceH1::Scan> sc(hpSpc->scan());
225 while (!sc->eos()) {
226 hp2D::Element<Real>& elm = (*sc)++;
227 hp2D::Quad<Real>* quad = dynamic_cast<hp2D::Quad<Real>*> (&elm);
228 if (quad) {
229 //build the local Space
230 concepts::MutableMesh2 quadMesh;
231 concepts::Quad2d* quad2d = dynamic_cast<concepts::Quad2d*>(&quad->cell());
232 if (quad2d) {
233 quadMesh.addCell(quad2d, false);
234 uint p = std::max(quad->p()[0], quad->p()[1]);
235 hp2D::hpAdaptiveSpaceH1 spc_K(quadMesh, 0, p+ rule_, &bc);
236 spc_K.rebuild();
237
238
239 //solution of the local problem
240 //concepts::Vector<F> sol_K;
241
242 //system Matrix
243 concepts::SparseMatrix<F> A_K(spc_K.dim());
244 //rhs b_K
245 concepts::Vector<F> b_K(spc_K);
246 //build the local right hand side, rhs = f(v) - B(u_h,v) + g(v) + flux(v)
247 buildlocalRhs_(quad2d->connector(), spc_K, flux, bc, b_K);
248
249 //build the systemmatrix
250 buildlocalA_(spc_K, A_K);
251
252 //solve the local problem
253 concepts::Vector<F> sol_K(spc_K);
254 //TODO: Have Mumps? if have mumps else superLU else gmres TODO: use mumps for speed up
255 concepts::SuperLU<F> solver_K(A_K);
256 solver_K(b_K, sol_K);
257
258
259 //compute the local error squared
260 error_2[quad2d->connector().key()] = computeLocalError_2(spc_K,sol_K);
261
262 }//if quad 2d
263 else
264 throw concepts::MissingFeature("Not implemented A ");
265 }//if quad
266 else
267 throw concepts::MissingFeature("Not implemented B ");
268 }//while
269
270 }// unique case
271
272 std::unique_ptr<hp2D::hpAdaptiveSpaceH1::Scan> sc(hpSpc->scan());
273 while (!sc->eos()) {
274 hp2D::Element<Real>& elm = (*sc)++;
275 hp2D::Quad<Real>* quad =
276 dynamic_cast<hp2D::Quad<Real>*> (&elm);
277 if (quad) {
278 //build the local Space
279 concepts::MutableMesh2 quadMesh;
280 concepts::Quad2d* quad2d =
281 dynamic_cast<concepts::Quad2d*> (&quad->cell());
282 if (quad2d) {
283 quadMesh.addCell(quad2d, false);
284 uint p = std::max(quad->p()[0], quad->p()[1]);
285 hp2D::hpAdaptiveSpaceH1 spc_K(quadMesh, 0, p + rule_, &bc);
286 spc_K.rebuild();
287
288 //solution of the local problem
289 //concepts::Vector<F> sol_K;
290
291 //rhs b_K
292 concepts::Vector<F> b_K(spc_K);
293 //build the local right hand side, rhs = f(v) - B(u_h,v) + g(v) + flux(v)
294 bool unique = buildlocalRhs_(quad2d->connector(), spc_K, flux, bc,b_K);
295
296 //system Matrix
297 concepts::SparseMatrix<F> A_K(spc_K.dim());
298
299
300 //build the systemmatrix
301 buildlocalA_(spc_K, A_K);
302
303 //solve the local problem
304 concepts::Vector<F> sol_K(spc_K);
305 //TODO: Have Mumps? if have mumps else superLU else gmres TODO: use mumps for speed up
306 concepts::SuperLU<F> solver_K(A_K);
307 solver_K(b_K, sol_K);
308
309 }
310 }//quad
311 }//while
312
313
314
315 // hp2D::Riesz<Real> lf_one(concepts::ConstFormula<Real>(1.0));
316 // concepts::Vector<Real> v_one_K(spcOneElement, lf_one);
317 // uint dim_K = spcOneElement.dim();
318 // concepts::SparseMatrix<Real> A_K(dim_K + 1, dim_K + 1);
319 // concepts::IndexRange idxrange_K(0, dim_K - 1);
320 // concepts::Set<concepts::IndexRange> setIdx_K;
321 // setIdx_K.insert(idxrange_K);
322 // concepts::SubMatrixN<concepts::SparseMatrix<Real> > MsubA_K(
323 // A_K, setIdx_K, setIdx_K);
324 // MsubA_K.assembly(MsubA_K, spcOneElement, la_K);
325 // for (uint i = 0; i < dim_K; i++)
326 // A_K(i, dim_K) = A_K(dim_K, i) = v_one_K[i];
327 // A_K.compress();
328 //
329 //
330 //
331 // concepts::Vector<Real> bigrhs_K(dim_K+1);
332 // for(uint i = 0 ; i < dim_K; i++)
333 // bigrhs_K[i]=rhs_K[i];
334 // bigrhs_K[dim_K]=0;
335 //
336 //
337 // //solve the System
338 // concepts::SuperLU<Real> solver_K(A_K);
339 // //concepts::CG<Real> solver(A, 1e-6, 1000);
340 // concepts::Vector<Real> bigsol_K(dim_K + 1);
341 // solver_K(bigrhs_K, bigsol_K);
342 // sol_K.resize(dim_K);
343 // for(uint i = 0 ; i < dim_K ; i++)
344 // sol_K[i]= bigsol_K[i];
345 //
346 // //sol_K(bigsol_K, setIdx_K);
347
348
349
350
351
352
353
355
356 //Place local errors and global error
357
358
359
360 for(concepts::HashMap<Real>::const_iterator iter_err = error_2.begin(); iter_err != error_2.end(); ++iter_err){
361 concepts::LocalEstimator<F>::locError_[iter_err->first] = sqrt(iter_err->second);
362 concepts::Estimator<F>::globError_ += iter_err->second;
363 }
365
366 }//if hpSpc
367 else
368 throw conceptsException(concepts::MissingFeature("Just AdaptiveSpace implemented."));
369
370
371
372
373
374 }
375
376 virtual ImplicitEquilibratedA0* clone() const{return new ImplicitEquilibratedA0(*this);}
377
378protected:
379
380 virtual std::ostream& info(std::ostream& os) const{
381 return os<< concepts::typeOf(*this);
382 }
383
384private:
385
386 //weak residual as informational part
388 //scalar multiplication factors for the wres_ linearforms
389 concepts::Sequence<F> scalars_;
390 //rhs lform
392
393 //Billinearinformation
395 concepts::Sequence<F> scalars_L;
396
397
398
399 //flag mark if local problems are solveable uniquely,
400 //i.e. for pure laplace problems local problems are solveable but not unique, since a local
401 //problem is a pure NeumannProblem
402 bool unique_;
403 //local polynomial addition rule, elementpolynomial.max + rule_
404 ushort rule_;
405
406 //Neumann formulas
408 //Neumann Attributes
410 //help structur to find position of neumann formula
412 //Dirichlet Attributes
413 concepts::Set<uint> dAttrbs_;
414 //inner Edges Attributes
415 concepts::Set<uint> iAttrbs_;
416
417
418
419 //TODO: Make this const
420 //build rhs for the unique case
421 bool buildlocalRhs_(const concepts::Quad& quad,
422 const hp2D::hpAdaptiveSpaceH1& spc_K,
423 const hp2D::Fluxes& flux,
426
427
428 // build rhs to int flux(v) ds on interior edges
429 hp2D::TraceSpace tspcFluxElements(spc_K, iAttrbs_);
430
431 //get all possible neumann edges
432 concepts::Set<uint> nattrb_K;
433 for (uint i = 0; i < 4; ++i) {
434 if (bc(quad.edge(i)->attrib()).type()
435 == concepts::Boundary::NEUMANN)
436 nattrb_K.insert(quad.edge(i)->attrib().attrib());
437 }
438
439
440 //number of pure Neumannedges, it is 4 if it's an interior quad or a quad that intersects neumannbdn
441 uint noN = tspcFluxElements.nelm() + nattrb_K.size();
442 //up to 4 edges can be neumann ones
444
445 //is a pure non unique neumannproblem
446
447 //local problem is unique solveable or touches a boundary element that is not Neumann (i.e. a Dirichlet)
448 //TODO: What if different boundary type?
449 if (unique_ || noN < 4){
450
451 hp2D::LocalFluxes locFlux(tspcFluxElements, quad.key(), flux);
452 hp1D::Riesz<F> lformFluxes_new(locFlux);
453 //build rhs vector coressponding to the fluxes
454 concepts::Vector<F> rhs_flux(tspcFluxElements, lformFluxes_new);
455
456 // f_K(v)
457 concepts::Vector<F> rhs_f_K(spc_K, f_);
458
459 //initialisation plus data copy
460 rhs = rhs_flux;
461 rhs += rhs_f_K;
462
463 //TODO: was ist wenn die billinearform nicht auf dem Space lebt?
464 for (uint i = 0; i < B_.size(); ++i) {
465 concepts::Vector<F> rhs_B(spc_K, *(B_[i]));
466 rhs += rhs_B * scalars_[i];
467 }
468
469 //add neumann contributions
470 if (nattrb_K.size() > 0) {
472 nattrb_K.begin(); iter != nattrb_K.end(); ++iter) {
473 hp2D::TraceSpace tspcNeumann(spc_K, *iter);
474 hp1D::Riesz<F> lform_g(nfrms_[help_[*iter]]);
475 //Boundary g_K integrals
476 concepts::Vector<F> rhs_g(tspcNeumann, lform_g);
477 rhs += rhs_g;
478 }
479 }
480
481 //problem is unique solveable return true
482 return true;
483
484 }else{
485 //local problem has solution that is unique up to a constant
486
487
488
489
490
491 }
492
493
494
495
496
497
498
499
500 }//build local Rhs
501
502
503
504
505
506 //TODO: Make this const
507 //build rhs for the unique case
508 void buildnonUniquelocalRhs_(const concepts::Quad& quad,
509 const hp2D::hpAdaptiveSpaceH1& spc_K,
510 const hp2D::Fluxes& flux,
513
514
515 // build rhs to int flux(v) ds on interior edges
516 hp2D::TraceSpace tspcFluxElements(spc_K, iAttrbs_);
517
518 //get all possible neumann edges
519 concepts::Set<uint> nattrb_K;
520 for(uint i=0; i< 4 ; ++i){
521 if(bc(quad.edge(i)->attrib()).type()== concepts::Boundary::NEUMANN)
522 nattrb_K.insert(quad.edge(i)->attrib().attrib());
523 }
524
525
526
527 hp2D::LocalFluxes locFlux(tspcFluxElements, quad.key(), flux);
528 hp1D::Riesz<F> lformFluxes_new(locFlux);
529 //build rhs vector coressponding to the fluxes
530 concepts::Vector<F> rhs_flux(tspcFluxElements, lformFluxes_new);
531
532 // f_K(v)
533 concepts::Vector<F> rhs_f_K(spc_K, f_);
534
535 //initialisation plus data copy
536 rhs = rhs_flux;
537 rhs+= rhs_f_K;
538
539 //TODO: was ist wenn die billinearform nicht auf dem Space lebt?
540 for(uint i = 0 ; i < B_.size(); ++i){
541 concepts::Vector<F> rhs_B(spc_K,*(B_[i]));
542 rhs+= rhs_B*scalars_[i];
543 }
544
545
546 //add neumann contributions
547 if(nattrb_K.size()>0){
548 for(concepts::Set<uint>::const_iterator iter = nattrb_K.begin(); iter != nattrb_K.end(); ++iter){
549 hp2D::TraceSpace tspcNeumann(spc_K, *iter);
550 hp1D::Riesz<F> lform_g(nfrms_[help_[*iter]]);
551 //Boundary g_K integrals
552 concepts::Vector<F> rhs_g(tspcNeumann, lform_g);
553 rhs += rhs_g;
554 }
555 }
556 }//build local Rhs
557
558
559
560
561
562
563
564
565
566
567
568
569
570 void buildlocalA_(const hp2D::hpAdaptiveSpaceH1& spc_K, concepts::SparseMatrix<F>& A_K){
571 typename concepts::Sequence<concepts::BilinearForm<F>* >::const_iterator iter = L_.begin();
572 typename concepts::Sequence<F>::const_iterator iter_s = scalars_L.begin();
573 //Billinearinformation
574 for(; iter!=L_.end(); ++iter, ++iter_s){
575 concepts::SparseMatrix<F> A(spc_K, **iter);
576 //add local contribution to the whole local matrix
577 A.addInto(A_K,*iter_s);
578 }
579 }
580
581
582 Real computeLocalError_2(hp2D::hpAdaptiveSpaceH1& spc_K, const concepts::Vector<F>& sol_K){
583 //TODO: Write this general !!
585 concepts::ElementFormulaVector<2,F> errGrad_K(spc_K, sol_K, hp2D::Grad<Real>());
586 if(unique_){
587 Real grad_l2 = concepts::L2product(spc_K,errGrad_K);
588 Real id_l2 = concepts::L2product(spc_K, errID_K);
589 return grad_l2 + id_l2;
590 }else{
591 //H1 seminorm
592 return concepts::L2product(spc_K,errGrad_K);
593 }
594 }
595
596
597
598
599
600};
601
602
603} //namespace
604
605#endif // implicitAO_hh
F max(const concepts::Array< F > &a)
Returns the maximal value in array a.
Definition arrayOp.hh:91
#define conceptsException(exc)
uint attrib() const
Returns the attribute.
Definition connector.hh:38
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 std::ostream & info(std::ostream &os) const
Returns information in an output stream.
ImplicitEquilibratedA0Error(const std::string &errorMessage)
virtual void addCell(Cell *cell, bool holding=true)
Quad & connector() const
Returns the quadrilateral connector (topology)
Definition cell2D.hh:234
Edge * edge(uint i) const
Definition topology.hh:316
virtual const concepts::QuadNd & cell() const
Returns the cell on which the element is built.
Definition quad.hh:196
const ushort * p() const
Definition quad.hh:229
virtual Scan * scan() const
Returns a scanner to iterate over the elements of the space.
virtual uint nelm() const
Returns the number of elements in the space.
#define conceptsAssert(cond, exc)
std::string typeOf(const T &t)
Definition output.hh:43
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