Logo  0.95.0-final
Finite Element Embedded Library and Language in C++
Feel++ Feel++ on Github Feel++ community
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
crb.hpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*-
2 
3  This file is part of the Feel library
4 
5  Author(s): Christophe Prud'homme <christophe.prudhomme@feelpp.org>
6  Date: 2009-11-24
7 
8  Copyright (C) 2009-2012 Université Joseph Fourier (Grenoble I)
9 
10  This library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU Lesser General Public
12  License as published by the Free Software Foundation; either
13  version 2.1 of the License, or (at your option) any later version.
14 
15  This library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public
21  License along with this library; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
29 #ifndef __CRB_H
30 #define __CRB_H 1
31 
32 
33 #include <boost/multi_array.hpp>
34 #include <boost/tuple/tuple.hpp>
35 #include "boost/tuple/tuple_io.hpp"
36 #include <boost/format.hpp>
37 #include <boost/foreach.hpp>
38 #include <boost/bimap.hpp>
39 #include <boost/bimap/support/lambda.hpp>
40 #include <boost/archive/text_oarchive.hpp>
41 #include <boost/archive/text_iarchive.hpp>
42 #include <boost/math/special_functions/fpclassify.hpp>
43 #include <fstream>
44 
45 
46 #include <boost/serialization/vector.hpp>
47 #include <boost/serialization/list.hpp>
48 #include <boost/serialization/string.hpp>
49 #include <boost/serialization/version.hpp>
50 #include <boost/serialization/split_member.hpp>
51 
52 #include <vector>
53 
54 #include <Eigen/Core>
55 #include <Eigen/LU>
56 #include <Eigen/Dense>
57 
59 #include <feel/feelcore/feel.hpp>
61 #include <feel/feelcore/parameter.hpp>
63 #include <feel/feelcrb/crbdb.hpp>
64 #include <feel/feelcrb/crbscm.hpp>
66 #include <feel/feelcrb/pod.hpp>
67 #include <feel/feeldiscr/bdf2.hpp>
68 #include <feel/feelfilters/exporter.hpp>
69 
71 
72 
73 namespace Feel
74 {
83 enum CRBErrorType { CRB_RESIDUAL = 0, CRB_RESIDUAL_SCM=1, CRB_NO_RESIDUAL=2 , CRB_EMPIRICAL=3};
84 
94 template<typename TruthModelType>
95 class CRB : public CRBDB
96 {
97  typedef CRBDB super;
98 public:
99 
100 
104 
105 
107 
111 
112  typedef TruthModelType truth_model_type;
113  typedef truth_model_type model_type;
114  typedef boost::shared_ptr<truth_model_type> truth_model_ptrtype;
115 
116  typedef double value_type;
117  typedef boost::tuple<double,double> bounds_type;
118 
120  typedef boost::shared_ptr<parameterspace_type> parameterspace_ptrtype;
122  typedef typename parameterspace_type::element_ptrtype parameter_ptrtype;
124  typedef typename parameterspace_type::sampling_ptrtype sampling_ptrtype;
125 
126  typedef boost::tuple<double, parameter_type, size_type, double, double> relative_error_type;
127  typedef relative_error_type max_error_type;
128 
129  typedef boost::tuple<double, std::vector< std::vector<double> > , std::vector< std::vector<double> >, double, double > error_estimation_type;
130  typedef boost::tuple<double, std::vector<double> > residual_error_type;
131 
132  typedef boost::bimap< int, boost::tuple<double,double,double> > convergence_type;
133 
134  typedef typename convergence_type::value_type convergence;
135 
136  typedef CRB self_type;
137 
140  typedef boost::shared_ptr<scm_type> scm_ptrtype;
141 
143  typedef CRBElementsDB<truth_model_type> crb_elements_db_type;
144  typedef boost::shared_ptr<crb_elements_db_type> crb_elements_db_ptrtype;
145 
148  typedef boost::shared_ptr<pod_type> pod_ptrtype;
149 
151  typedef typename model_type::functionspace_type functionspace_type;
152  typedef typename model_type::functionspace_ptrtype functionspace_ptrtype;
153 
154 
156  typedef typename model_type::element_type element_type;
157  typedef typename model_type::element_ptrtype element_ptrtype;
158 
159  typedef typename model_type::backend_type backend_type;
160  typedef boost::shared_ptr<backend_type> backend_ptrtype;
161  typedef typename model_type::sparse_matrix_ptrtype sparse_matrix_ptrtype;
162  typedef typename model_type::vector_ptrtype vector_ptrtype;
163  typedef typename model_type::beta_vector_type beta_vector_type;
164 
165 
166  typedef Eigen::VectorXd y_type;
167  typedef std::vector<y_type> y_set_type;
168  typedef std::vector<boost::tuple<double,double> > y_bounds_type;
169 
170  typedef std::vector<element_type> wn_type;
171  typedef boost::tuple< std::vector<wn_type> , std::vector<std::string> > export_vector_wn_type;
172 
173  typedef std::vector<double> vector_double_type;
174  typedef boost::shared_ptr<vector_double_type> vector_double_ptrtype;
175 
176  typedef Eigen::VectorXd vectorN_type;
177  typedef Eigen::MatrixXd matrixN_type;
178 
179  typedef Eigen::Map< Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > map_dense_matrix_type;
180  typedef Eigen::Map< Eigen::Matrix<double, Eigen::Dynamic, 1> > map_dense_vector_type;
181 
182  typedef boost::tuple< std::vector<vectorN_type> , std::vector<vectorN_type> , std::vector<vectorN_type>, std::vector<vectorN_type> > solutions_tuple;
183  typedef boost::tuple< double,double,double , std::vector< std::vector< double > > , std::vector< std::vector< double > > > upper_bounds_tuple;
184 
185  typedef std::vector<element_type> mode_set_type;
186  typedef boost::shared_ptr<mode_set_type> mode_set_ptrtype;
187 
188  typedef boost::multi_array<value_type, 2> array_2_type;
189  typedef boost::multi_array<vectorN_type, 2> array_3_type;
190  typedef boost::multi_array<matrixN_type, 2> array_4_type;
191 
193  typedef typename model_type::mesh_type mesh_type;
194  typedef boost::shared_ptr<mesh_type> mesh_ptrtype;
195 
197  typedef typename model_type::space_type space_type;
198  typedef boost::shared_ptr<space_type> space_ptrtype;
199 
202  typedef boost::shared_ptr<bdf_type> bdf_ptrtype;
203 
204  // ! export
206  typedef boost::shared_ptr<export_type> export_ptrtype;
207 
209  typedef boost::shared_ptr<preconditioner_type> preconditioner_ptrtype;
210 
211  //here a fusion vector containing sequence 0 ... nb_spaces
212  //useful to acces to a component of a composite space in ComputeIntegrals
213  static const int nb_spaces = functionspace_type::nSpaces;
214  typedef typename mpl::if_< boost::is_same< mpl::int_<nb_spaces> , mpl::int_<2> > , fusion::vector< mpl::int_<0>, mpl::int_<1> > ,
215  typename mpl::if_ < boost::is_same< mpl::int_<nb_spaces> , mpl::int_<3> > , fusion::vector < mpl::int_<0> , mpl::int_<1> , mpl::int_<2> > ,
216  typename mpl::if_< boost::is_same< mpl::int_<nb_spaces> , mpl::int_<4> >, fusion::vector< mpl::int_<0>, mpl::int_<1>, mpl::int_<2>, mpl::int_<3> >,
217  fusion::vector< mpl::int_<0>, mpl::int_<1>, mpl::int_<2>, mpl::int_<3>, mpl::int_<4> >
218  >::type >::type >::type index_vector_type;
219 
220 
222 
226 
228  CRB()
229  :
230  super(),
231  M_elements_database(),
232  M_nlsolver( SolverNonLinear<double>::build( SOLVERS_PETSC, Environment::worldComm() ) ),
233  M_model(),
234  M_output_index( 0 ),
235  M_tolerance( 1e-2 ),
236  M_iter_max( 3 ),
237  M_factor( -1 ),
238  M_error_type( CRB_NO_RESIDUAL ),
239  M_Dmu( new parameterspace_type ),
240  M_Xi( new sampling_type( M_Dmu ) ),
241  M_WNmu( new sampling_type( M_Dmu, 1, M_Xi ) ),
242  M_WNmu_complement(),
243  exporter( Exporter<mesh_type>::New( "ensight" ) )
244  {
245 
246  }
247 
249  CRB( std::string name,
250  po::variables_map const& vm )
251  :
252  super( ( boost::format( "%1%" ) % vm["crb.error-type"].template as<int>() ).str(),
253  name,
254  ( boost::format( "%1%-%2%-%3%" ) % name % vm["crb.output-index"].template as<int>() % vm["crb.error-type"].template as<int>() ).str(),
255  vm ),
256  M_elements_database(
257  ( boost::format( "%1%" ) % vm["crb.error-type"].template as<int>() ).str(),
258  name,
259  ( boost::format( "%1%-%2%-%3%-elements" ) % name % vm["crb.output-index"].template as<int>() % vm["crb.error-type"].template as<int>() ).str(),
260  vm ),
261  M_nlsolver( SolverNonLinear<double>::build( SOLVERS_PETSC, Environment::worldComm() ) ),
262  M_model(),
263  M_backend( backend_type::build( vm ) ),
264  M_backend_primal( backend_type::build( vm ) ),
265  M_backend_dual( backend_type::build( vm ) ),
266  M_output_index( vm["crb.output-index"].template as<int>() ),
267  M_tolerance( vm["crb.error-max"].template as<double>() ),
268  M_iter_max( vm["crb.dimension-max"].template as<int>() ),
269  M_factor( vm["crb.factor"].template as<int>() ),
270  M_error_type( CRBErrorType( vm["crb.error-type"].template as<int>() ) ),
271  M_Dmu( new parameterspace_type ),
272  M_Xi( new sampling_type( M_Dmu ) ),
273  M_WNmu( new sampling_type( M_Dmu, 1, M_Xi ) ),
274  M_WNmu_complement(),
275  M_scmA( new scm_type( name+"_a", vm ) ),
276  M_scmM( new scm_type( name+"_m", vm ) ),
277  exporter( Exporter<mesh_type>::New( vm, "BasisFunction" ) )
278  {
279  // this is too early to load the DB, we don't have the model yet and the
280  //associated function space for the reduced basis function if
281  // do the loadDB() in setTruthModel()
282  //this->loadDB() )
283 
284  }
285 
287  CRB( std::string name,
288  po::variables_map const& vm,
289  truth_model_ptrtype const & model )
290  :
291  super( ( boost::format( "%1%" ) % vm["crb.error-type"].template as<int>() ).str(),
292  name,
293  ( boost::format( "%1%-%2%-%3%" ) % name % vm["crb.output-index"].template as<int>() % vm["crb.error-type"].template as<int>() ).str(),
294  vm ),
295  M_elements_database(
296  ( boost::format( "%1%" ) % vm["crb.error-type"].template as<int>() ).str(),
297  name,
298  ( boost::format( "%1%-%2%-%3%-elements" ) % name % vm["crb.output-index"].template as<int>() % vm["crb.error-type"].template as<int>() ).str(),
299  vm ,
300  model ),
301  M_nlsolver( SolverNonLinear<double>::build( SOLVERS_PETSC, Environment::worldComm() ) ),
302  M_model(),
303  M_backend( backend_type::build( vm ) ),
304  M_backend_primal( backend_type::build( vm ) ),
305  M_backend_dual( backend_type::build( vm ) ),
306  M_output_index( vm["crb.output-index"].template as<int>() ),
307  M_tolerance( vm["crb.error-max"].template as<double>() ),
308  M_iter_max( vm["crb.dimension-max"].template as<int>() ),
309  M_factor( vm["crb.factor"].template as<int>() ),
310  M_error_type( CRBErrorType( vm["crb.error-type"].template as<int>() ) ),
311  M_Dmu( new parameterspace_type ),
312  M_Xi( new sampling_type( M_Dmu ) ),
313  M_WNmu( new sampling_type( M_Dmu, 1, M_Xi ) ),
314  M_WNmu_complement(),
315  M_scmA( new scm_type( name+"_a", vm , model , false /*not scm for mass mastrix*/ ) ),
316  M_scmM( new scm_type( name+"_m", vm , model , true /*scm for mass matrix*/ ) ),
317  exporter( Exporter<mesh_type>::New( vm, "BasisFunction" ) )
318  {
319  this->setTruthModel( model );
320  if ( this->loadDB() )
321  LOG(INFO) << "Database " << this->lookForDB() << " available and loaded\n";
322  M_elements_database.setMN( M_N );
323  if( M_elements_database.loadDB() )
324  LOG(INFO) << "Element Database " << M_elements_database.lookForDB() << " available and loaded\n";
325  auto basis_functions = M_elements_database.wn();
326  M_WN = basis_functions.template get<0>();
327  M_WNdu = basis_functions.template get<1>();
328 
329  M_preconditioner_primal = preconditioner(_pc=(PreconditionerType) M_backend_primal->pcEnumType(), // by default : lu in seq or wirh mumps, else gasm in parallel
330  _backend= M_backend_primal,
331  _pcfactormatsolverpackage=(MatSolverPackageType) M_backend_primal->matSolverPackageEnumType(),// mumps if is installed ( by defaut )
332  _worldcomm=M_backend_primal->comm(),
333  _prefix=M_backend_primal->prefix() ,
334  _rebuild=true);
335  M_preconditioner_dual = preconditioner(_pc=(PreconditionerType) M_backend_dual->pcEnumType(), // by default : lu in seq or wirh mumps, else gasm in parallel
336  _backend= M_backend_dual,
337  _pcfactormatsolverpackage=(MatSolverPackageType) M_backend_dual->matSolverPackageEnumType(),// mumps if is installed ( by defaut )
338  _worldcomm=M_backend_dual->comm(),
339  _prefix=M_backend_dual->prefix() ,
340  _rebuild=true);
341  }
342 
343 
345  CRB( CRB const & o )
346  :
347  super( o ),
348  M_elements_database( o.M_elements_database ),
349  M_nlsolver( o.M_nlsolver ),
350  M_output_index( o.M_output_index ),
351  M_tolerance( o.M_tolerance ),
352  M_iter_max( o.M_iter_max ),
353  M_factor( o.M_factor ),
354  M_error_type( o.M_error_type ),
355  M_maxerror( o.M_maxerror ),
356  M_Dmu( o.M_Dmu ),
357  M_Xi( o.M_Xi ),
358  M_WNmu( o.M_WNmu ),
359  M_WNmu_complement( o.M_WNmu_complement ),
360  M_C0_pr( o.M_C0_pr ),
361  M_C0_du( o.M_C0_du ),
362  M_Lambda_pr( o.M_Lambda_pr ),
363  M_Lambda_du( o.M_Lambda_du ),
364  M_Gamma_pr( o.M_Gamma_pr ),
365  M_Gamma_du( o.M_Gamma_du ),
366  M_Cmf_pr( o.M_Cmf_pr ),
367  M_Cmf_du( o.M_Cmf_du ),
368  M_Cmf_du_ini( o.M_Cmf_du_ini ),
369  M_Cma_pr( o.M_Cma_pr ),
370  M_Cma_du( o.M_Cma_du ),
371  M_Cmm_pr( o.M_Cmm_pr ),
372  M_Cmm_du( o.M_Cmm_du ),
373  M_coeff_pr_ini_online( o.M_coeff_pr_ini_online ),
374  M_coeff_du_ini_online( o.M_coeff_du_ini_online )
375  {}
376 
379  {}
380 
381 
383 
387 
389  CRB& operator=( CRB const & o )
390  {
391  if ( this != &o )
392  {
393  }
394 
395  return *this;
396  }
398 
402 
403 
405  int factor() const
406  {
407  return factor;
408  }
410  int maxIter() const
411  {
412  return M_iter_max;
413  }
414 
416  parameterspace_ptrtype Dmu() const
417  {
418  return M_Dmu;
419  }
420 
422  int outputIndex() const
423  {
424  return M_output_index;
425  }
426 
428  int dimension() const
429  {
430  return M_N;
431  }
432 
434  sampling_ptrtype trainSampling() const
435  {
436  return M_Xi;
437  }
438 
441  {
442  return M_error_type;
443  }
444 
446  scm_ptrtype scm() const
447  {
448  return M_scmA;
449  }
450 
451  void loadSCMDB();
452 
454 
458 
460  void setOutputIndex( uint16_type oindex )
461  {
462  int M_prev_o = M_output_index;
463  M_output_index = oindex;
464 
465  if ( ( size_type )M_output_index >= M_model->Nl() )
466  M_output_index = M_prev_o;
467 
468  //std::cout << " -- crb set output index to " << M_output_index << " (max output = " << M_model->Nl() << ")\n";
469  this->setDBFilename( ( boost::format( "%1%-%2%-%3%.crbdb" ) % this->name() % M_output_index % M_error_type ).str() );
470 
471  if ( M_output_index != M_prev_o )
472  this->loadDB();
473 
474  //std::cout << "Database " << this->lookForDB() << " available and loaded\n";
475 
476  }
477 
480  {
481  M_error_type = error;
482  }
483 
485  void setTolerance( double tolerance )
486  {
487  M_tolerance = tolerance;
488  }
489 
491  void setTruthModel( truth_model_ptrtype const& model )
492  {
493  M_model = model;
494  M_Dmu = M_model->parameterSpace();
495  M_Xi = sampling_ptrtype( new sampling_type( M_Dmu ) );
496 
497  if ( ! loadDB() )
498  M_WNmu = sampling_ptrtype( new sampling_type( M_Dmu ) );
499  else
500  {
501  LOG(INFO) << "Database " << this->lookForDB() << " available and loaded\n";
502  }
503 
504  //M_scmA->setTruthModel( M_model );
505  //M_scmM->setTruthModel( M_model );
506  }
507 
509  void setMaxIter( int K )
510  {
511  M_iter_max = K;
512  }
513 
515  void setFactor( int Factor )
516  {
517  M_factor = Factor;
518  }
519 
521  void setOfflineStep( bool b )
522  {
523  M_offline_step = b;
524  }
525 
526  struct ComputePhi
527  {
528 
529  ComputePhi( wn_type v)
530  :
531  M_curs( 0 ),
532  M_vect( v )
533  {}
534 
535  template< typename T >
536  void
537  operator()( const T& t ) const
538  {
539  mesh_ptrtype mesh = t.functionSpace()->mesh();
540  double surface = integrate( _range=elements(mesh), _expr=vf::cst(1.) ).evaluate()(0,0);
541  double mean = integrate( _range=elements(mesh), _expr=vf::idv( t ) ).evaluate()(0,0);
542  mean /= surface;
543  auto element_mean = vf::project(t.functionSpace(), elements(mesh), vf::cst(mean) );
544  auto element_t = vf::project(t.functionSpace(), elements(mesh), vf::idv(t) );
545  int first_dof = t.start();
546  int nb_dof = t.functionSpace()->nLocalDof();
547  for(int dof=0 ; dof<nb_dof; dof++)
548  M_vect[M_curs][first_dof + dof] = element_t[dof] - element_mean[dof];
549 
550  ++M_curs;
551  }
552 
553  wn_type vectorPhi()
554  {
555  return M_vect;
556  }
557  mutable int M_curs;
558  mutable wn_type M_vect;
559  };
560 
561 
562  struct ComputeIntegrals
563  {
564 
565  ComputeIntegrals( element_type const composite_e1 ,
566  element_type const composite_e2 )
567  :
568  M_composite_e1 ( composite_e1 ),
569  M_composite_e2 ( composite_e2 )
570  {}
571 
572  template< typename T >
573  void
574  operator()( const T& t ) const
575  {
576  auto e1 = M_composite_e1.template element< T::value >();
577  auto e2 = M_composite_e2.template element< T::value >();
578  mesh_ptrtype mesh = e1.functionSpace()->mesh();
579  double integral = integrate( _range=elements(mesh) , _expr=trans( vf::idv( e1 ) ) * vf::idv( e2 ) ).evaluate()(0,0);
580 
581  M_vect.push_back( integral );
582  }
583 
584  std::vector< double > vectorIntegrals()
585  {
586  return M_vect;
587  }
588 
589  mutable std::vector< double > M_vect;
590  element_type M_composite_e1;
591  element_type M_composite_e2;
592  };
593 
594  struct ComputeIntegralsSquare
595  {
596 
597  ComputeIntegralsSquare( element_type const composite_e1 ,
598  element_type const composite_e2 )
599  :
600  M_composite_e1 ( composite_e1 ),
601  M_composite_e2 ( composite_e2 )
602  {}
603 
604  template< typename T >
605  void
606  operator()( const T& t ) const
607  {
608  int i = T::value;
609  if( i == 0 )
610  M_error.resize( 1 );
611  else
612  M_error.conservativeResize( i+1 );
613 
614  auto e1 = M_composite_e1.template element< T::value >();
615  auto e2 = M_composite_e2.template element< T::value >();
616 
617  auto Xh = M_composite_e1.functionSpace();
618  mesh_ptrtype mesh = Xh->mesh();
619  double integral = integrate( _range=elements(mesh) ,
620  _expr=trans( vf::idv( e1 ) - vf::idv( e2 ) )
621  * ( vf::idv( e1 ) - vf::idv( e2 ) )
622  ).evaluate()(0,0);
623  M_error(i) = math::sqrt( integral ) ;
624  }
625 
626  vectorN_type vectorErrors()
627  {
628  return M_error;
629  }
630 
631  mutable vectorN_type M_error;
632  element_type M_composite_e1;
633  element_type M_composite_e2;
634  };
635 
637 
641 
646  double orthonormalize( size_type N, wn_type& wn, int Nm = 1 );
647 
648  void checkResidual( parameter_type const& mu, std::vector< std::vector<double> > const& primal_residual_coeffs,
649  std::vector< std::vector<double> > const& dual_residual_coeffs , element_type & u, element_type & udu ) const;
650 
651  void compareResidualsForTransientProblems(int N, parameter_type const& mu, std::vector<element_type> const & Un,
652  std::vector<element_type> const & Unold, std::vector<element_type> const& Undu,
653  std::vector<element_type> const & Unduold,
654  std::vector< std::vector<double> > const& primal_residual_coeffs,
655  std::vector< std::vector<double> > const& dual_residual_coeffs ) const ;
656 
657 
658  void buildFunctionFromRbCoefficients(int N, std::vector< vectorN_type > const & RBcoeff, wn_type const & WN, std::vector<element_ptrtype> & FEMsolutions );
659 
660  /*
661  * check orthonormality
662  * return the norm of the matrix A(i,j)=M_model->scalarProduct( WN[j], WN[i] ), should be 0
663  */
664  double checkOrthonormality( int N, const wn_type& wn ) const;
665 
670  void check( size_type N ) const;
671 
681  void computeErrorEstimationEfficiencyIndicator ( parameterspace_ptrtype const& Dmu, double& max_ei, double& min_ei,int N = 4 );
682 
683 
688  void exportBasisFunctions( const export_vector_wn_type& wn )const ;
689 
704  // boost::tuple<double,double> lb( size_type N, parameter_type const& mu, std::vector< vectorN_type >& uN, std::vector< vectorN_type >& uNdu , std::vector<vectorN_type> & uNold=std::vector<vectorN_type>(), std::vector<vectorN_type> & uNduold=std::vector<vectorN_type>(), int K=0) const;
705  boost::tuple<double,double> lb( size_type N, parameter_type const& mu, std::vector< vectorN_type >& uN, std::vector< vectorN_type >& uNdu , std::vector<vectorN_type> & uNold, std::vector<vectorN_type> & uNduold, int K=0 ) const;
706 
707  /*
708  * update the jacobian
709  * \param map_X : solution
710  * \param map_J : jacobian
711  * \param mu : current parameter
712  * \param N : dimension of the reduced basis
713  */
714  void updateJacobian( const map_dense_vector_type& map_X, map_dense_matrix_type& map_J , const parameter_type & mu , int N) const ;
715 
716  /*
717  * update the residual
718  * \param map_X : solution
719  * \param map_R : residual
720  * \param mu : current parameter
721  * \param N : dimension of the reduced basis
722  */
723  void updateResidual( const map_dense_vector_type& map_X, map_dense_vector_type& map_R , const parameter_type & mu, int N ) const ;
724 
725  /*
726  * compute the projection of the initial guess
727  * \param mu : current parameter
728  * \param N : dimension of the reduced basis
729  * \param initial guess
730  */
731  void computeProjectionInitialGuess( const parameter_type & mu, int N , vectorN_type& initial_guess ) const ;
732 
733  /*
734  * newton algorithm to solve non linear problem
735  * \param N : dimension of the reduced basis
736  * \param mu : current parameter
737  * \param uN : reduced solution ( vectorN_type )
738  * \param condition number of the reduced jacobian
739  */
740  void newton( size_type N, parameter_type const& mu , vectorN_type & uN , double& condition_number, double& output) const ;
741 
742  /*
743  * fixed point for primal problem ( offline step )
744  * \param mu : current parameter
745  * \param A : matrix of the bilinear form (fill the matrix)
746  * \param zero_iteration : don't perfom iterations if true ( for linear problems for example )
747  */
748  element_type offlineFixedPointPrimal( parameter_type const& mu, sparse_matrix_ptrtype & A, bool zero_iteration ) ;
749 
750  /*
751  * \param mu : current parameter
752  * \param dual_initial_field : to be filled
753  * \param A : matrix of the primal problem, needed only to check dual properties
754  * \param u : solution of the primal problem, needed only to check dual properties
755  * \param zero_iteration : don't perfom iterations if true ( for linear problems for example )
756  */
757  element_type offlineFixedPointDual( parameter_type const& mu , element_ptrtype & dual_initial_field, const sparse_matrix_ptrtype & A, const element_type & u, bool zero_iteration ) ;
758 
759  /*
760  * fixed point ( primal problem ) - ONLINE step
761  * \param N : dimension of the reduced basis
762  * \param mu :current parameter
763  * \param uN : dual reduced solution ( vectorN_type )
764  * \param uNold : dual old reduced solution ( vectorN_type )
765  * \param condition number of the reduced matrix A
766  * \param output : vector of outpus at each time step
767  * \param K : number of time step ( default value, must be >0 if used )
768  */
769  void fixedPointPrimal( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uN, std::vector<vectorN_type> & uNold, double& condition_number,
770  std::vector< double > & output_vector, int K=0) const;
771 
772  /*
773  * fixed point ( dual problem ) - ONLINE step
774  * \param N : dimension of the reduced basis
775  * \param mu :current parameter
776  * \param uNdu : dual reduced solution ( vectorN_type )
777  * \param uNduold : dual old reduced solution ( vectorN_type )
778  * \param output : vector of outpus at each time step
779  * \param K : number of time step ( default value, must be >0 if used )
780  */
781  void fixedPointDual( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uNdu, std::vector<vectorN_type> & uNduold, std::vector< double > & output_vector, int K=0) const;
782 
794  void fixedPoint( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uN, std::vector< vectorN_type > & uNdu, std::vector<vectorN_type> & uNold, std::vector<vectorN_type> & uNduold,
795  double& condition_number, std::vector< double > & output_vector, int K=0) const;
796 
801  double computeConditioning( matrixN_type & A ) const ;
802 
803 
814  boost::tuple<double,double> lb( parameter_ptrtype const& mu, size_type N, std::vector< vectorN_type >& uN, std::vector< vectorN_type >& uNdu ) const
815  {
816  return lb( N, *mu, uN, uNdu );
817  }
818 
831  value_type ub( size_type N, parameter_type const& mu, std::vector< vectorN_type >& uN, std::vector< vectorN_type >& uNdu ) const
832  {
833  auto o = lb( N, mu, uN, uNdu );
834  auto e = delta( N, mu, uN, uNdu );
835  return o.template get<0>() + e.template get<0>();
836  }
837 
848  value_type delta( size_type N, parameter_ptrtype const& mu, std::vector< vectorN_type > const& uN, std::vector< vectorN_type > const& uNdu, std::vector<vectorN_type> const& uNold, std::vector<vectorN_type> const& uNduold , int k=0 ) const
849  {
850  auto e = delta( N, mu, uN, uNdu );
851  return e.template get<0>();
852  }
853 
864  error_estimation_type delta( size_type N, parameter_type const& mu, std::vector< vectorN_type > const& uN, std::vector< vectorN_type > const& uNdu, std::vector<vectorN_type> const& uNold, std::vector<vectorN_type> const& uNduold, int k=0 ) const;
865 
874  value_type ub( size_type K, parameter_ptrtype const& mu, std::vector< vectorN_type >& uN, std::vector< vectorN_type >& uNdu ) const
875  {
876  return ub( K, *mu, uN, uNdu );
877  }
878 
884  convergence_type offline();
885 
886 
891  max_error_type maxErrorBounds( size_type N ) const;
892 
897  residual_error_type transientPrimalResidual( int Ncur, parameter_type const& mu, vectorN_type const& Un, vectorN_type const& Unold=vectorN_type(), double time_step=1, double time=1e30 ) const;
898  residual_error_type steadyPrimalResidual( int Ncur, parameter_type const& mu, vectorN_type const& Un, double time=0 ) const;
899 
900 
901  residual_error_type transientDualResidual( int Ncur, parameter_type const& mu, vectorN_type const& Un, vectorN_type const& Unold=vectorN_type(), double time_step=1, double time=1e30 ) const;
902  residual_error_type steadyDualResidual( int Ncur, parameter_type const& mu, vectorN_type const& Un, double time=0 ) const;
903 
904 
905  value_type initialDualResidual( int Ncur, parameter_type const& mu, vectorN_type const& Uduini, double time_step ) const ;
906 
907 
911  void offlineResidual( int Ncur , int number_of_added_elements=1 );
912  void offlineResidual( int Ncur, mpl::bool_<true> ,int number_of_added_elements=1 );
913  void offlineResidual( int Ncur, mpl::bool_<false> , int number_of_added_elements=1 );
914 
915  /*
916  * compute empirical error estimation, ie : |S_n - S{n-1}|
917  * \param Ncur : number of elements in the reduced basis <=> M_N
918  * \param mu : parameters value (one value per parameter)
919  * \output : empirical error estimation
920  */
921  value_type empiricalErrorEstimation ( int Ncur, parameter_type const& mu, int k ) const ;
922 
923 
930  element_type expansion( parameter_type const& mu , int N=-1, int time_index=-1);
931 
937  element_type expansion( vectorN_type const& u , int const N, wn_type const & WN ) const;
938 
939 
940  void checkInitialGuess( const element_type expansion_uN , parameter_type const& mu, vectorN_type & error ) const ;
941  void checkInitialGuess( const element_type expansion_uN , parameter_type const& mu, vectorN_type & error , mpl::bool_<true> ) const ;
942  void checkInitialGuess( const element_type expansion_uN , parameter_type const& mu, vectorN_type & error , mpl::bool_<false> ) const ;
943 
947  //boost::tuple<double,double,double> run( parameter_type const& mu, double eps = 1e-6 );
948  //boost::tuple<double,double,double,double> run( parameter_type const& mu, double eps = 1e-6 );
949  //by default N=-1 so we take dimension-max but if N>0 then we take N basis functions toperform online step
950  boost::tuple<double,double, solutions_tuple, double, double, double, upper_bounds_tuple > run( parameter_type const& mu, double eps = 1e-6, int N = -1 );
951 
955  void run( const double * X, unsigned long N, double * Y, unsigned long P );
956  void run( const double * X, unsigned long N, double * Y, unsigned long P, mpl::bool_<true> );
957  void run( const double * X, unsigned long N, double * Y, unsigned long P, mpl::bool_<false> );
958 
963  {
964  M_Xi->randomize( N );
965  return *M_Xi;
966  }
967 
972  {
973  M_Xi->equidistribute( N );
974  return *M_Xi;
975  }
976 
977  sampling_ptrtype wnmu ( ) const
978  {
979  return M_WNmu;
980  }
981 
982  wn_type wn() const
983  {
984  return M_WN;
985  }
986 
987  wn_type wndu() const
988  {
989  return M_WNdu;
990  }
991 
995  void saveDB();
996 
1000  bool loadDB();
1001 
1008  void projectionOnPodSpace( const element_type & u , element_ptrtype& projection ,const std::string& name_of_space="primal" );
1009 
1010 
1011  bool useWNmu()
1012  {
1013  bool use = this->vm()["crb.run-on-WNmu"].template as<bool>();
1014  return use;
1015  }
1016 
1017 
1021  bool rebuildDB() ;
1022 
1026  bool showMuSelection() ;
1027 
1032 
1036  void printMuSelection( void );
1037 
1042  void printErrorsDuringRbConstruction( void );
1043  /*
1044  * compute correction terms for output
1045  * \param mu \f$ \mu\f$ the parameter at which to evaluate the output
1046  * \param uN : primal solution
1047  * \param uNdu : dual solution
1048  * \pram uNold : old primal solution
1049  * \param K : time index
1050  */
1051  double correctionTerms(parameter_type const& mu, std::vector< vectorN_type > const & uN, std::vector< vectorN_type > const & uNdu , std::vector<vectorN_type> const & uNold, int const K=0) const;
1052 
1053  /*
1054  * build matrix to store functions used to compute the variance output
1055  * \param N : number of elements in the reduced basis
1056  */
1057  void buildVarianceMatrixPhi(int const N);
1058  void buildVarianceMatrixPhi(int const N , mpl::bool_<true> );
1059  void buildVarianceMatrixPhi(int const N , mpl::bool_<false> );
1060 
1061  WorldComm const& worldComm() const { return Environment::worldComm() ; }
1062 
1066  void computationalTimeStatistics( std::string appname );
1067 
1069 
1070 
1071 private:
1072  crb_elements_db_type M_elements_database;
1073 
1074  boost::shared_ptr<SolverNonLinear<double> > M_nlsolver;
1075 
1076  truth_model_ptrtype M_model;
1077 
1078  backend_ptrtype M_backend;
1079  backend_ptrtype M_backend_primal;
1080  backend_ptrtype M_backend_dual;
1081 
1082  int M_output_index;
1083 
1084  double M_tolerance;
1085 
1086  size_type M_iter_max;
1087 
1088  int M_factor;
1089 
1090  CRBErrorType M_error_type;
1091 
1092  double M_maxerror;
1093 
1094  // parameter space
1095  parameterspace_ptrtype M_Dmu;
1096 
1097  // fine sampling of the parameter space
1098  sampling_ptrtype M_Xi;
1099 
1100  // sampling of parameter space to build WN
1101  sampling_ptrtype M_WNmu;
1102  sampling_ptrtype M_WNmu_complement;
1103 
1104  //scm
1105  scm_ptrtype M_scmA;
1106  scm_ptrtype M_scmM;
1107 
1108  //export
1109  export_ptrtype exporter;
1110 
1111 #if 0
1112  array_2_type M_C0_pr;
1113  array_2_type M_C0_du;
1114  array_3_type M_Lambda_pr;
1115  array_3_type M_Lambda_du;
1116  array_4_type M_Gamma_pr;
1117  array_4_type M_Gamma_du;
1118  array_3_type M_Cmf_pr;
1119  array_3_type M_Cmf_du;
1120  array_4_type M_Cma_pr;
1121  array_4_type M_Cma_du;
1122  array_4_type M_Cmm_pr;
1123  array_4_type M_Cmm_du;
1124 #endif
1125  std::vector< std::vector< std::vector< std::vector< double > > > > M_C0_pr;
1126  std::vector< std::vector< std::vector< std::vector< double > > > > M_C0_du;
1127  std::vector< std::vector< std::vector< std::vector< vectorN_type > > > > M_Lambda_pr;
1128  std::vector< std::vector< std::vector< std::vector< vectorN_type > > > > M_Lambda_du;
1129  std::vector< std::vector< std::vector< std::vector< matrixN_type > > > > M_Gamma_pr;
1130  std::vector< std::vector< std::vector< std::vector< matrixN_type > > > > M_Gamma_du;
1131  std::vector< std::vector< std::vector< std::vector< vectorN_type > > > > M_Cmf_pr;
1132  std::vector< std::vector< std::vector< std::vector< vectorN_type > > > > M_Cmf_du;
1133  std::vector< std::vector< std::vector< std::vector< vectorN_type > > > > M_Cmf_du_ini;
1134  std::vector< std::vector< std::vector< std::vector< matrixN_type > > > > M_Cma_pr;
1135  std::vector< std::vector< std::vector< std::vector< matrixN_type > > > > M_Cma_du;
1136  std::vector< std::vector< std::vector< std::vector< matrixN_type > > > > M_Cmm_pr;
1137  std::vector< std::vector< std::vector< std::vector< matrixN_type > > > > M_Cmm_du;
1138 
1139 
1140  std::vector<double> M_coeff_pr_ini_online;
1141  std::vector<double> M_coeff_du_ini_online;
1142 
1143 
1144  friend class boost::serialization::access;
1145  // When the class Archive corresponds to an output archive, the
1146  // & operator is defined similar to <<. Likewise, when the class Archive
1147  // is a type of input archive the & operator is defined similar to >>.
1148  template<class Archive>
1149  void save( Archive & ar, const unsigned int version ) const;
1150 
1151  template<class Archive>
1152  void load( Archive & ar, const unsigned int version ) ;
1153 
1154  BOOST_SERIALIZATION_SPLIT_MEMBER()
1155 
1156  // reduced basis space
1157  wn_type M_WN;
1158  wn_type M_WNdu;
1159 
1160  size_type M_N;
1161  size_type M_Nm;
1162 
1163  bool orthonormalize_primal;
1164  bool orthonormalize_dual;
1165  bool solve_dual_problem;
1166 
1167  convergence_type M_rbconv;
1168 
1169  //time
1170  bdf_ptrtype M_bdf_primal;
1171  bdf_ptrtype M_bdf_primal_save;
1172  bdf_ptrtype M_bdf_dual;
1173  bdf_ptrtype M_bdf_dual_save;
1174 
1175  // left hand side
1176  std::vector < std::vector<matrixN_type> > M_Aqm_pr;
1177  std::vector < std::vector<matrixN_type> > M_Aqm_du;
1178  std::vector < std::vector<matrixN_type> > M_Aqm_pr_du;
1179 
1180  //jacobian
1181  std::vector < std::vector<matrixN_type> > M_Jqm_pr;
1182 
1183  //residual
1184  std::vector < std::vector<vectorN_type> > M_Rqm_pr;
1185 
1186  //mass matrix
1187  std::vector < std::vector<matrixN_type> > M_Mqm_pr;
1188  std::vector < std::vector<matrixN_type> > M_Mqm_du;
1189  std::vector < std::vector<matrixN_type> > M_Mqm_pr_du;
1190 
1191  // right hand side
1192  std::vector < std::vector<vectorN_type> > M_Fqm_pr;
1193  std::vector < std::vector<vectorN_type> > M_Fqm_du;
1194  // output
1195  std::vector < std::vector<vectorN_type> > M_Lqm_pr;
1196  std::vector < std::vector<vectorN_type> > M_Lqm_du;
1197 
1198  //initial guess
1199  std::vector < std::vector<vectorN_type> > M_InitialGuessV_pr;
1200 
1201  std::vector<int> M_index;
1202  int M_mode_number;
1203 
1204  std::vector < matrixN_type > M_variance_matrix_phi;
1205 
1206  bool M_compute_variance;
1207  bool M_rbconv_contains_primal_and_dual_contributions;
1208  parameter_type M_current_mu;
1209  int M_no_residual_index;
1210 
1211  bool M_database_contains_variance_info;
1212 
1213  bool M_use_newton;
1214 
1215  bool M_offline_step;
1216 
1217  preconditioner_ptrtype M_preconditioner;
1218  preconditioner_ptrtype M_preconditioner_primal;
1219  preconditioner_ptrtype M_preconditioner_dual;
1220 
1221 };
1222 
1223 po::options_description crbOptions( std::string const& prefix = "" );
1224 
1225 
1226 
1227 
1228 template<typename TruthModelType>
1229 typename CRB<TruthModelType>::element_type
1230 CRB<TruthModelType>::offlineFixedPointPrimal(parameter_type const& mu, sparse_matrix_ptrtype & A, bool zero_iteration )
1231 {
1232  auto u = M_model->functionSpace()->element();
1233 
1234  sparse_matrix_ptrtype M = M_model->newMatrix();
1235  int nl = M_model->Nl(); //number of outputs
1236  std::vector< vector_ptrtype > F( nl );
1237  for(int l=0; l<nl; l++)
1238  F[l]=M_model->newVector();
1239 
1240  M_backend_primal = backend_type::build( BACKEND_PETSC );
1241  bool reuse_prec = this->vm()["crb.reuse-prec"].template as<bool>() ;
1242 
1243  M_bdf_primal = bdf( _space=M_model->functionSpace(), _vm=this->vm() , _name="bdf_primal" );
1244  M_bdf_primal_save = bdf( _space=M_model->functionSpace(), _vm=this->vm() , _name="bdf_primal_save" );
1245 
1246  //set parameters for time discretization
1247  M_bdf_primal->setTimeInitial( M_model->timeInitial() );
1248  M_bdf_primal->setTimeStep( M_model->timeStep() );
1249  M_bdf_primal->setTimeFinal( M_model->timeFinal() );
1250  M_bdf_primal->setOrder( M_model->timeOrder() );
1251 
1252  M_bdf_primal_save->setTimeInitial( M_model->timeInitial() );
1253  M_bdf_primal_save->setTimeStep( M_model->timeStep() );
1254  M_bdf_primal_save->setTimeFinal( M_model->timeFinal() );
1255  M_bdf_primal_save->setOrder( M_model->timeOrder() );
1256 
1257  M_bdf_primal_save->setRankProcInNameOfFiles( true );
1258  M_bdf_primal->setRankProcInNameOfFiles( true );
1259 
1260  //initialization of unknown
1261  auto elementptr = M_model->functionSpace()->elementPtr();
1262  M_model->initializationField( elementptr, mu );
1263 
1264  u = *elementptr;
1265 
1266  auto Apr = M_model->newMatrix();
1267 
1268 
1269  int max_fixedpoint_iterations = option(_name="crb.max-fixedpoint-iterations").template as<int>();
1270  double increment_fixedpoint_tol = option(_name="crb.increment-fixedpoint-tol").template as<double>();
1271  double fixedpoint_critical_value = option(_name="crb.fixedpoint-critical-value").template as<double>();
1272  int iteration=0;
1273  double increment_norm=1e3;
1274 
1275  if( zero_iteration )
1276  increment_norm = 0;
1277 
1278  double bdf_coeff;
1279 
1280  auto vec_bdf_poly = M_backend_primal->newVector( M_model->functionSpace() );
1281 
1282  //assemble the initial guess for the given mu
1283  if ( M_model->isSteady() )
1284  {
1285  elementptr = M_model->assembleInitialGuess( mu ) ;
1286  u = *elementptr ;
1287  }
1288 
1289  auto uold = M_model->functionSpace()->element();
1290 
1291  element_ptrtype uproj( new element_type( M_model->functionSpace() ) );
1292 
1293  vector_ptrtype Rhs( M_backend_primal->newVector( M_model->functionSpace() ) );
1294 
1295  for ( M_bdf_primal->start(u),M_bdf_primal_save->start(u);
1296  !M_bdf_primal->isFinished() , !M_bdf_primal_save->isFinished();
1297  M_bdf_primal->next() , M_bdf_primal_save->next() )
1298  {
1299 
1300  bdf_coeff = M_bdf_primal->polyDerivCoefficient( 0 );
1301 
1302  auto bdf_poly = M_bdf_primal->polyDeriv();
1303 
1304  do
1305  {
1306  boost::tie( M, Apr, F) = M_model->update( mu , u, M_bdf_primal->time() );
1307  //boost::tie( M, Apr, F) = M_model->update( mu , M_bdf_primal->time() );
1308 
1309  if( iteration == 0 )
1310  A = Apr;
1311 
1312  if ( ! M_model->isSteady() )
1313  {
1314  Apr->addMatrix( bdf_coeff, M );
1315  *Rhs = *F[0];
1316  *vec_bdf_poly = bdf_poly;
1317  Rhs->addVector( *vec_bdf_poly, *M );
1318  }
1319  else
1320  *Rhs = *F[0];
1321  //Apr->close();
1322 
1323  //backup for non linear problems
1324  uold = u;
1325 
1326  //solve
1327  M_preconditioner_primal->setMatrix( Apr );
1328  if ( reuse_prec )
1329  {
1330  auto ret = M_backend_primal->solve( _matrix=Apr, _solution=u, _rhs=Rhs, _prec=M_preconditioner_primal, _reuse_prec=( M_bdf_primal->iteration() >=2 ) );
1331  if ( !ret.template get<0>() )
1332  LOG(INFO)<<"[CRB] WARNING : at time "<<M_bdf_primal->time()<<" we have not converged ( nb_it : "<<ret.template get<1>()<<" and residual : "<<ret.template get<2>() <<" ) \n";
1333  }
1334  else
1335  {
1336 
1337  auto ret = M_backend_primal->solve( _matrix=Apr, _solution=u, _rhs=Rhs , _prec=M_preconditioner_primal );
1338  if ( !ret.template get<0>() )
1339  LOG(INFO)<<"[CRB] WARNING : at time "<<M_bdf_primal->time()<<" we have not converged ( nb_it : "<<ret.template get<1>()<<" and residual : "<<ret.template get<2>() <<" ) \n";
1340  }
1341 
1342  //on each subspace the norme of the increment is computed and then we perform the sum
1343  increment_norm = M_model->computeNormL2( u , uold );
1344  iteration++;
1345 
1346  }while( increment_norm > increment_fixedpoint_tol && iteration < max_fixedpoint_iterations );
1347 
1348  M_bdf_primal->shiftRight( u );
1349 
1350  if ( ! M_model->isSteady() )
1351  {
1352  element_ptrtype projection ( new element_type ( M_model->functionSpace() ) );
1353  projectionOnPodSpace ( u , projection, "primal" );
1354  *uproj=u;
1355  M_bdf_primal_save->shiftRight( *uproj );
1356  }
1357 
1358  if( increment_norm > fixedpoint_critical_value )
1359  throw std::logic_error( (boost::format("[CRB::offlineFixedPointPrimal] at time %1% ERROR : increment > critical value " ) %M_bdf_primal->time() ).str() );
1360 
1361  for ( size_type l = 0; l < M_model->Nl(); ++l )
1362  {
1363  F[l]->close();
1364  element_ptrtype eltF( new element_type( M_model->functionSpace() ) );
1365  *eltF = *F[l];
1366  LOG(INFO) << "u^T F[" << l << "]= " << inner_product( u, *eltF ) << " at time : "<<M_bdf_primal->time()<<"\n";
1367  }
1368  LOG(INFO) << "[CRB::offlineWithErrorEstimation] energy = " << A->energy( u, u ) << "\n";
1369 
1370  }//end of loop over time
1371 
1372  return u;
1373 #if 0
1374  //*u = M_model->solve( mu );
1375  do
1376  {
1377  //merge all matrices/vectors contributions from affine decomposition
1378  //result : a tuple : M , A and F
1379  auto merge = M_model->update( mu );
1380  A = merge.template get<1>();
1381  F = merge.template get<2>();
1382  //backup
1383  uold = un;
1384 
1385  //solve
1386  //M_backend->solve( _matrix=A , _solution=un, _rhs=F[0]);
1387  M_preconditioner_primal->setMatrix( A );
1388  M_backend_primal->solve( _matrix=A , _solution=un, _rhs=F[0] , _prec=M_preconditioner );
1389 
1390  //on each subspace the norme of the increment is computed and then we perform the sum
1391  increment_norm = M_model->computeNormL2( un , uold );
1392  iteration++;
1393 
1394  } while( increment_norm > increment_fixedpoint_tol && iteration < max_fixedpoint_iterations );
1395 
1396  element_ptrtype eltF( new element_type( M_model->functionSpace() ) );
1397  *eltF = *F[0];
1398  LOG(INFO) << "[CRB::offlineFixedPoint] u^T F = " << inner_product( *u, *eltF ) ;
1399  LOG(INFO) << "[CRB::offlineFixedPoint] energy = " << A->energy( *u, *u ) ;
1400 #endif
1401 }//offline fixed point
1402 
1403 
1404 template<typename TruthModelType>
1405 typename CRB<TruthModelType>::element_type
1406 CRB<TruthModelType>::offlineFixedPointDual(parameter_type const& mu, element_ptrtype & dual_initial_field, const sparse_matrix_ptrtype & A, const element_type & u, bool zero_iteration )
1407 {
1408 
1409  M_backend_dual = backend_type::build( BACKEND_PETSC );
1410  bool reuse_prec = this->vm()["crb.reuse-prec"].template as<bool>() ;
1411 
1412  auto udu = M_model->functionSpace()->element();
1413 
1414  sparse_matrix_ptrtype M = M_model->newMatrix();
1415  int nl = M_model->Nl(); //number of outputs
1416  std::vector< vector_ptrtype > F( nl );
1417  for(int l=0; l<nl; l++)
1418  F[l]=M_model->newVector();
1419 
1420 
1421  M_bdf_dual = bdf( _space=M_model->functionSpace(), _vm=this->vm() , _name="bdf_dual" );
1422  M_bdf_dual_save = bdf( _space=M_model->functionSpace(), _vm=this->vm() , _name="bdf_dual_save" );
1423 
1424  M_bdf_dual->setTimeInitial( M_model->timeFinal()+M_model->timeStep() );
1425 
1426  M_bdf_dual->setTimeStep( -M_model->timeStep() );
1427  M_bdf_dual->setTimeFinal( M_model->timeInitial()+M_model->timeStep() );
1428  M_bdf_dual->setOrder( M_model->timeOrder() );
1429 
1430  M_bdf_dual_save->setTimeInitial( M_model->timeFinal()+M_model->timeStep() );
1431  M_bdf_dual_save->setTimeStep( -M_model->timeStep() );
1432  M_bdf_dual_save->setTimeFinal( M_model->timeInitial()+M_model->timeStep() );
1433  M_bdf_dual_save->setOrder( M_model->timeOrder() );
1434 
1435  M_bdf_dual_save->setRankProcInNameOfFiles( true );
1436  M_bdf_dual->setRankProcInNameOfFiles( true );
1437 
1438  auto Adu = M_model->newMatrix();
1439  auto Apr = M_model->newMatrix();
1440 
1441  double dt = M_model->timeStep();
1442 
1443  int max_fixedpoint_iterations = option(_name="crb.max-fixedpoint-iterations").template as<int>();
1444  double increment_fixedpoint_tol = option(_name="crb.increment-fixedpoint-tol").template as<double>();
1445  double fixedpoint_critical_value = option(_name="crb.fixedpoint-critical-value").template as<double>();
1446  int iteration=0;
1447  double increment_norm=1e3;
1448 
1449  vector_ptrtype Rhs( M_backend_dual->newVector( M_model->functionSpace() ) );
1450 
1451  if( zero_iteration )
1452  increment_norm = 0;
1453 
1454  double bdf_coeff;
1455 
1456  auto vec_bdf_poly = M_backend_dual->newVector( M_model->functionSpace() );
1457 
1458  if ( M_model->isSteady() )
1459  udu.zero() ;
1460  else
1461  {
1462  boost::tie( M, Apr, F) = M_model->update( mu , M_bdf_dual->timeInitial() );
1463 
1464 #if 0
1465  Apr->addMatrix( 1./dt, M );
1466  Apr->transpose( Adu );
1467  *Rhs=*F[M_output_index];
1468  Rhs->scale( 1./dt );
1469  // M->scale(1./dt);
1470 
1471  M_preconditioner_dual->setMatrix( Adu );
1472  M_backend_dual->solve( _matrix=Adu, _solution=dual_initial_field, _rhs=Rhs, _prec=M_preconditioner_dual );
1473 #else
1474  *Rhs=*F[M_output_index];
1475  //Rhs->scale( 1./dt );
1476  //M->scale(1./dt);
1477  M_preconditioner_dual->setMatrix( M );
1478  M_backend_dual->solve( _matrix=M, _solution=dual_initial_field, _rhs=Rhs, _prec=M_preconditioner_dual );
1479 #endif
1480  udu=*dual_initial_field;
1481  }
1482 
1483  auto uold = M_model->functionSpace()->element();
1484 
1485  element_ptrtype uproj( new element_type( M_model->functionSpace() ) );
1486 
1487 
1488  for ( M_bdf_dual->start(udu),M_bdf_dual_save->start(udu);
1489  !M_bdf_dual->isFinished() , !M_bdf_dual_save->isFinished();
1490  M_bdf_dual->next() , M_bdf_dual_save->next() )
1491  {
1492 
1493  bdf_coeff = M_bdf_dual->polyDerivCoefficient( 0 );
1494 
1495  auto bdf_poly = M_bdf_dual->polyDeriv();
1496 
1497  do
1498  {
1499  boost::tie( M, Apr, F) = M_model->update( mu , udu, M_bdf_dual->time() );
1500 
1501  if( ! M_model->isSteady() )
1502  {
1503  Apr->addMatrix( bdf_coeff, M );
1504  Rhs->zero();
1505  *vec_bdf_poly = bdf_poly;
1506  Rhs->addVector( *vec_bdf_poly, *M );
1507  }
1508  else
1509  {
1510  *Rhs = *F[M_output_index];
1511  Rhs->scale( -1 );
1512  }
1513 
1514 
1515  if( option("crb.use-symmetric-matrix").template as<bool>() )
1516  Adu = Apr;
1517  else
1518  Apr->transpose( Adu );
1519  //Adu->close();
1520  //Rhs->close();
1521 
1522  //backup for non linear problems
1523  uold = udu;
1524 
1525  //solve
1526  M_preconditioner_dual->setMatrix( Adu );
1527  if ( reuse_prec )
1528  {
1529  auto ret = M_backend_dual->solve( _matrix=Adu, _solution=udu, _rhs=Rhs, _prec=M_preconditioner_dual, _reuse_prec=( M_bdf_primal->iteration() >=2 ) );
1530  if ( !ret.template get<0>() )
1531  LOG(INFO)<<"[CRB] WARNING : at time "<<M_bdf_primal->time()<<" we have not converged ( nb_it : "<<ret.template get<1>()<<" and residual : "<<ret.template get<2>() <<" ) \n";
1532  }
1533  else
1534  {
1535  auto ret = M_backend_dual->solve( _matrix=Adu, _solution=udu, _rhs=Rhs , _prec=M_preconditioner_dual );
1536  if ( !ret.template get<0>() )
1537  LOG(INFO)<<"[CRB] WARNING : at time "<<M_bdf_primal->time()<<" we have not converged ( nb_it : "<<ret.template get<1>()<<" and residual : "<<ret.template get<2>() <<" ) \n";
1538  }
1539 
1540  //on each subspace the norme of the increment is computed and then we perform the sum
1541  increment_norm = M_model->computeNormL2( udu , uold );
1542  iteration++;
1543 
1544  }while( increment_norm > increment_fixedpoint_tol && iteration < max_fixedpoint_iterations );
1545 
1546  M_bdf_dual->shiftRight( udu );
1547 
1548  //check dual property
1549  double term1 = A->energy( udu, u );
1550  double term2 = Adu->energy( u, udu );
1551  double diff = math::abs( term1-term2 );
1552  LOG(INFO) << "< A u , udu > - < u , A* udu > = "<<diff<<"\n";
1553 
1554  if ( ! M_model->isSteady() )
1555  {
1556  element_ptrtype projection ( new element_type ( M_model->functionSpace() ) );
1557  projectionOnPodSpace ( udu , projection, "dual" );
1558  *uproj=udu;
1559  M_bdf_dual_save->shiftRight( *uproj );
1560  }
1561 
1562  if( increment_norm > fixedpoint_critical_value )
1563  throw std::logic_error( (boost::format("[CRB::offlineFixedPointDual] at time %1% ERROR : increment > critical value " ) %M_bdf_dual->time() ).str() );
1564 
1565  }//end of loop over time
1566 
1567  return udu;
1568 }//offline fixed point
1569 
1570 
1571 
1572 template<typename TruthModelType>
1573 void
1574 CRB<TruthModelType>::loadSCMDB()
1575 {
1576  if ( M_error_type == CRB_RESIDUAL_SCM )
1577  {
1578  M_scmA->setScmForMassMatrix( false );
1579  if( ! M_scmA->loadDB() )
1580  std::vector<boost::tuple<double,double,double> > M_rbconv2 = M_scmA->offline();
1581 
1582  if ( ! M_model->isSteady() )
1583  {
1584  M_scmM->setScmForMassMatrix( true );
1585  if( ! M_scmM->loadDB() )
1586  std::vector<boost::tuple<double,double,double> > M_rbconv3 = M_scmM->offline();
1587  }
1588  }
1589 }
1590 
1591 
1592 template<typename TruthModelType>
1593 typename CRB<TruthModelType>::convergence_type
1595 {
1596  M_database_contains_variance_info = this->vm()["crb.save-information-for-variance"].template as<bool>();
1597 
1598  int proc_number = this->worldComm().globalRank();
1599  M_rbconv_contains_primal_and_dual_contributions = true;
1600 
1601  bool rebuild_database = this->vm()["crb.rebuild-database"].template as<bool>() ;
1602  orthonormalize_primal = this->vm()["crb.orthonormalize-primal"].template as<bool>() ;
1603  orthonormalize_dual = this->vm()["crb.orthonormalize-dual"].template as<bool>() ;
1604  solve_dual_problem = this->vm()["crb.solve-dual-problem"].template as<bool>() ;
1605 
1606  M_use_newton = this->vm()["crb.use-newton"].template as<bool>() ;
1607 
1608  //if ( this->worldComm().globalSize() > 1 )
1609  // solve_dual_problem = false;
1610 
1611  if ( ! solve_dual_problem ) orthonormalize_dual=false;
1612 
1613  M_Nm = this->vm()["crb.Nm"].template as<int>() ;
1614  bool seek_mu_in_complement = this->vm()["crb.seek-mu-in-complement"].template as<bool>() ;
1615 
1616  boost::timer ti;
1617  LOG(INFO)<< "Offline CRB starts, this may take a while until Database is computed...\n";
1618  //LOG(INFO) << "[CRB::offline] Starting offline for output " << M_output_index << "\n";
1619  //LOG(INFO) << "[CRB::offline] initialize underlying finite element model\n";
1620  M_model->init();
1621  //LOG(INFO) << " -- model init done in " << ti.elapsed() << "s\n";
1622 
1623  parameter_type mu( M_Dmu );
1624 
1625  double delta_pr;
1626  double delta_du;
1627  size_type index;
1628 
1629  //if M_N == 0 then there is not an already existing database
1630  if ( rebuild_database || M_N == 0)
1631  {
1632 
1633  ti.restart();
1634  //scm_ptrtype M_scm = scm_ptrtype( new scm_type( M_vm ) );
1635  //M_scm->setTruthModel( M_model );
1636  // std::vector<boost::tuple<double,double,double> > M_rbconv2 = M_scm->offline();
1637 
1638  LOG(INFO) << "[CRB::offline] compute random sampling\n";
1639 
1640  int sampling_size = this->vm()["crb.sampling-size"].template as<int>();
1641  std::string file_name = ( boost::format("M_Xi_%1%") % sampling_size ).str();
1642  std::ifstream file ( file_name );
1643  if( ! file )
1644  {
1645  // random sampling
1646  M_Xi->randomize( sampling_size );
1647  //M_Xi->equidistribute( this->vm()["crb.sampling-size"].template as<int>() );
1648  M_Xi->writeOnFile(file_name);
1649  }
1650  else
1651  {
1652  M_Xi->clear();
1653  M_Xi->readFromFile(file_name);
1654  }
1655 
1656  M_WNmu->setSuperSampling( M_Xi );
1657 
1658 
1659  if( proc_number == 0 ) std::cout<<"[CRB offline] M_error_type = "<<M_error_type<<std::endl;
1660 
1661  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
1662  std::cout << " -- sampling init done in " << ti.elapsed() << "s\n";
1663  ti.restart();
1664 
1665  if ( M_error_type == CRB_RESIDUAL || M_error_type == CRB_RESIDUAL_SCM )
1666  {
1667  int __QLhs = M_model->Qa();
1668  int __QRhs = M_model->Ql( 0 );
1669  int __QOutput = M_model->Ql( M_output_index );
1670  int __Qm = M_model->Qm();
1671 
1672  //typename array_2_type::extent_gen extents2;
1673  //M_C0_pr.resize( extents2[__QRhs][__QRhs] );
1674  //M_C0_du.resize( extents2[__QOutput][__QOutput] );
1675  M_C0_pr.resize( __QRhs );
1676  for( int __q1=0; __q1< __QRhs; __q1++)
1677  {
1678  int __mMaxQ1=M_model->mMaxF(0,__q1);
1679  M_C0_pr[__q1].resize( __mMaxQ1 );
1680  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1681  {
1682  M_C0_pr[__q1][__m1].resize( __QRhs );
1683  for( int __q2=0; __q2< __QRhs; __q2++)
1684  {
1685  int __mMaxQ2=M_model->mMaxF(0,__q2);
1686  M_C0_pr[__q1][__m1][__q2].resize( __mMaxQ2 );
1687  }
1688  }
1689  }
1690 
1691  M_C0_du.resize( __QOutput );
1692  for( int __q1=0; __q1< __QOutput; __q1++)
1693  {
1694  int __mMaxQ1=M_model->mMaxF(M_output_index,__q1);
1695  M_C0_du[__q1].resize( __mMaxQ1 );
1696  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1697  {
1698  M_C0_du[__q1][__m1].resize( __QOutput );
1699  for( int __q2=0; __q2< __QOutput; __q2++)
1700  {
1701  int __mMaxQ2=M_model->mMaxF(M_output_index,__q2);
1702  M_C0_du[__q1][__m1][__q2].resize( __mMaxQ2 );
1703  }
1704  }
1705  }
1706 
1707  //typename array_3_type::extent_gen extents3;
1708  //M_Lambda_pr.resize( extents3[__QLhs][__QRhs] );
1709  //M_Lambda_du.resize( extents3[__QLhs][__QOutput] );
1710  M_Lambda_pr.resize( __QLhs );
1711  for( int __q1=0; __q1< __QLhs; __q1++)
1712  {
1713  int __mMaxQ1=M_model->mMaxA(__q1);
1714  M_Lambda_pr[__q1].resize( __mMaxQ1 );
1715  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1716  {
1717  M_Lambda_pr[__q1][__m1].resize( __QRhs );
1718  for( int __q2=0; __q2< __QRhs; __q2++)
1719  {
1720  int __mMaxQ2=M_model->mMaxF(0,__q2);
1721  M_Lambda_pr[__q1][__m1][__q2].resize( __mMaxQ2 );
1722  }
1723  }
1724  }
1725 
1726  M_Lambda_du.resize( __QLhs );
1727  for( int __q1=0; __q1< __QLhs; __q1++)
1728  {
1729  int __mMaxQ1=M_model->mMaxA(__q1);
1730  M_Lambda_du[__q1].resize( __mMaxQ1 );
1731  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1732  {
1733  M_Lambda_du[__q1][__m1].resize( __QOutput );
1734  for( int __q2=0; __q2< __QOutput; __q2++)
1735  {
1736  int __mMaxQ2=M_model->mMaxF(M_output_index,__q2);
1737  M_Lambda_du[__q1][__m1][__q2].resize( __mMaxQ2 );
1738  }
1739  }
1740  }
1741 
1742  //typename array_4_type::extent_gen extents4;
1743  //M_Gamma_pr.resize( extents4[__QLhs][__QLhs] );
1744  //M_Gamma_du.resize( extents4[__QLhs][__QLhs] );
1745  M_Gamma_pr.resize( __QLhs );
1746  for( int __q1=0; __q1< __QLhs; __q1++)
1747  {
1748  int __mMaxQ1=M_model->mMaxA(__q1);
1749  M_Gamma_pr[__q1].resize( __mMaxQ1 );
1750  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1751  {
1752  M_Gamma_pr[__q1][__m1].resize( __QLhs );
1753  for( int __q2=0; __q2< __QLhs; __q2++)
1754  {
1755  int __mMaxQ2=M_model->mMaxA(__q2);
1756  M_Gamma_pr[__q1][__m1][__q2].resize( __mMaxQ2 );
1757  }
1758  }
1759  }
1760 
1761  M_Gamma_du.resize( __QLhs );
1762  for( int __q1=0; __q1< __QLhs; __q1++)
1763  {
1764  int __mMaxQ1=M_model->mMaxA(__q1);
1765  M_Gamma_du[__q1].resize( __mMaxQ1 );
1766  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1767  {
1768  M_Gamma_du[__q1][__m1].resize( __QLhs );
1769  for( int __q2=0; __q2< __QLhs; __q2++)
1770  {
1771  int __mMaxQ2=M_model->mMaxA(__q2);
1772  M_Gamma_du[__q1][__m1][__q2].resize( __mMaxQ2 );
1773  }
1774  }
1775  }
1776 
1777  if ( model_type::is_time_dependent )
1778  {
1779  // M_Cmf_pr.resize( extents3[__Qm][__QRhs] );
1780  // M_Cmf_du.resize( extents3[__Qm][__QRhs] );
1781  M_Cmf_pr.resize( __Qm );
1782  for( int __q1=0; __q1< __Qm; __q1++)
1783  {
1784  int __mMaxQ1=M_model->mMaxM(__q1);
1785  M_Cmf_pr[__q1].resize( __mMaxQ1 );
1786  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1787  {
1788  M_Cmf_pr[__q1][__m1].resize( __QRhs );
1789  for( int __q2=0; __q2< __QRhs; __q2++)
1790  {
1791  int __mMaxQ2=M_model->mMaxF(0,__q2);
1792  M_Cmf_pr[__q1][__m1][__q2].resize( __mMaxQ2 );
1793  }
1794  }
1795  }
1796 
1797  M_Cmf_du.resize( __Qm );
1798  for( int __q1=0; __q1< __Qm; __q1++)
1799  {
1800  int __mMaxQ1=M_model->mMaxM(__q1);
1801  M_Cmf_du[__q1].resize( __mMaxQ1 );
1802  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1803  {
1804  M_Cmf_du[__q1][__m1].resize( __QOutput );
1805  for( int __q2=0; __q2< __QOutput; __q2++)
1806  {
1807  int __mMaxQ2=M_model->mMaxF(M_output_index,__q2);
1808  M_Cmf_du[__q1][__m1][__q2].resize( __mMaxQ2 );
1809  }
1810  }
1811  }
1812  M_Cmf_du_ini.resize( __Qm );
1813  for( int __q1=0; __q1< __Qm; __q1++)
1814  {
1815  int __mMaxQ1=M_model->mMaxM(__q1);
1816  M_Cmf_du_ini[__q1].resize( __mMaxQ1 );
1817  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1818  {
1819  M_Cmf_du_ini[__q1][__m1].resize( __QOutput );
1820  for( int __q2=0; __q2< __QOutput; __q2++)
1821  {
1822  int __mMaxQ2=M_model->mMaxF(M_output_index,__q2);
1823  M_Cmf_du_ini[__q1][__m1][__q2].resize( __mMaxQ2 );
1824  }
1825  }
1826  }
1827 
1828  // M_Cma_pr.resize( extents4[__Qm][__QLhs] );
1829  // M_Cma_du.resize( extents4[__Qm][__QLhs] );
1830  M_Cma_pr.resize( __Qm );
1831  for( int __q1=0; __q1< __Qm; __q1++)
1832  {
1833  int __mMaxQ1=M_model->mMaxM(__q1);
1834  M_Cma_pr[__q1].resize( __mMaxQ1 );
1835  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1836  {
1837  M_Cma_pr[__q1][__m1].resize( __QLhs );
1838  for( int __q2=0; __q2< __QLhs; __q2++)
1839  {
1840  int __mMaxQ2=M_model->mMaxA(__q2);
1841  M_Cma_pr[__q1][__m1][__q2].resize( __mMaxQ2 );
1842  }
1843  }
1844  }
1845 
1846  M_Cma_du.resize( __Qm );
1847  for( int __q1=0; __q1< __Qm; __q1++)
1848  {
1849  int __mMaxQ1=M_model->mMaxM(__q1);
1850  M_Cma_du[__q1].resize( __mMaxQ1 );
1851  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1852  {
1853  M_Cma_du[__q1][__m1].resize( __QLhs );
1854  for( int __q2=0; __q2< __QLhs; __q2++)
1855  {
1856  int __mMaxQ2=M_model->mMaxA(__q2);
1857  M_Cma_du[__q1][__m1][__q2].resize( __mMaxQ2 );
1858  }
1859  }
1860  }
1861 
1862  // M_Cmm_pr.resize( extents4[__Qm][__Qm] );
1863  // M_Cmm_du.resize( extents4[__Qm][__Qm] );
1864  M_Cmm_pr.resize( __Qm );
1865  for( int __q1=0; __q1< __Qm; __q1++)
1866  {
1867  int __mMaxQ1=M_model->mMaxM(__q1);
1868  M_Cmm_pr[__q1].resize( __mMaxQ1 );
1869  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1870  {
1871  M_Cmm_pr[__q1][__m1].resize( __Qm );
1872  for( int __q2=0; __q2< __Qm; __q2++)
1873  {
1874  int __mMaxQ2=M_model->mMaxM(__q2);
1875  M_Cmm_pr[__q1][__m1][__q2].resize( __mMaxQ2 );
1876  }
1877  }
1878  }
1879 
1880  M_Cmm_du.resize( __Qm );
1881  for( int __q1=0; __q1< __Qm; __q1++)
1882  {
1883  int __mMaxQ1=M_model->mMaxM(__q1);
1884  M_Cmm_du[__q1].resize( __mMaxQ1 );
1885  for( int __m1=0; __m1< __mMaxQ1; __m1++)
1886  {
1887  M_Cmm_du[__q1][__m1].resize( __Qm );
1888  for( int __q2=0; __q2< __Qm; __q2++)
1889  {
1890  int __mMaxQ2=M_model->mMaxM(__q2);
1891  M_Cmm_du[__q1][__m1][__q2].resize( __mMaxQ2 );
1892  }
1893  }
1894  }
1895 
1896  }//end of if ( model_type::is_time_dependent )
1897  }//end of if ( M_error_type == CRB_RESIDUAL || M_error_type == CRB_RESIDUAL_SCM )
1898  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
1899  std::cout << " -- residual data init done in " << ti.elapsed() << std::endl;
1900  ti.restart();
1901 
1902  // empty sets
1903  M_WNmu->clear();
1904 
1905  if( M_error_type == CRB_NO_RESIDUAL )
1906  mu = M_Dmu->element();
1907  else
1908  {
1909  // start with M_C = { arg min mu, mu \in Xi }
1910  boost::tie( mu, index ) = M_Xi->min();
1911  }
1912 
1913  int size = mu.size();
1914  if( proc_number == 0 )
1915  {
1916  std::cout << " -- start with mu = [ ";
1917  for ( int i=0; i<size-1; i++ ) std::cout<<mu( i )<<" ";
1918  std::cout<<mu( size-1 )<<" ]"<<std::endl;
1919  }
1920  //std::cout << " -- WN size : " << M_WNmu->size() << "\n";
1921 
1922  // dimension of reduced basis space
1923  M_N = 0;
1924 
1925  // scm offline stage: build C_K
1926  this->loadSCMDB();
1927 
1928  M_maxerror = 1e10;
1929  delta_pr = 0;
1930  delta_du = 0;
1931  //boost::tie( M_maxerror, mu, index ) = maxErrorBounds( N );
1932 
1933  LOG(INFO) << "[CRB::offline] allocate reduced basis data structures\n";
1934  M_Aqm_pr.resize( M_model->Qa() );
1935  M_Aqm_du.resize( M_model->Qa() );
1936  M_Aqm_pr_du.resize( M_model->Qa() );
1937 
1938  if( M_use_newton )
1939  M_Jqm_pr.resize( M_model->Qa() );
1940 
1941  for(int q=0; q<M_model->Qa(); q++)
1942  {
1943  M_Aqm_pr[q].resize( M_model->mMaxA(q) );
1944  M_Aqm_du[q].resize( M_model->mMaxA(q) );
1945  M_Aqm_pr_du[q].resize( M_model->mMaxA(q) );
1946 
1947  if(M_use_newton)
1948  M_Jqm_pr[q].resize( M_model->mMaxA(q) );
1949  }
1950 
1951  M_Mqm_pr.resize( M_model->Qm() );
1952  M_Mqm_du.resize( M_model->Qm() );
1953  M_Mqm_pr_du.resize( M_model->Qm() );
1954  for(int q=0; q<M_model->Qm(); q++)
1955  {
1956  M_Mqm_pr[q].resize( M_model->mMaxM(q) );
1957  M_Mqm_du[q].resize( M_model->mMaxM(q) );
1958  M_Mqm_pr_du[q].resize( M_model->mMaxM(q) );
1959  }
1960 
1961  int QInitialGuessV = M_model->QInitialGuess();
1962  M_InitialGuessV_pr.resize( QInitialGuessV );
1963  for(int q=0; q<QInitialGuessV; q++)
1964  {
1965  M_InitialGuessV_pr[q].resize( M_model->mMaxInitialGuess(q) );
1966  }
1967 
1968  M_Fqm_pr.resize( M_model->Ql( 0 ) );
1969  M_Fqm_du.resize( M_model->Ql( 0 ) );
1970  M_Lqm_pr.resize( M_model->Ql( M_output_index ) );
1971  M_Lqm_du.resize( M_model->Ql( M_output_index ) );
1972 
1973  if(M_use_newton)
1974  M_Rqm_pr.resize( M_model->Ql( 0 ) );
1975 
1976  for(int q=0; q<M_model->Ql( 0 ); q++)
1977  {
1978  M_Fqm_pr[q].resize( M_model->mMaxF( 0 , q) );
1979  M_Fqm_du[q].resize( M_model->mMaxF( 0 , q) );
1980 
1981  if(M_use_newton)
1982  M_Rqm_pr[q].resize( M_model->mMaxF( 0 , q) );
1983  }
1984  for(int q=0; q<M_model->Ql( M_output_index ); q++)
1985  {
1986  M_Lqm_pr[q].resize( M_model->mMaxF( M_output_index , q) );
1987  M_Lqm_du[q].resize( M_model->mMaxF( M_output_index , q) );
1988  }
1989  }//end of if( rebuild_database )
1990  else
1991  {
1992  // scm offline stage: build C_K
1993  this->loadSCMDB();
1994 
1995  mu = M_current_mu;
1996  if( proc_number == 0 )
1997  {
1998  std::cout<<"we are going to enrich the reduced basis"<<std::endl;
1999  std::cout<<"there are "<<M_N<<" elements in the database"<<std::endl;
2000  }
2001  LOG(INFO) <<"we are going to enrich the reduced basis"<<std::endl;
2002  LOG(INFO) <<"there are "<<M_N<<" elements in the database"<<std::endl;
2003  }//end of else associated to if ( rebuild_databse )
2004 
2005  //sparse_matrix_ptrtype M,Adu,At;
2006  //element_ptrtype InitialGuess;
2007  //vector_ptrtype MF;
2008  //std::vector<vector_ptrtype> L;
2009 
2010  LOG(INFO) << "[CRB::offline] compute affine decomposition\n";
2011  std::vector< std::vector<sparse_matrix_ptrtype> > Aqm;
2012  std::vector< std::vector<sparse_matrix_ptrtype> > Mqm;
2013  //to project the initial guess on the reduced basis we solve A u = F
2014  //with A = \int_\Omega u v ( mass matrix )
2015  //F = \int_\Omega initial_guess v
2016  //so InitialGuessV is the mu-independant part of the vector F
2017  std::vector< std::vector<element_ptrtype> > InitialGuessV;
2018  std::vector< std::vector<std::vector<vector_ptrtype> > > Fqm,Lqm;
2019  sparse_matrix_ptrtype Aq_transpose = M_model->newMatrix();
2020 
2021  sparse_matrix_ptrtype A = M_model->newMatrix();
2022  int nl = M_model->Nl();
2023  std::vector< vector_ptrtype > F( nl );
2024  for(int l=0; l<nl; l++)
2025  F[l]=M_model->newVector();
2026 
2027  std::vector< std::vector<sparse_matrix_ptrtype> > Jqm;
2028  std::vector< std::vector<std::vector<vector_ptrtype> > > Rqm;
2029 
2030  InitialGuessV = M_model->computeInitialGuessVAffineDecomposition();
2031 
2032 
2033  if( M_use_newton )
2034  boost::tie( Mqm , Jqm, Rqm ) = M_model->computeAffineDecomposition();
2035  else
2036  {
2037  if( option("crb.stock-matrices").template as<bool>() )
2038  boost::tie( Mqm, Aqm, Fqm ) = M_model->computeAffineDecomposition();
2039  }
2040 
2041  element_ptrtype dual_initial_field( new element_type( M_model->functionSpace() ) );
2042  element_ptrtype uproj( new element_type( M_model->functionSpace() ) );
2043  auto u = M_model->functionSpace()->element();
2044  auto udu = M_model->functionSpace()->element();
2045 
2046  M_mode_number=1;
2047 
2048  LOG(INFO) << "[CRB::offline] starting offline adaptive loop\n";
2049 
2050  bool reuse_prec = this->vm()["crb.reuse-prec"].template as<bool>() ;
2051 
2052  bool use_predefined_WNmu = this->vm()["crb.use-predefined-WNmu"].template as<bool>() ;
2053 
2054  int N_log_equi = this->vm()["crb.use-logEquidistributed-WNmu"].template as<int>() ;
2055  int N_equi = this->vm()["crb.use-equidistributed-WNmu"].template as<int>() ;
2056 
2057  if( N_log_equi > 0 || N_equi > 0 )
2058  use_predefined_WNmu = true;
2059 
2060  if ( use_predefined_WNmu )
2061  {
2062  std::string file_name = ( boost::format("SamplingWNmu") ).str();
2063  std::ifstream file ( file_name );
2064  if( ! file )
2065  {
2066  throw std::logic_error( "[CRB::offline] ERROR the file SamplingWNmu doesn't exist so it's impossible to known which parameters you want to use to build the database" );
2067  }
2068  else
2069  {
2070  M_WNmu->clear();
2071  int sampling_size = M_WNmu->readFromFile(file_name);
2072  M_iter_max = sampling_size;
2073  }
2074  mu = M_WNmu->at( M_N ); // first element
2075 
2076  if( proc_number == this->worldComm().masterRank() )
2077  std::cout<<"[CRB::offline] read WNmu ( sampling size : "<<M_iter_max<<" )"<<std::endl;
2078  }
2079 
2080 
2081  LOG(INFO) << "[CRB::offline] strategy "<< M_error_type <<"\n";
2082  if( proc_number == this->worldComm().masterRank() ) std::cout << "[CRB::offline] strategy "<< M_error_type <<std::endl;
2083 
2084  if( M_error_type == CRB_NO_RESIDUAL || use_predefined_WNmu )
2085  {
2086  //in this case it makes no sens to check the estimated error
2087  M_maxerror = 1e10;
2088  }
2089 
2090  while ( M_maxerror > M_tolerance && M_N < M_iter_max )
2091  {
2092 
2093  boost::timer timer, timer2;
2094  LOG(INFO) <<"========================================"<<"\n";
2095 
2096  if ( M_error_type == CRB_NO_RESIDUAL )
2097  LOG(INFO) << "N=" << M_N << "/" << M_iter_max << " ( nb proc : "<<worldComm().globalSize()<<")";
2098  else
2099  LOG(INFO) << "N=" << M_N << "/" << M_iter_max << " maxerror=" << M_maxerror << " / " << M_tolerance << "( nb proc : "<<worldComm().globalSize()<<")";
2100 
2101  // for a given parameter \p mu assemble the left and right hand side
2102  u.setName( ( boost::format( "fem-primal-N%1%-proc%2%" ) % (M_N) % proc_number ).str() );
2103  udu.setName( ( boost::format( "fem-dual-N%1%-proc%2%" ) % (M_N) % proc_number ).str() );
2104 
2105  if ( M_model->isSteady() && ! M_use_newton )
2106  {
2107 
2108  //we need to treat nonlinearity also in offline step
2109  //because in online step we have to treat nonlinearity ( via a fixed point for example )
2110  bool zero_iteration=false;
2111  u = offlineFixedPointPrimal( mu , A , zero_iteration );
2112  if( solve_dual_problem )
2113  udu = offlineFixedPointDual( mu , dual_initial_field , A , u, zero_iteration );
2114  }
2115 
2116  if ( M_model->isSteady() && M_use_newton )
2117  {
2118  mu.check();
2119  u.zero();
2120 
2121  timer2.restart();
2122  LOG(INFO) << "[CRB::offline] solving primal" << "\n";
2123  u = M_model->solve( mu );
2124  if( proc_number == this->worldComm().masterRank() )
2125  LOG(INFO) << " -- primal problem solved in " << timer2.elapsed() << "s";
2126  timer2.restart();
2127  }
2128 
2129 
2130  if( ! M_model->isSteady() )
2131  {
2132  bool zero_iteration=true;
2133  u = offlineFixedPointPrimal( mu, A , zero_iteration );
2134  if ( solve_dual_problem || M_error_type==CRB_RESIDUAL || M_error_type == CRB_RESIDUAL_SCM )
2135  udu = offlineFixedPointDual( mu , dual_initial_field , A , u, zero_iteration );
2136  }
2137 
2138 
2139  if( ! use_predefined_WNmu )
2140  M_WNmu->push_back( mu, index );
2141 
2142  M_WNmu_complement = M_WNmu->complement();
2143 
2144  bool norm_zero = false;
2145 
2146  if ( M_model->isSteady() )
2147  {
2148  M_WN.push_back( u );
2149  M_WNdu.push_back( udu );
2150  }//end of steady case
2151 
2152  else
2153  {
2154  if ( M_N == 0 && orthonormalize_primal==false )
2155  {
2156  //add initial solution as element in the reduced basis if it's not zero
2157  //else there will be problems during orthonormalization step
2158  //note : at this step *u contains solution of primal probleme at final time
2159  //so it's the initial solution of the dual problem
2160  //in the case where orthonormalize_primal==true, even with initial solution in
2161  //the reduced basis we will commit an approximation in the online part
2162  //when initializing uN.
2163  //if initial solution is zero then the system the matrix used in online will be singular
2164  element_ptrtype primal_initial_field ( new element_type ( M_model->functionSpace() ) );
2165 
2166  M_model->initializationField( primal_initial_field, mu ); //fill initial_field
2167  int norm_ini = M_model->scalarProduct( *primal_initial_field, *primal_initial_field );
2168 
2169  if ( norm_ini != 0 )
2170  {
2171  M_WN.push_back( *primal_initial_field );
2172  M_WNdu.push_back( *dual_initial_field );
2173  }
2174 
2175  else
2176  {
2177  norm_zero=true;
2178  }
2179  } // end of if ( M_N == 0 )
2180 
2181  //POD in time
2182  LOG(INFO)<<"[CRB::offline] start of POD \n";
2183 
2184  pod_ptrtype POD = pod_ptrtype( new pod_type( ) );
2185 
2186 
2187  if ( M_mode_number == 1 )
2188  {
2189  //in this case, it's the first time that we add mu
2190  POD->setNm( M_Nm );
2191  }
2192 
2193  else
2194  {
2195  //in this case, mu has been chosen twice (at least)
2196  //so we add the M_mode_number^th mode in the basis
2197  POD->setNm( M_mode_number*M_Nm );
2198  int size = mu.size();
2199  LOG(INFO)<<"... CRB M_mode_number = "<<M_mode_number<<"\n";
2200  LOG(INFO)<<"for mu = [ ";
2201 
2202  for ( int i=0; i<size-1; i++ ) LOG(INFO)<<mu[i]<<" , ";
2203 
2204  LOG(INFO)<<mu[ size-1 ];
2205  LOG(INFO)<<" ]\n";
2206 
2207  double Tf = M_model->timeFinal();
2208  double dt = M_model->timeStep();
2209  int nb_mode_max = Tf/dt;
2210 
2211  if ( M_mode_number>=nb_mode_max-1 )
2212  {
2213  std::cout<<"Error : we access to "<<M_mode_number<<"^th mode"<<std::endl;
2214  std::cout<<"parameter choosen : [ ";
2215 
2216  for ( int i=0; i<size-1; i++ ) std::cout<<mu[i]<<" , ";
2217 
2218  std::cout<<mu[ size-1 ]<<" ] "<<std::endl;
2219  throw std::logic_error( "[CRB::offline] ERROR during the construction of the reduced basis, one parameter has been choosen too many times" );
2220  }
2221  }
2222 
2223  POD->setBdf( M_bdf_primal_save );
2224  POD->setModel( M_model );
2225  POD->setTimeInitial( M_model->timeInitial() );
2226  mode_set_type ModeSet;
2227 
2228  size_type number_max_of_mode = POD->pod( ModeSet,true );
2229 
2230  if ( number_max_of_mode < M_Nm )
2231  {
2232  std::cout<<"With crb.Nm = "<<M_Nm<<" there was too much too small eigenvalues so the value";
2233  std::cout<<" of crb.Nm as been changed to "<<number_max_of_mode<<std::endl;
2234  M_Nm = number_max_of_mode;
2235  }
2236 
2237  //now : loop over number modes per mu
2238 
2239  if ( !seek_mu_in_complement )
2240  {
2241  for ( size_type i=0; i<M_Nm; i++ )
2242  M_WN.push_back( ModeSet[M_mode_number*M_Nm-1+i] ) ;
2243  //M_WN.push_back( ModeSet[M_mode_number-1] ) ;
2244  }
2245 
2246  else
2247  {
2248  for ( size_type i=0; i<M_Nm; i++ )
2249  M_WN.push_back( ModeSet[i] ) ;
2250  }
2251 
2252  //and now the dual
2253  if ( solve_dual_problem || M_error_type==CRB_RESIDUAL || M_error_type == CRB_RESIDUAL_SCM )
2254  {
2255  POD->setBdf( M_bdf_dual );
2256  POD->setTimeInitial( M_model->timeFinal()+M_model->timeStep() );
2257  mode_set_type ModeSetdu;
2258  POD->pod( ModeSetdu,false );
2259 
2260  if ( !seek_mu_in_complement )
2261  {
2262  for ( size_type i=0; i<M_Nm; i++ )
2263  M_WNdu.push_back( ModeSetdu[M_mode_number*M_Nm-1+i] ) ;
2264  }
2265 
2266  else
2267  {
2268  for ( size_type i=0; i<M_Nm; i++ )
2269  M_WNdu.push_back( ModeSetdu[i] ) ;
2270  }
2271  }
2272 
2273  else
2274  {
2275  element_ptrtype element_zero ( new element_type ( M_model->functionSpace() ) );
2276 
2277  for ( size_type i=0; i<M_Nm; i++ )
2278  {
2279  M_WNdu.push_back( *element_zero ) ;
2280  }
2281  }
2282 
2283 
2284  }//end of transient case
2285 
2286  //in the case of transient problem, we can add severals modes for a same mu
2287  //Moreover, if the case where the initial condition is not zero and we don't orthonormalize elements in the basis,
2288  //we add the initial condition in the basis (so one more element)
2289  size_type number_of_added_elements = M_Nm + ( M_N==0 && orthonormalize_primal==false && norm_zero==false && !M_model->isSteady() );
2290 
2291  //in the case of steady problems, we add only one element
2292  if( M_model->isSteady() )
2293  number_of_added_elements=1;
2294 
2295  M_N+=number_of_added_elements;
2296 
2297  double norm_max = option(_name="crb.orthonormality-tol").template as<double>();
2298  int max_iter = option(_name="crb.orthonormality-max-iter").template as<int>();
2299  if ( orthonormalize_primal )
2300  {
2301  double norm = norm_max+1;
2302  int iter=0;
2303  double old = 10;
2304  while( norm >= norm_max && iter < max_iter)
2305  {
2306  norm = orthonormalize( M_N, M_WN, number_of_added_elements );
2307  iter++;
2308  //if the norm doesn't change
2309  if( math::abs(old-norm) < norm_max )
2310  norm=0;
2311  old=norm;
2312  }
2313  }
2314 
2315  if ( orthonormalize_dual )
2316  {
2317  double norm = norm_max+1;
2318  int iter=0;
2319  double old = 10;
2320  while( norm >= norm_max && iter < max_iter )
2321  {
2322  norm = orthonormalize( M_N, M_WNdu, number_of_added_elements );
2323  iter++;
2324  if( math::abs(old-norm) < norm_max )
2325  norm=0;
2326  old=norm;
2327  }
2328  }
2329 
2330  if( ! M_use_newton )
2331  {
2332  LOG(INFO) << "[CRB::offline] compute Aq_pr, Aq_du, Aq_pr_du" << "\n";
2333 
2334  for (size_type q = 0; q < M_model->Qa(); ++q )
2335  {
2336  for( size_type m = 0; m < M_model->mMaxA(q); ++m )
2337  {
2338  M_Aqm_pr[q][m].conservativeResize( M_N, M_N );
2339  M_Aqm_du[q][m].conservativeResize( M_N, M_N );
2340  M_Aqm_pr_du[q][m].conservativeResize( M_N, M_N );
2341 
2342  // only compute the last line and last column of reduced matrices
2343  for ( size_type i = M_N-number_of_added_elements; i < M_N; i++ )
2344  {
2345  for ( size_type j = 0; j < M_N; ++j )
2346  {
2347  M_Aqm_pr[q][m]( i, j ) = M_model->Aqm(q , m , M_WN[i], M_WN[j] );//energy
2348  M_Aqm_du[q][m]( i, j ) = M_model->Aqm( q , m , M_WNdu[i], M_WNdu[j], true );
2349  M_Aqm_pr_du[q][m]( i, j ) = M_model->Aqm(q , m , M_WNdu[i], M_WN[j] );
2350  }
2351  }
2352 
2353  for ( size_type j=M_N-number_of_added_elements; j < M_N; j++ )
2354  {
2355  for ( size_type i = 0; i < M_N; ++i )
2356  {
2357  M_Aqm_pr[q][m]( i, j ) = M_model->Aqm(q , m , M_WN[i], M_WN[j] );
2358  M_Aqm_du[q][m]( i, j ) = M_model->Aqm(q , m , M_WNdu[i], M_WNdu[j], true );
2359  M_Aqm_pr_du[q][m]( i, j ) = M_model->Aqm(q , m , M_WNdu[i], M_WN[j] );
2360  }
2361  }
2362  }//loop over m
2363  }//loop over q
2364 
2365  LOG(INFO) << "[CRB::offline] compute Mq_pr, Mq_du, Mq_pr_du" << "\n";
2366 
2367 
2368  LOG(INFO) << "[CRB::offline] compute Fq_pr, Fq_du" << "\n";
2369 
2370  for ( size_type q = 0; q < M_model->Ql( 0 ); ++q )
2371  {
2372  for( size_type m = 0; m < M_model->mMaxF( 0, q ); ++m )
2373  {
2374  M_Fqm_pr[q][m].conservativeResize( M_N );
2375  M_Fqm_du[q][m].conservativeResize( M_N );
2376  for ( size_type l = 1; l <= number_of_added_elements; ++l )
2377  {
2378  int index = M_N-l;
2379  M_Fqm_pr[q][m]( index ) = M_model->Fqm( 0, q, m, M_WN[index] );
2380  M_Fqm_du[q][m]( index ) = M_model->Fqm( 0, q, m, M_WNdu[index] );
2381  }
2382  }//loop over m
2383  }//loop over q
2384 
2385  }//end of "if ! use_newton"
2386 
2387 
2388  if( M_use_newton )
2389  {
2390  LOG(INFO) << "[CRB::offline] compute Jq_pr " << "\n";
2391 
2392  for (size_type q = 0; q < M_model->Qa(); ++q )
2393  {
2394  for( size_type m = 0; m < M_model->mMaxA(q); ++m )
2395  {
2396  M_Jqm_pr[q][m].conservativeResize( M_N, M_N );
2397 
2398  // only compute the last line and last column of reduced matrices
2399  for ( size_type i = M_N-number_of_added_elements; i < M_N; i++ )
2400  {
2401  for ( size_type j = 0; j < M_N; ++j )
2402  {
2403  M_Jqm_pr[q][m]( i, j ) = Jqm[q][m]->energy( M_WN[i], M_WN[j] );
2404  }
2405  }
2406 
2407  for ( size_type j=M_N-number_of_added_elements; j < M_N; j++ )
2408  {
2409  for ( size_type i = 0; i < M_N; ++i )
2410  {
2411  M_Jqm_pr[q][m]( i, j ) = Jqm[q][m]->energy( M_WN[i], M_WN[j] );
2412  }
2413  }
2414  }//loop over m
2415  }//loop over q
2416 
2417 
2418  LOG(INFO) << "[CRB::offline] compute Rq_pr" << "\n";
2419 
2420  for ( size_type q = 0; q < M_model->Ql( 0 ); ++q )
2421  {
2422  for( size_type m = 0; m < M_model->mMaxF( 0, q ); ++m )
2423  {
2424  M_Rqm_pr[q][m].conservativeResize( M_N );
2425  for ( size_type l = 1; l <= number_of_added_elements; ++l )
2426  {
2427  int index = M_N-l;
2428  M_Rqm_pr[q][m]( index ) = M_model->Fqm( 0, q, m, M_WN[index] );
2429  }
2430  }//loop over m
2431  }//loop over q
2432 
2433  }//end if use_newton case
2434 
2435 
2436  LOG(INFO) << "[CRB::offline] compute MFqm" << "\n";
2437  int q_max = M_model->QInitialGuess();
2438  for ( size_type q = 0; q < q_max; ++q )
2439  {
2440  int m_max =M_model->mMaxInitialGuess(q);
2441  for( size_type m = 0; m < m_max; ++m )
2442  {
2443  M_InitialGuessV_pr[q][m].conservativeResize( M_N );
2444  for ( size_type j = 0; j < M_N; ++j )
2445  M_InitialGuessV_pr[q][m]( j ) = inner_product( *InitialGuessV[q][m] , M_WN[j] );
2446  }
2447  }
2448 
2449 
2450  for ( size_type q = 0; q < M_model->Qm(); ++q )
2451  {
2452  for( size_type m = 0; m < M_model->mMaxM(q); ++m )
2453  {
2454  M_Mqm_pr[q][m].conservativeResize( M_N, M_N );
2455  M_Mqm_du[q][m].conservativeResize( M_N, M_N );
2456  M_Mqm_pr_du[q][m].conservativeResize( M_N, M_N );
2457 
2458  // only compute the last line and last column of reduced matrices
2459  for ( size_type i=M_N-number_of_added_elements ; i < M_N; i++ )
2460  {
2461  for ( size_type j = 0; j < M_N; ++j )
2462  {
2463  M_Mqm_pr[q][m]( i, j ) = M_model->Mqm(q , m , M_WN[i], M_WN[j] );
2464  M_Mqm_du[q][m]( i, j ) = M_model->Mqm(q , m , M_WNdu[i], M_WNdu[j], true );
2465  M_Mqm_pr_du[q][m]( i, j ) = M_model->Mqm( q , m , M_WNdu[i], M_WN[j] );
2466  }
2467  }
2468  for ( size_type j = M_N-number_of_added_elements; j < M_N ; j++ )
2469  {
2470  for ( size_type i = 0; i < M_N; ++i )
2471  {
2472  M_Mqm_pr[q][m]( i, j ) = M_model->Mqm(q , m , M_WN[i], M_WN[j] );
2473  M_Mqm_du[q][m]( i, j ) = M_model->Mqm(q , m , M_WNdu[i], M_WNdu[j], true );
2474  M_Mqm_pr_du[q][m]( i, j ) = M_model->Mqm(q , m , M_WNdu[i], M_WN[j] );
2475  }
2476  }
2477  }//loop over m
2478  }//loop over q
2479 
2480  LOG(INFO) << "[CRB::offline] compute Lq_pr, Lq_du" << "\n";
2481 
2482  for ( size_type q = 0; q < M_model->Ql( M_output_index ); ++q )
2483  {
2484  for( size_type m = 0; m < M_model->mMaxF( M_output_index, q ); ++m )
2485  {
2486  M_Lqm_pr[q][m].conservativeResize( M_N );
2487  M_Lqm_du[q][m].conservativeResize( M_N );
2488 
2489  for ( size_type l = 1; l <= number_of_added_elements; ++l )
2490  {
2491  int index = M_N-l;
2492  M_Lqm_pr[q][m]( index ) = M_model->Fqm( M_output_index, q, m, M_WN[index] );
2493  M_Lqm_du[q][m]( index ) = M_model->Fqm( M_output_index, q, m, M_WNdu[index] );
2494  }
2495  }//loop over m
2496  }//loop over q
2497 
2498 
2499  LOG(INFO) << "compute coefficients needed for the initialization of unknown in the online step\n";
2500 
2501  element_ptrtype primal_initial_field ( new element_type ( M_model->functionSpace() ) );
2502  element_ptrtype projection ( new element_type ( M_model->functionSpace() ) );
2503  M_model->initializationField( primal_initial_field, mu ); //fill initial_field
2504  if ( model_type::is_time_dependent || !M_model->isSteady() )
2505  {
2506  if ( orthonormalize_primal )
2507  {
2508  for ( size_type elem=M_N-number_of_added_elements; elem<M_N; elem++ )
2509  {
2510  //primal
2511  double k = M_model->scalarProduct( *primal_initial_field, M_WN[elem] );
2512  M_coeff_pr_ini_online.push_back( k );
2513  }
2514  }
2515 
2516  else if ( !orthonormalize_primal )
2517  {
2518  matrixN_type MN ( ( int )M_N, ( int )M_N ) ;
2519  vectorN_type FN ( ( int )M_N );
2520 
2521  //primal
2522  for ( size_type i=0; i<M_N; i++ )
2523  {
2524  for ( size_type j=0; j<i; j++ )
2525  {
2526  MN( i,j ) = M_model->scalarProduct( M_WN[j] , M_WN[i] );
2527  MN( j,i ) = MN( i,j );
2528  }
2529 
2530  MN( i,i ) = M_model->scalarProduct( M_WN[i] , M_WN[i] );
2531  FN( i ) = M_model->scalarProduct( *primal_initial_field,M_WN[i] );
2532  }
2533 
2534  vectorN_type projectionN ( ( int ) M_N );
2535  projectionN = MN.lu().solve( FN );
2536 
2537  for ( size_type i=M_N-number_of_added_elements; i<M_N; i++ )
2538  {
2539  M_coeff_pr_ini_online.push_back( projectionN( i ) );
2540  }
2541  }
2542 
2543  if ( solve_dual_problem )
2544  {
2545  if ( orthonormalize_dual )
2546  {
2547  for ( size_type elem=M_N-number_of_added_elements; elem<M_N; elem++ )
2548  {
2549  double k = M_model->scalarProduct( *dual_initial_field, M_WNdu[elem] );
2550  M_coeff_du_ini_online.push_back( k );
2551  }
2552  }
2553 
2554  else if ( !orthonormalize_dual )
2555  {
2556  matrixN_type MNdu ( ( int )M_N, ( int )M_N ) ;
2557  vectorN_type FNdu ( ( int )M_N );
2558 
2559  //dual
2560  for ( size_type i=0; i<M_N; i++ )
2561  {
2562  for ( size_type j=0; j<i; j++ )
2563  {
2564  MNdu( i,j ) = M_model->scalarProduct( M_WNdu[j] , M_WNdu[i] );
2565  MNdu( j,i ) = MNdu( i,j );
2566  }
2567 
2568  MNdu( i,i ) = M_model->scalarProduct( M_WNdu[i] , M_WNdu[i] );
2569  FNdu( i ) = M_model->scalarProduct( *dual_initial_field,M_WNdu[i] );
2570  }
2571 
2572  vectorN_type projectionN ( ( int ) M_N );
2573  projectionN = MNdu.lu().solve( FNdu );
2574 
2575  for ( size_type i=M_N-number_of_added_elements; i<M_N; i++ )
2576  {
2577  M_coeff_du_ini_online.push_back( projectionN( i ) );
2578  }
2579  }
2580  }
2581  }
2582 
2583  timer2.restart();
2584 
2585  M_compute_variance = this->vm()["crb.compute-variance"].template as<bool>();
2586  if ( M_database_contains_variance_info )
2587  throw std::logic_error( "[CRB::offline] ERROR : build variance is not actived" );
2588  //buildVarianceMatrixPhi( M_N );
2589 
2590  if ( M_error_type==CRB_RESIDUAL || M_error_type == CRB_RESIDUAL_SCM )
2591  {
2592  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
2593  std::cout << " -- offlineResidual update starts\n";
2594  offlineResidual( M_N, number_of_added_elements );
2595  LOG(INFO)<<"[CRB::offline] end of call offlineResidual and M_N = "<< M_N <<"\n";
2596  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
2597  std::cout << " -- offlineResidual updated in " << timer2.elapsed() << "s\n";
2598  timer2.restart();
2599  }
2600 
2601 
2602  if ( M_error_type == CRB_NO_RESIDUAL && ! use_predefined_WNmu )
2603  {
2604  //M_maxerror=M_iter_max-M_N;
2605 
2606  bool already_exist;
2607  do
2608  {
2609  //initialization
2610  already_exist=false;
2611  //pick randomly an element
2612  mu = M_Dmu->element();
2613  //make sure that the new mu is not already is M_WNmu
2614  BOOST_FOREACH( auto _mu, *M_WNmu )
2615  {
2616  if( mu == _mu )
2617  already_exist=true;
2618  }
2619  }
2620  while( already_exist );
2621 
2622  M_current_mu = mu;
2623  }
2624  else if ( use_predefined_WNmu )
2625  {
2626  //remmber that in this case M_iter_max = sampling size
2627  if( M_N < M_iter_max )
2628  {
2629  mu = M_WNmu->at( M_N );
2630  M_current_mu = mu;
2631  }
2632  }
2633  else
2634  {
2635  boost::tie( M_maxerror, mu, index , delta_pr , delta_du ) = maxErrorBounds( M_N );
2636 
2637  M_index.push_back( index );
2638  M_current_mu = mu;
2639 
2640  int count = std::count( M_index.begin(),M_index.end(),index );
2641  M_mode_number = count;
2642 
2643  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
2644  std::cout << " -- max error bounds computed in " << timer2.elapsed() << "s\n";
2645 
2646  timer2.restart();
2647  }
2648 
2649  M_rbconv.insert( convergence( M_N, boost::make_tuple(M_maxerror,delta_pr,delta_du) ) );
2650 
2651  //mu = M_Xi->at( M_N );//M_WNmu_complement->min().template get<0>();
2652 
2653  check( M_WNmu->size() );
2654 
2655  if ( this->vm()["crb.check.rb"].template as<int>() == 1 )std::cout << " -- check reduced basis done in " << timer2.elapsed() << "s\n";
2656 
2657  timer2.restart();
2658  LOG(INFO) << "time: " << timer.elapsed() << "\n";
2659  if( proc_number == 0 ) std::cout << "============================================================\n";
2660  LOG(INFO) <<"========================================"<<"\n";
2661 
2662  //save DB after adding an element
2663  this->saveDB();
2664  M_elements_database.setWn( boost::make_tuple( M_WN , M_WNdu ) );
2665  M_elements_database.saveDB();
2666 
2667  }
2668 
2669  if( proc_number == 0 )
2670  std::cout<<"number of elements in the reduced basis : "<<M_N<<" ( nb proc : "<<worldComm().globalSize()<<")"<<std::endl;
2671  LOG(INFO) << " index choosen : ";
2672  BOOST_FOREACH( auto id, M_index )
2673  LOG(INFO)<<id<<" ";
2674  LOG(INFO)<<"\n";
2675  bool visualize_basis = this->vm()["crb.visualize-basis"].template as<bool>() ;
2676 
2677  if ( visualize_basis )
2678  {
2679  std::vector<wn_type> wn;
2680  std::vector<std::string> names;
2681  wn.push_back( M_WN );
2682  names.push_back( "primal" );
2683  wn.push_back( M_WNdu );
2684  names.push_back( "dual" );
2685  exportBasisFunctions( boost::make_tuple( wn ,names ) );
2686 
2687  if ( orthonormalize_primal || orthonormalize_dual )
2688  {
2689  std::cout<<"[CRB::offline] Basis functions have been exported but warning elements have been orthonormalized"<<std::endl;
2690  }
2691  }
2692 
2693 
2694  // this->saveDB();
2695  //if( proc_number == 0 ) std::cout << "Offline CRB is done\n";
2696 
2697  return M_rbconv;
2698 
2699 }
2700 
2701 
2702 template<typename TruthModelType>
2703 void
2704 CRB<TruthModelType>::checkInitialGuess( const element_type expansion_uN , parameter_type const& mu, vectorN_type & error) const
2705 {
2706  static const bool is_composite = functionspace_type::is_composite;
2707  checkInitialGuess( expansion_uN, mu, error , mpl::bool_< is_composite >() );
2708 }
2709 
2710 template<typename TruthModelType>
2711 void
2712 CRB<TruthModelType>::checkInitialGuess( const element_type expansion_uN , parameter_type const& mu, vectorN_type & error, mpl::bool_<false>) const
2713 {
2714  error.resize(1);
2715  const element_ptrtype initial_guess = M_model->assembleInitialGuess( mu );
2716  auto Xh = expansion_uN.functionSpace();
2717  auto mesh = Xh->mesh();
2718  error(0) = math::sqrt(
2719  integrate( _range=elements(mesh) ,
2720  _expr=vf::idv( initial_guess ) * vf::idv( expansion_uN )
2721  * vf::idv( initial_guess ) * vf::idv( expansion_uN )
2722  ).evaluate()(0,0)
2723  );
2724 
2725 
2726 }
2727 
2728 template<typename TruthModelType>
2729 void
2730 CRB<TruthModelType>::checkInitialGuess( const element_type expansion_uN , parameter_type const& mu, vectorN_type & error, mpl::bool_<true>) const
2731 {
2732  //using namespace Feel::vf;
2733  index_vector_type index_vector;
2734  const element_ptrtype initial_guess = M_model->assembleInitialGuess( mu );
2735  ComputeIntegralsSquare compute_integrals_square( *initial_guess , expansion_uN );
2736  fusion::for_each( index_vector , compute_integrals_square );
2737  error.resize( functionspace_type::nSpaces );
2738  error = compute_integrals_square.vectorErrors();
2739 
2740 }
2741 
2742 
2743 template<typename TruthModelType>
2744 void
2745 CRB<TruthModelType>::buildVarianceMatrixPhi( int const N )
2746 {
2747  static const bool is_composite = functionspace_type::is_composite;
2748  return buildVarianceMatrixPhi( N , mpl::bool_< is_composite >() );
2749 }
2750 template<typename TruthModelType>
2751 void
2752 CRB<TruthModelType>::buildVarianceMatrixPhi( int const N , mpl::bool_<true> )
2753 {
2754 
2755  std::vector<std::string> s;
2756  static const int nb_spaces = functionspace_type::nSpaces;
2757 
2758  if( N == 1 )
2759  M_variance_matrix_phi.resize( nb_spaces );
2760 
2761 
2762  for(int i=0;i<nb_spaces;i++)
2763  M_variance_matrix_phi[i].conservativeResize( M_N , M_N );
2764 
2765  //introduction of the new variable phi
2766  int size_WN = M_WN.size();
2767  wn_type phi;
2768 
2769  for(int i = 0; i < size_WN; ++i)
2770  {
2771  auto sub = subelements( M_WN[i] , s );
2772  element_type global_element = M_model->functionSpace()->element();
2773  wn_type v( nb_spaces , global_element);
2774  ComputePhi compute_phi(v);
2775  fusion::for_each( sub , compute_phi ) ;
2776  auto vect = compute_phi.vectorPhi();
2777 
2778  //now we want to have only one element_type (global_element)
2779  //which sum the contribution of each space
2780  global_element.zero();
2781  BOOST_FOREACH( auto element , vect )
2782  global_element += element;
2783  phi.push_back( global_element );
2784  }
2785 
2786 
2787  index_vector_type index_vector;
2788  for(int space=0; space<nb_spaces; space++)
2789  M_variance_matrix_phi[space].conservativeResize( N , N );
2790 
2791 
2792  for(int i = 0; i < M_N; ++i)
2793  {
2794 
2795  for(int j = i+1; j < M_N; ++j)
2796  {
2797  ComputeIntegrals compute_integrals( phi[i] , phi[j] );
2798  fusion::for_each( index_vector , compute_integrals );
2799  auto vect = compute_integrals.vectorIntegrals();
2800  for(int space=0; space<nb_spaces; space++)
2801  M_variance_matrix_phi[space](i,j)=vect[space];
2802  } //j
2803  ComputeIntegrals compute_integrals ( phi[i] , phi[i] );
2804  fusion::for_each( index_vector , compute_integrals );
2805  auto vect = compute_integrals.vectorIntegrals();
2806  for(int space=0; space<nb_spaces; space++)
2807  M_variance_matrix_phi[space](i,i)=vect[space];
2808  }// i
2809 
2810 }
2811 
2812 
2813 template<typename TruthModelType>
2814 void
2815 CRB<TruthModelType>::buildVarianceMatrixPhi( int const N , mpl::bool_<false> )
2816 {
2817  std::vector<std::string> s;
2818  int nb_spaces = functionspace_type::nSpaces;
2819 
2820  if( N == 1 )
2821  M_variance_matrix_phi.resize( nb_spaces );
2822 
2823  M_variance_matrix_phi[0].conservativeResize( M_N , M_N );
2824 
2825  //introduction of the new variable phi
2826  int size_WN = M_WN.size();
2827  //wn_type phi ( size_WN );
2828  wn_type phi;
2829 
2830  mesh_ptrtype mesh = M_WN[0].functionSpace()->mesh();
2831 
2832  for(int i = 0; i < size_WN; ++i)
2833  {
2834  double surface = integrate( _range=elements(mesh), _expr=vf::cst(1.) ).evaluate()(0,0);
2835  double mean = integrate( _range=elements(mesh), _expr=vf::idv( M_WN[i] ) ).evaluate()(0,0);
2836  mean /= surface;
2837  auto element_mean = vf::project(M_WN[i].functionSpace(), elements(mesh), vf::cst(mean) );
2838  phi.push_back( M_WN[i] - element_mean );
2839  }
2840 
2841  for(int space=0; space<nb_spaces; space++)
2842  M_variance_matrix_phi[space].conservativeResize( N , N );
2843 
2844  for(int i = 0; i < M_N; ++i)
2845  {
2846  for(int j = i+1; j < M_N; ++j)
2847  {
2848  M_variance_matrix_phi[0]( i , j ) = integrate( _range=elements(mesh) , _expr=vf::idv( phi[i] ) * vf::idv( phi[j] ) ).evaluate()(0,0);
2849  M_variance_matrix_phi[0]( j , i ) = M_variance_matrix_phi[0]( i , j );
2850  } //j
2851 
2852  M_variance_matrix_phi[0]( i , i ) = integrate( _range=elements(mesh) , _expr=vf::idv( phi[i] ) * vf::idv( phi[i] ) ).evaluate()(0,0);
2853  }// i
2854 
2855 }
2856 
2857 
2858 
2859 template<typename TruthModelType>
2860 void
2861 CRB<TruthModelType>::buildFunctionFromRbCoefficients(int N, std::vector< vectorN_type > const & RBcoeff, wn_type const & WN, std::vector<element_ptrtype> & FEMsolutions )
2862 {
2863 
2864  if( WN.size() == 0 )
2865  throw std::logic_error( "[CRB::buildFunctionFromRbCoefficients] ERROR : reduced basis space is empty" );
2866 
2867 
2868  int nb_solutions = RBcoeff.size();
2869 
2870  for( int i = 0; i < nb_solutions; i++ )
2871  {
2872  element_ptrtype FEMelement ( new element_type( M_model->functionSpace() ) );
2873  FEMelement->setZero();
2874  for( int j = 0; j < N; j++ )
2875  FEMelement->add( RBcoeff[i](j) , WN[j] );
2876  FEMsolutions.push_back( FEMelement );
2877  }
2878 }
2879 
2880 template<typename TruthModelType>
2881 void
2882 CRB<TruthModelType>::compareResidualsForTransientProblems( int N, parameter_type const& mu, std::vector<element_type> const & Un, std::vector<element_type> const & Unold,
2883  std::vector<element_type> const& Undu, std::vector<element_type> const & Unduold,
2884  std::vector< std::vector<double> > const& primal_residual_coeffs, std::vector < std::vector<double> > const& dual_residual_coeffs ) const
2885 {
2886 
2887  LOG( INFO ) <<"\n compareResidualsForTransientProblems \n";
2888  backend_ptrtype backend = backend_type::build( BACKEND_PETSC ) ;
2889 
2890  if ( M_model->isSteady() )
2891  {
2892  throw std::logic_error( "[CRB::compareResidualsForTransientProblems] ERROR : to check residual in a steady case, use checkResidual and not compareResidualsForTransientProblems" );
2893  }
2894 
2895  sparse_matrix_ptrtype A,AM,M,Adu;
2896  //vector_ptrtype MF;
2897  std::vector<vector_ptrtype> F,L;
2898 
2899  vector_ptrtype Rhs( backend->newVector( M_model->functionSpace() ) );
2900  vector_ptrtype Aun( backend->newVector( M_model->functionSpace() ) );
2901  vector_ptrtype AduUn( backend->newVector( M_model->functionSpace() ) );
2902 
2903  vector_ptrtype Mun( backend->newVector( M_model->functionSpace() ) );
2904  vector_ptrtype Munold( backend->newVector( M_model->functionSpace() ) );
2905  vector_ptrtype Frhs( backend->newVector( M_model->functionSpace() ) );
2906  vector_ptrtype un( backend->newVector( M_model->functionSpace() ) );
2907  vector_ptrtype unold( backend->newVector( M_model->functionSpace() ) );
2908  vector_ptrtype undu( backend->newVector( M_model->functionSpace() ) );
2909  vector_ptrtype unduold( backend->newVector( M_model->functionSpace() ) );
2910 
2911  //set parameters for time discretization
2912  auto bdf_primal = bdf( _space=M_model->functionSpace(), _vm=this->vm() , _name="bdf_primal_check_residual_transient" );
2913  bdf_primal->setTimeInitial( M_model->timeInitial() );
2914  bdf_primal->setTimeStep( M_model->timeStep() );
2915  bdf_primal->setTimeFinal( M_model->timeFinal() );
2916  bdf_primal->setOrder( M_model->timeOrder() );
2917 
2918 
2919  double time_step = bdf_primal->timeStep();
2920  int time_index=0;
2921  for ( bdf_primal->start() ; !bdf_primal->isFinished(); bdf_primal->next() )
2922  {
2923 
2924  auto bdf_poly = bdf_primal->polyDeriv();
2925  boost::tie( M, A, F) = M_model->update( mu , bdf_primal->time() );
2926 
2927  A->close();
2928 
2929  *un = Un[time_index];
2930  *unold = Unold[time_index];
2931 
2932  A->multVector( un, Aun );
2933  M->multVector( un, Mun );
2934 
2935  M->multVector( unold, Munold );
2936  Aun->scale( -1 );
2937  Mun->scale( -1 );
2938  *Frhs = *F[0];
2939 
2940  vector_ptrtype __ef_pr( backend->newVector( M_model->functionSpace() ) );
2941  vector_ptrtype __ea_pr( backend->newVector( M_model->functionSpace() ) );
2942  vector_ptrtype __emu_pr( backend->newVector( M_model->functionSpace() ) );
2943  vector_ptrtype __emuold_pr( backend->newVector( M_model->functionSpace() ) );
2944  M_model->l2solve( __ef_pr, Frhs );
2945  M_model->l2solve( __ea_pr, Aun );
2946  M_model->l2solve( __emu_pr, Mun );
2947  M_model->l2solve( __emuold_pr, Munold );
2948 
2949  double check_Cff_pr = M_model->scalarProduct( __ef_pr,__ef_pr );
2950  double check_Caf_pr = 2*M_model->scalarProduct( __ef_pr,__ea_pr );
2951  double check_Caa_pr = M_model->scalarProduct( __ea_pr,__ea_pr );
2952  double check_Cmf_pr = 2./time_step*( M_model->scalarProduct( __emu_pr , __ef_pr )+M_model->scalarProduct( __emuold_pr , __ef_pr ) );
2953  double check_Cma_pr = 2./time_step*( M_model->scalarProduct( __emu_pr , __ea_pr )+M_model->scalarProduct( __emuold_pr , __ea_pr ) );
2954  double check_Cmm_pr = 1./(time_step*time_step)*( M_model->scalarProduct( __emu_pr , __emu_pr ) + 2*M_model->scalarProduct( __emu_pr , __emuold_pr ) + M_model->scalarProduct( __emuold_pr , __emuold_pr ) );
2955 
2956  double Cff_pr = primal_residual_coeffs[time_index][0];
2957  double Caf_pr = primal_residual_coeffs[time_index][1];
2958  double Caa_pr = primal_residual_coeffs[time_index][2];
2959  double Cmf_pr = primal_residual_coeffs[time_index][3];
2960  double Cma_pr = primal_residual_coeffs[time_index][4];
2961  double Cmm_pr = primal_residual_coeffs[time_index][5];
2962 
2963  LOG(INFO)<<" --- time : "<<bdf_primal->time();
2964  LOG(INFO)<<"Cff : "<< check_Cff_pr <<" - "<<Cff_pr<<" => "<<check_Cff_pr-Cff_pr;
2965  LOG(INFO)<<"Caf : "<< check_Caf_pr <<" - "<<Caf_pr<<" => "<<check_Caf_pr-Caf_pr;
2966  LOG(INFO)<<"Caa : "<< check_Caa_pr <<" - "<<Caa_pr<<" => "<<check_Caa_pr-Caa_pr;
2967  LOG(INFO)<<"Cmf : "<< check_Cmf_pr <<" - "<<Cmf_pr<<" => "<<check_Cmf_pr-Cmf_pr;
2968  LOG(INFO)<<"Cma : "<< check_Cma_pr <<" - "<<Cma_pr<<" => "<<check_Cma_pr-Cma_pr;
2969  LOG(INFO)<<"Cmm : "<< check_Cmm_pr <<" - "<<Cmm_pr<<" => "<<check_Cmm_pr-Cmm_pr;
2970  time_index++;
2971  }
2972 
2973  time_index--;
2974 
2975  bool solve_dual_problem = this->vm()["crb.solve-dual-problem"].template as<bool>();
2976  //if( this->worldComm().globalSize() > 1 )
2977  // solve_dual_problem=false;
2978 
2979  double sum=0;
2980  if( solve_dual_problem )
2981  {
2982 
2983  Adu = M_model->newMatrix();
2984 
2985  auto bdf_dual = bdf( _space=M_model->functionSpace(), _vm=this->vm() , _name="bdf_dual_check_residual_transient" );
2986 
2987  bdf_dual->setTimeInitial( M_model->timeFinal()+M_model->timeStep() );
2988  bdf_dual->setTimeStep( -M_model->timeStep() );
2989  bdf_dual->setTimeFinal( M_model->timeInitial()+M_model->timeStep() );
2990  bdf_dual->setOrder( M_model->timeOrder() );
2991  bdf_dual->start();
2992 
2993  //element_ptrtype dual_initial_field( new element_type( M_model->functionSpace() ) );
2994  LOG(INFO)<<"**********dual problem************* "<<std::endl;
2995 
2996  boost::tie( M, A, F) = M_model->update( mu , bdf_dual->timeInitial() );
2997 
2998  vectorN_type dual_initial ( N );
2999  for(int i=0; i<N; i++)
3000  dual_initial(i) = M_coeff_du_ini_online[i];
3001  auto dual_initial_field = this->expansion( dual_initial , N , M_WNdu );
3002 
3003  *undu = dual_initial_field;
3004  M->multVector( undu, Mun );
3005  *Frhs = *F[0];
3006 
3007 
3008  auto R = backend->newVector( M_model->functionSpace() );
3009  R = Frhs;
3010  R->add( -1 , *Mun ); //R -= Mun;
3011  //std::cout<<"[COMPARE] R->l2Norm() : "<<R->l2Norm()<<std::endl;
3012 
3013  vector_ptrtype __ef_du( backend->newVector( M_model->functionSpace() ) );
3014  vector_ptrtype __emu_du( backend->newVector( M_model->functionSpace() ) );
3015  M_model->l2solve( __ef_du, Frhs );
3016  M_model->l2solve( __emu_du, Mun );
3017  double check_Cff_du = M_model->scalarProduct( __ef_du,__ef_du );
3018  double check_Cmf_du = 2*M_model->scalarProduct( __ef_du,__emu_du );
3019  double check_Cmm_du = M_model->scalarProduct( __emu_du,__emu_du );
3020  double residual_final_condition = math::abs( check_Cff_du + check_Cmf_du + check_Cmm_du );
3021  //std::cout<<"residual on final condition : "<<residual_final_condition<<std::endl;
3022  //initialization
3023  time_step = bdf_dual->timeStep();
3024 
3025 
3026  for ( bdf_dual->start(); !bdf_dual->isFinished() ; bdf_dual->next() )
3027  {
3028  auto bdf_poly = bdf_dual->polyDeriv();
3029 
3030  boost::tie( M, A, F ) = M_model->update( mu , bdf_dual->time() );
3031  if( option("crb.use-symmetric-matrix").template as<bool>() )
3032  Adu = A;
3033  else
3034  A->transpose( Adu );
3035  *undu = Undu[time_index];
3036  *unduold = Unduold[time_index];
3037  Adu->multVector( undu, AduUn );
3038  M->multVector( undu, Mun );
3039  M->multVector( unduold, Munold );
3040  AduUn->scale( -1 );
3041  Munold->scale( -1 );
3042  *Frhs = *F[0];
3043 
3044  vector_ptrtype __ea_du( backend->newVector( M_model->functionSpace() ) );
3045  vector_ptrtype __emu_du( backend->newVector( M_model->functionSpace() ) );
3046  vector_ptrtype __emuold_du( backend->newVector( M_model->functionSpace() ) );
3047  M_model->l2solve( __ea_du, AduUn );
3048  M_model->l2solve( __emu_du, Mun );
3049  M_model->l2solve( __emuold_du, Munold );
3050  double check_Caa_du = M_model->scalarProduct( __ea_du,__ea_du );
3051  double check_Cma_du = 2./time_step*( M_model->scalarProduct( __emu_du , __ea_du )+M_model->scalarProduct( __emuold_du , __ea_du ) );
3052  double check_Cmm_du = 1./(time_step*time_step)*( M_model->scalarProduct( __emu_du , __emu_du ) + 2*M_model->scalarProduct( __emu_du , __emuold_du ) + M_model->scalarProduct( __emuold_du , __emuold_du ) );
3053 
3054 
3055  double Cff_du = dual_residual_coeffs[time_index][0];
3056  double Caf_du = dual_residual_coeffs[time_index][1];
3057  double Caa_du = dual_residual_coeffs[time_index][2];
3058  double Cmf_du = dual_residual_coeffs[time_index][3];
3059  double Cma_du = dual_residual_coeffs[time_index][4];
3060  double Cmm_du = dual_residual_coeffs[time_index][5];
3061  LOG(INFO)<<" --- time : "<<bdf_dual->time()<<std::endl;
3062  LOG(INFO)<<"Caa : "<< check_Caa_du <<" - "<<Caa_du<<" => "<<check_Caa_du-Caa_du<<std::endl;
3063  LOG(INFO)<<"Cma : "<< check_Cma_du <<" - "<<Cma_du<<" => "<<check_Cma_du-Cma_du<<std::endl;
3064  LOG(INFO)<<"Cmm : "<< check_Cmm_du <<" - "<<Cmm_du<<" => "<<check_Cmm_du-Cmm_du<<std::endl;
3065  time_index--;
3066  //std::cout<<"[CHECK] ------ time "<<bdf_dual->time()<<std::endl;
3067  //std::cout<<"[CHECK] Caa_du : "<<check_Caa_du<<std::endl;
3068  //std::cout<<"[CHECK] Cma_du : "<<check_Cma_du<<std::endl;
3069  //std::cout<<"[CHECK] Cmm_du : "<<check_Cmm_du<<std::endl;
3070  sum += math::abs( check_Caa_du + check_Cma_du + check_Cmm_du );
3071  }
3072  //std::cout<<"[CHECK] dual_sum : "<<sum<<std::endl;
3073  }//solve-dual-problem
3074 }
3075 
3076 
3077 template<typename TruthModelType>
3078 void
3079 CRB<TruthModelType>::checkResidual( parameter_type const& mu, std::vector< std::vector<double> > const& primal_residual_coeffs,
3080  std::vector< std::vector<double> > const& dual_residual_coeffs , element_type & u, element_type & udu ) const
3081 {
3082 
3083 
3084  if ( orthonormalize_primal || orthonormalize_dual )
3085  {
3086  throw std::logic_error( "[CRB::checkResidual] ERROR : to check residual don't use orthonormalization" );
3087  }
3088 
3089  if ( !M_model->isSteady() )
3090  {
3091  throw std::logic_error( "[CRB::checkResidual] ERROR : to check residual select steady state" );
3092  }
3093 
3094  if ( M_error_type==CRB_NO_RESIDUAL || M_error_type==CRB_EMPIRICAL )
3095  {
3096  throw std::logic_error( "[CRB::checkResidual] ERROR : to check residual set option crb.error-type to 0 or 1" );
3097  }
3098 
3099  int size = mu.size();
3100 
3101  if ( 0 )
3102  {
3103  std::cout<<"[CRB::checkResidual] use mu = [";
3104  for ( int i=0; i<size-1; i++ ) std::cout<< mu[i] <<" , ";
3105  std::cout<< mu[size-1]<<" ]"<<std::endl;
3106  }
3107 
3108  LOG( INFO ) <<"[CRB::checkResidual] use mu = \n"<<mu;
3109  sparse_matrix_ptrtype A,At,M;
3110  std::vector<vector_ptrtype> F,L;
3111 
3112  //backend_ptrtype backendA = backend_type::build( BACKEND_PETSC );
3113  //backend_ptrtype backendAt = backend_type::build( BACKEND_PETSC );
3114 
3115  //element_ptrtype u( new element_type( M_model->functionSpace() ) );
3116  //element_ptrtype udu( new element_type( M_model->functionSpace() ) );
3117  vector_ptrtype U( M_backend->newVector( M_model->functionSpace() ) );
3118  vector_ptrtype Rhs( M_backend->newVector( M_model->functionSpace() ) );
3119 
3120  boost::timer timer, timer2;
3121 
3122  boost::tie( boost::tuples::ignore, A, F ) = M_model->update( mu );
3123 
3124  LOG(INFO) << " -- updated model for parameter in " << timer2.elapsed() << "s\n";
3125  timer2.restart();
3126 
3127  LOG(INFO) << "[CRB::checkResidual] transpose primal matrix" << "\n";
3128  At = M_model->newMatrix();
3129  if( option("crb.use-symmetric-matrix").template as<bool>() )
3130  At = A;
3131  else
3132  A->transpose( At );
3133  //u->setName( ( boost::format( "fem-primal-%1%" ) % ( M_N ) ).str() );
3134  //udu->setName( ( boost::format( "fem-dual-%1%" ) % ( M_N ) ).str() );
3135 
3136  //LOG(INFO) << "[CRB::checkResidual] solving primal" << "\n";
3137  //backendA->solve( _matrix=A, _solution=u, _rhs=F[0] );
3138  //LOG(INFO) << " -- primal problem solved in " << timer2.elapsed() << "s\n";
3139  timer2.restart();
3140  *Rhs = *F[M_output_index];
3141  Rhs->scale( -1 );
3142  //backendAt->solve( _matrix=At, _solution=udu, _rhs=Rhs );
3143  //LOG(INFO) << " -- dual problem solved in " << timer2.elapsed() << "s\n";
3144  timer2.restart();
3145 
3146  vector_ptrtype Aun( M_backend->newVector( M_model->functionSpace() ) );
3147  vector_ptrtype Atun( M_backend->newVector( M_model->functionSpace() ) );
3148  vector_ptrtype Un( M_backend->newVector( M_model->functionSpace() ) );
3149  vector_ptrtype Undu( M_backend->newVector( M_model->functionSpace() ) );
3150  vector_ptrtype Frhs( M_backend->newVector( M_model->functionSpace() ) );
3151  vector_ptrtype Lrhs( M_backend->newVector( M_model->functionSpace() ) );
3152  *Un = u;
3153  *Undu = udu;
3154  A->multVector( Un, Aun );
3155  At->multVector( Undu, Atun );
3156  Aun->scale( -1 );
3157  Atun->scale( -1 );
3158  *Frhs = *F[0];
3159  *Lrhs = *F[M_output_index];
3160  LOG(INFO) << "[CRB::checkResidual] residual (f,f) " << M_N-1 << ":=" << M_model->scalarProduct( Frhs, Frhs ) << "\n";
3161  LOG(INFO) << "[CRB::checkResidual] residual (f,A) " << M_N-1 << ":=" << 2*M_model->scalarProduct( Frhs, Aun ) << "\n";
3162  LOG(INFO) << "[CRB::checkResidual] residual (A,A) " << M_N-1 << ":=" << M_model->scalarProduct( Aun, Aun ) << "\n";
3163 
3164  LOG(INFO) << "[CRB::checkResidual] residual (l,l) " << M_N-1 << ":=" << M_model->scalarProduct( Lrhs, Lrhs ) << "\n";
3165  LOG(INFO) << "[CRB::checkResidual] residual (l,At) " << M_N-1 << ":=" << 2*M_model->scalarProduct( Lrhs, Atun ) << "\n";
3166  LOG(INFO) << "[CRB::checkResidual] residual (At,At) " << M_N-1 << ":=" << M_model->scalarProduct( Atun, Atun ) << "\n";
3167 
3168 
3169  Lrhs->scale( -1 );
3170 
3171 
3172  vector_ptrtype __ef_pr( M_backend->newVector( M_model->functionSpace() ) );
3173  vector_ptrtype __ea_pr( M_backend->newVector( M_model->functionSpace() ) );
3174  M_model->l2solve( __ef_pr, Frhs );
3175  M_model->l2solve( __ea_pr, Aun );
3176  double check_C0_pr = M_model->scalarProduct( __ef_pr,__ef_pr );
3177  double check_Lambda_pr = 2*M_model->scalarProduct( __ef_pr,__ea_pr );
3178  double check_Gamma_pr = M_model->scalarProduct( __ea_pr,__ea_pr );
3179 
3180  vector_ptrtype __ef_du( M_backend->newVector( M_model->functionSpace() ) );
3181  vector_ptrtype __ea_du( M_backend->newVector( M_model->functionSpace() ) );
3182  M_model->l2solve( __ef_du, Lrhs );
3183  M_model->l2solve( __ea_du, Atun );
3184  double check_C0_du = M_model->scalarProduct( __ef_du,__ef_du );
3185  double check_Lambda_du = 2*M_model->scalarProduct( __ef_du,__ea_du );
3186  double check_Gamma_du = M_model->scalarProduct( __ea_du,__ea_du );
3187 
3188  double primal_sum = check_C0_pr + check_Lambda_pr + check_Gamma_pr ;
3189  double dual_sum = check_C0_du + check_Lambda_du + check_Gamma_du ;
3190 
3191  //LOG(INFO)<<"[CRB::checkResidual] primal_sum = "<<check_C0_pr<<" + "<<check_Lambda_pr<<" + "<<check_Gamma_pr<<" = "<<primal_sum<<"\n";
3192  //LOG(INFO)<<"[CRB::checkResidual] dual_sum = "<<check_C0_du<<" + "<<check_Lambda_du<<" + "<<check_Gamma_du<<" = "<<dual_sum<<"\n";
3193 
3194 
3195  int time_index=0;
3196  double C0_pr = primal_residual_coeffs[time_index][0];
3197  double Lambda_pr = primal_residual_coeffs[time_index][1];
3198  double Gamma_pr = primal_residual_coeffs[time_index][2];
3199 
3200  double C0_du,Lambda_du,Gamma_du;
3201  C0_du = dual_residual_coeffs[time_index][0];
3202  Lambda_du = dual_residual_coeffs[time_index][1];
3203  Gamma_du = dual_residual_coeffs[time_index][2];
3204 
3205  double err_C0_pr = math::abs( C0_pr - check_C0_pr ) ;
3206  double err_Lambda_pr = math::abs( Lambda_pr - check_Lambda_pr ) ;
3207  double err_Gamma_pr = math::abs( Gamma_pr - check_Gamma_pr ) ;
3208  double err_C0_du = math::abs( C0_du - check_C0_du ) ;
3209  double err_Lambda_du = math::abs( Lambda_du - check_Lambda_du ) ;
3210  double err_Gamma_du = math::abs( Gamma_du - check_Gamma_du ) ;
3211 
3212  int start_dual_index = 6;
3213 #if 1
3214  LOG(INFO)<<"[CRB::checkResidual]";
3215  LOG(INFO)<<"====primal coefficients==== ";
3216  LOG(INFO)<<" c0_pr \t\t lambda_pr \t\t gamma_pr";
3217  LOG(INFO)<<"computed : ";
3218  LOG(INFO)<<std::setprecision( 16 )<<primal_residual_coeffs[time_index][0]<<"\t"<<primal_residual_coeffs[time_index][1]<<"\t"<<primal_residual_coeffs[time_index][2];
3219 
3220  LOG(INFO)<<"\n";
3221  LOG(INFO)<<"true : ";
3222  LOG(INFO)<<std::setprecision( 16 )<<check_C0_pr<<"\t"<<check_Lambda_pr<<"\t"<<check_Gamma_pr;
3223  LOG(INFO)<<"====dual coefficients==== ";
3224  LOG(INFO)<<" c0_du \t\t lambda_du \t\t gamma_du";
3225  LOG(INFO)<<"computed : ";
3226 
3227  LOG(INFO)<<std::setprecision( 16 )<<dual_residual_coeffs[time_index][0]<<"\t"<<dual_residual_coeffs[time_index][1]<<"\t"<<dual_residual_coeffs[time_index][2];
3228 
3229  LOG(INFO)<<"\ntrue : ";
3230  LOG(INFO)<<std::setprecision( 16 )<<check_C0_du<<"\t"<<check_Lambda_du<<"\t"<<check_Gamma_du;
3231  LOG(INFO)<<std::setprecision( 16 )<<"primal_true_sum = "<<check_C0_pr+check_Lambda_pr+check_Gamma_pr;
3232  LOG(INFO)<<std::setprecision( 16 )<<"dual_true_sum = "<<check_C0_du+check_Lambda_du+check_Gamma_du;
3233 
3234  LOG(INFO)<<std::setprecision( 16 )<<"primal_computed_sum = "<<C0_pr+Lambda_pr+Gamma_pr;
3235  LOG(INFO)<<std::setprecision( 16 )<<"dual_computed_sum = "<<C0_du+Lambda_du+Gamma_du;
3236 
3237 #endif
3238  LOG(INFO)<<"errors committed on coefficients ";
3239  LOG(INFO)<<std::setprecision( 16 )<<"C0_pr : "<<err_C0_pr<<"\tLambda_pr : "<<err_Lambda_pr<<"\tGamma_pr : "<<err_Gamma_pr;
3240  LOG(INFO)<<std::setprecision( 16 )<<"C0_du : "<<err_C0_du<<"\tLambda_du : "<<err_Lambda_du<<"\tGamma_du : "<<err_Gamma_du;
3241  LOG(INFO)<<"and now relative error : ";
3242  double errC0pr = err_C0_pr/check_C0_pr;
3243  double errLambdapr = err_Lambda_pr/check_Lambda_pr;
3244  double errGammapr = err_Gamma_pr/check_Gamma_pr;
3245  double errC0du = err_C0_du/check_C0_du;
3246  double errLambdadu = err_Lambda_pr/check_Lambda_pr;
3247  double errGammadu = err_Gamma_pr/check_Gamma_pr;
3248  LOG(INFO)<<std::setprecision( 16 )<<errC0pr<<"\t"<<errLambdapr<<"\t"<<errGammapr;
3249  LOG(INFO)<<std::setprecision( 16 )<<errC0du<<"\t"<<errLambdadu<<"\t"<<errGammadu;
3250 
3251  //residual r(v)
3252  Aun->add( *Frhs );
3253  //Lrhs->scale( -1 );
3254  Atun->add( *Lrhs );
3255  //to have dual norm of residual we need to solve ( e , v ) = r(v) and then it's given by ||e||
3256  vector_ptrtype __e_pr( M_backend->newVector( M_model->functionSpace() ) );
3257  M_model->l2solve( __e_pr, Aun );
3258  double dual_norm_pr = math::sqrt ( M_model->scalarProduct( __e_pr,__e_pr ) );
3259  LOG(INFO)<<"[CRB::checkResidual] dual norm of primal residual without isolate terms (c0,lambda,gamma) = "<<dual_norm_pr<<"\n";
3260  //idem for the dual equation
3261  vector_ptrtype __e_du( M_backend->newVector( M_model->functionSpace() ) );
3262  M_model->l2solve( __e_du, Atun );
3263  double dual_norm_du = math::sqrt ( M_model->scalarProduct( __e_du,__e_du ) );
3264  LOG(INFO) <<"[CRB::checkResidual] dual norm of dual residual without isolate terms = "<<dual_norm_du<<"\n";
3265 #if 0
3266  double err_primal = math::sqrt ( M_model->scalarProduct( Aun, Aun ) );
3267  double err_dual = math::sqrt ( M_model->scalarProduct( Atun, Atun ) );
3268  LOG(INFO) << "[CRB::checkResidual] true primal residual for reduced basis function " << M_N-1 << ":=" << err_primal << "\n";
3269  LOG(INFO) << "[CRB::checkResidual] true dual residual for reduced basis function " << M_N-1 << ":=" << err_dual << "\n";
3270 #endif
3271 }
3272 
3273 
3274 template<typename TruthModelType>
3275 void
3277 {
3278 
3279  if ( this->vm()["crb.check.rb"].template as<int>() == 0)
3280  return;
3281 
3282  std::cout << " -- check reduced basis\n";
3283 
3284 
3285  LOG(INFO) << "----------------------------------------------------------------------\n";
3286 
3287  // check that for each mu associated to a basis function of \f$W_N\f$
3288  //for( int k = std::max(0,(int)N-2); k < N; ++k )
3289  for ( size_type k = 0; k < N; ++k )
3290  {
3291  LOG(INFO) << "**********************************************************************\n";
3292  parameter_type const& mu = M_WNmu->at( k );
3293  std::vector< vectorN_type > uN; //uN.resize( N );
3294  std::vector< vectorN_type > uNdu; //( N );
3295  std::vector< vectorN_type > uNold;
3296  std::vector< vectorN_type > uNduold;
3297  auto tuple = lb( N, mu, uN, uNdu, uNold, uNduold );
3298  double s = tuple.template get<0>();
3299  auto error_estimation = delta( N, mu, uN, uNdu , uNold, uNduold );
3300  double err = error_estimation.template get<0>() ;
3301 
3302 
3303 #if 0
3304  //if ( err > 1e-5 )
3305  // {
3306  std::cout << "[check] error bounds are not < 1e-10\n";
3307  std::cout << "[check] k = " << k << "\n";
3308  std::cout << "[check] mu = " << mu << "\n";
3309  std::cout << "[check] delta = " << err << "\n";
3310  std::cout << "[check] uN( " << k << " ) = " << uN( k ) << "\n";
3311 #endif
3312  // }
3313  element_type u_fem; bool need_to_solve=false;
3314  u_fem = M_model->solveFemUsingOfflineEim ( mu );
3315  double sfem = M_model->output( M_output_index, mu , u_fem , need_to_solve );
3316  int size = mu.size();
3317  std::cout<<" o mu = [ ";
3318 
3319  for ( int i=0; i<size-1; i++ ) std::cout<< mu[i] <<" , ";
3320 
3321  std::cout<< mu[size-1]<<" ]"<<std::endl;
3322 
3323  LOG(INFO) << "[check] s= " << s << " +- " << err << " | sfem= " << sfem << " | abs(sfem-srb) =" << math::abs( sfem - s ) << "\n";
3324  std::cout <<"[check] s = " << s << " +- " << err << " | sfem= " << sfem << " | abs(sfem-srb) =" << math::abs( sfem - s )<< "\n";
3325 
3326  }
3327 
3328  LOG(INFO) << "----------------------------------------------------------------------\n";
3329 
3330 }
3331 
3332 template<typename TruthModelType>
3333 void
3334 CRB<TruthModelType>::computeErrorEstimationEfficiencyIndicator ( parameterspace_ptrtype const& Dmu, double& max_ei, double& min_ei,int N )
3335 {
3336  std::vector< vectorN_type > uN; //( N );
3337  std::vector< vectorN_type > uNdu;//( N );
3338 
3339  //sampling of parameter space Dmu
3340  sampling_ptrtype Sampling;
3341  Sampling = sampling_ptrtype( new sampling_type( M_Dmu ) );
3342  //Sampling->equidistribute( N );
3343  Sampling->randomize( N );
3344  //Sampling->logEquidistribute( N );
3345 
3346  int RBsize = M_WNmu->size();
3347 
3348  y_type ei( Sampling->size() );
3349 
3350  for ( size_type k = 0; k < Sampling->size(); ++k )
3351  {
3352  parameter_type const& mu = M_Xi->at( k );
3353  double s = lb( RBsize, mu, uN, uNdu );//output
3354  element_type u_fem; bool need_to_solve = true;
3355  double sfem = M_model->output( M_output_index, mu , u_fem , need_to_solve); //true ouput
3356  double error_estimation = delta( RBsize,mu,uN,uNdu );
3357  ei( k ) = error_estimation/math::abs( sfem-s );
3358  std::cout<<" efficiency indicator = "<<ei( k )<<" for parameters {";
3359 
3360  for ( int i=0; i<mu.size(); i++ ) std::cout<<mu[i]<<" ";
3361 
3362  std::cout<<"} -- |sfem - s| = "<<math::abs( sfem-s )<<" and error estimation = "<<error_estimation<<std::endl;
3363  }
3364 
3365  Eigen::MatrixXf::Index index_max_ei;
3366  max_ei = ei.array().abs().maxCoeff( &index_max_ei );
3367  Eigen::MatrixXf::Index index_min_ei;
3368  min_ei = ei.array().abs().minCoeff( &index_min_ei );
3369 
3370  std::cout<<"[EI] max_ei = "<<max_ei<<" and min_ei = "<<min_ei<<min_ei<<" sampling size = "<<N<<std::endl;
3371 
3372 }//end of computeErrorEstimationEfficiencyIndicator
3373 
3374 
3375 
3376 
3377 
3378 template< typename TruthModelType>
3379 double
3380 CRB<TruthModelType>::correctionTerms(parameter_type const& mu, std::vector< vectorN_type > const & uN, std::vector< vectorN_type > const & uNdu, std::vector<vectorN_type> const & uNold, int const k ) const
3381 {
3382  int N = uN[0].size();
3383 
3384  matrixN_type Aprdu ( (int)N, (int)N ) ;
3385  matrixN_type Mprdu ( (int)N, (int)N ) ;
3386  vectorN_type Fdu ( (int)N );
3387  vectorN_type du ( (int)N );
3388  vectorN_type pr ( (int)N );
3389  vectorN_type oldpr ( (int)N );
3390 
3391 
3392  double time = 1e30;
3393 
3394  beta_vector_type betaAqm;
3395  beta_vector_type betaMqm;
3396  std::vector<beta_vector_type> betaFqm;
3397 
3398  double correction=0;
3399 
3400  if( M_model->isSteady() )
3401  {
3402  Aprdu.setZero( N , N );
3403  Fdu.setZero( N );
3404 
3405  boost::tie( betaMqm, betaAqm, betaFqm ) = M_model->computeBetaQm( mu ,time);
3406 
3407  for(size_type q = 0;q < M_model->Ql(0); ++q)
3408  {
3409  for(int m=0; m < M_model->mMaxF(0,q); m++)
3410  Fdu += betaFqm[0][q][m]*M_Fqm_du[q][m].head(N);
3411  }
3412  for(size_type q = 0;q < M_model->Qa(); ++q)
3413  {
3414  for(int m=0; m < M_model->mMaxA(q); m++)
3415  Aprdu += betaAqm[q][m]*M_Aqm_pr_du[q][m].block(0,0,N,N);
3416  }
3417 
3418  du = uNdu[0];
3419  pr = uN[0];
3420  correction = -( Fdu.dot( du ) - du.dot( Aprdu*pr ) );
3421  }
3422  else
3423  {
3424 
3425  double dt = M_model->timeStep();
3426  double Tf = M_model->timeFinal();
3427  int K = Tf/dt;
3428  int time_index;
3429 
3430  for( int kp=1; kp<=k; kp++)
3431  {
3432 
3433  Aprdu.setZero( N , N );
3434  Mprdu.setZero( N , N );
3435  Fdu.setZero( N );
3436 
3437  time_index = K-k+kp;
3438  time = time_index*dt;
3439 
3440  boost::tie( betaMqm, betaAqm, betaFqm) = M_model->computeBetaQm( mu ,time);
3441 
3442  time_index--;
3443 
3444 
3445  for(size_type q = 0;q < M_model->Ql(0); ++q)
3446  {
3447  for(int m=0; m < M_model->mMaxF(0,q); m++)
3448  Fdu += betaFqm[0][q][m]*M_Fqm_du[q][m].head(N);
3449  }
3450 
3451 
3452  for(size_type q = 0;q < M_model->Qa(); ++q)
3453  {
3454  for(int m=0; m < M_model->mMaxA(q); m++)
3455  Aprdu += betaAqm[q][m]*M_Aqm_pr_du[q][m].block(0,0,N,N);
3456  }
3457 
3458 
3459  for(size_type q = 0;q < M_model->Qm(); ++q)
3460  {
3461  for(int m=0; m<M_model->mMaxM(q); m++)
3462  Mprdu += betaMqm[q][m]*M_Mqm_pr_du[q][m].block(0,0,N,N);
3463  }
3464 
3465 
3466  du = uNdu[K-1-time_index];
3467  pr = uN[time_index];
3468  oldpr = uNold[time_index];
3469  correction += dt*( Fdu.dot( du ) - du.dot( Aprdu*pr ) ) - du.dot(Mprdu*pr) + du.dot(Mprdu*oldpr) ;
3470  }
3471  }
3472 
3473  return correction;
3474 
3475 }
3476 
3477 
3478 template<typename TruthModelType>
3479 void
3480 CRB<TruthModelType>::computeProjectionInitialGuess( const parameter_type & mu, int N , vectorN_type& initial_guess ) const
3481 {
3482  VLOG(2) <<"Compute projection of initial guess\n";
3483  beta_vector_type betaMqm;
3484  beta_vector_type beta_initial_guess;
3485 
3486  matrixN_type Mass ( ( int )N, ( int )N ) ;
3487  vectorN_type F ( ( int )N );
3488 
3489  //beta coefficients of the initial guess ( mu-dependant part)
3490  beta_initial_guess = M_model->computeBetaInitialGuess( mu );
3491 
3492  //in steady case
3493  //for the mass matrix, the beta coefficient is 1
3494  //and the mu-indepenant part is assembled in crbmodel
3495  //WARNING : for unsteady case, don't call computeBetaQm to have beta coefficients
3496  //of the mass matrix, because computeBetaQm will compute all beta coefficients ( M A and F )
3497  //and beta coeff need to solve a model if we don't give an approximation of the unknown
3498  Mass.setZero( N,N );
3499  int q_max = M_Mqm_pr.size();
3500  for ( size_type q = 0; q < q_max; ++q )
3501  {
3502  int m_max = M_Mqm_pr[q].size();
3503  for(int m=0; m<m_max; m++)
3504  {
3505  Mass += 1*M_Mqm_pr[q][m].block( 0,0,N,N );
3506  }
3507  }
3508 
3509  F.setZero( N );
3510  q_max = M_InitialGuessV_pr.size();
3511  for ( size_type q = 0; q < q_max; ++q )
3512  {
3513  int m_max = M_InitialGuessV_pr[q].size();
3514  for(int m=0; m<m_max; m++)
3515  F += beta_initial_guess[q][m]*M_InitialGuessV_pr[q][m].head( N );
3516  }
3517 
3518  initial_guess = Mass.lu().solve( F );
3519 }
3520 
3521 template<typename TruthModelType>
3522 void
3523 CRB<TruthModelType>::updateJacobian( const map_dense_vector_type& map_X, map_dense_matrix_type& map_J , const parameter_type & mu , int N) const
3524 {
3525  //map_J.setZero( N , N );
3526  map_J.setZero( );
3527  beta_vector_type betaJqm;
3528  boost::tie( boost::tuples::ignore, betaJqm, boost::tuples::ignore ) = M_model->computeBetaQm( this->expansion( map_X , N , M_WN ), mu , 0 );
3529  for ( size_type q = 0; q < M_model->Qa(); ++q )
3530  {
3531  for(int m=0; m<M_model->mMaxA(q); m++)
3532  map_J += betaJqm[q][m]*M_Jqm_pr[q][m].block( 0,0,N,N );
3533  }
3534 }
3535 
3536 template<typename TruthModelType>
3537 void
3538 CRB<TruthModelType>::updateResidual( const map_dense_vector_type& map_X, map_dense_vector_type& map_R , const parameter_type & mu, int N ) const
3539 {
3540  map_R.setZero( );
3541  std::vector< beta_vector_type > betaRqm;
3542  boost::tie( boost::tuples::ignore, boost::tuples::ignore, betaRqm ) = M_model->computeBetaQm( this->expansion( map_X , N , M_WN ), mu , 0 );
3543  for ( size_type q = 0; q < M_model->Ql( 0 ); ++q )
3544  {
3545  for(int m=0; m<M_model->mMaxF(0,q); m++)
3546  map_R += betaRqm[0][q][m]*M_Rqm_pr[q][m].head( N );
3547  }
3548 }
3549 
3550 template<typename TruthModelType>
3551 void
3552 CRB<TruthModelType>::newton( size_type N, parameter_type const& mu , vectorN_type & uN , double& condition_number, double& output) const
3553 {
3554  matrixN_type J ( ( int )N, ( int )N ) ;
3555  vectorN_type R ( ( int )N );
3556 
3557  double *r_data = R.data();
3558  double *j_data = J.data();
3559  double *uN_data = uN.data();
3560 
3561  Eigen::Map< Eigen::Matrix<double, Eigen::Dynamic , 1> > map_R ( r_data, N );
3562  Eigen::Map< Eigen::Matrix<double, Eigen::Dynamic , 1> > map_uN ( uN_data, N );
3563  Eigen::Map< Eigen::Matrix<double, Eigen::Dynamic , Eigen::Dynamic> > map_J ( j_data, N , N );
3564 
3565  computeProjectionInitialGuess( mu , N , uN );
3566 
3567  M_nlsolver->map_dense_jacobian = boost::bind( &self_type::updateJacobian, boost::ref( *this ), _1, _2 , mu , N );
3568  M_nlsolver->map_dense_residual = boost::bind( &self_type::updateResidual, boost::ref( *this ), _1, _2 , mu , N );
3569  M_nlsolver->solve( map_J , map_uN , map_R, 1e-12, 100);
3570 
3571  condition_number=0;
3572 
3573  if( option(_name="crb.compute-conditioning").template as<bool>() )
3574  condition_number = computeConditioning( J );
3575 
3576  //compute output
3577 
3578  vectorN_type L ( ( int )N );
3579  std::vector<beta_vector_type> betaFqm;
3580  boost::tie( boost::tuples::ignore, boost::tuples::ignore, betaFqm ) = M_model->computeBetaQm( this->expansion( uN , N , M_WN ), mu , 0 );
3581  L.setZero( N );
3582  for ( size_type q = 0; q < M_model->Ql( M_output_index ); ++q )
3583  {
3584  for(int m=0; m < M_model->mMaxF(M_output_index,q); m++)
3585  L += betaFqm[M_output_index][q][m]*M_Lqm_pr[q][m].head( N );
3586  }
3587 
3588  output = L.dot( uN );
3589 
3590 
3591 }
3592 
3593 template<typename TruthModelType>
3594 double
3596 {
3597  Eigen::SelfAdjointEigenSolver< matrixN_type > eigen_solver;
3598  eigen_solver.compute( A );
3599  int number_of_eigenvalues = eigen_solver.eigenvalues().size();
3600  //we copy eigenvalues in a std::vector beacause it's easier to manipulate it
3601  std::vector<double> eigen_values( number_of_eigenvalues );
3602 
3603 
3604  for ( int i=0; i<number_of_eigenvalues; i++ )
3605  {
3606  if ( imag( eigen_solver.eigenvalues()[i] )>1e-12 )
3607  {
3608  throw std::logic_error( "[CRB::lb] ERROR : complex eigenvalues were found" );
3609  }
3610 
3611  eigen_values[i]=real( eigen_solver.eigenvalues()[i] );
3612  }
3613 
3614  int position_of_largest_eigenvalue=number_of_eigenvalues-1;
3615  int position_of_smallest_eigenvalue=0;
3616  double eig_max = eigen_values[position_of_largest_eigenvalue];
3617  double eig_min = eigen_values[position_of_smallest_eigenvalue];
3618  return eig_max / eig_min;
3619 }
3620 
3621 
3622 
3623 template<typename TruthModelType>
3624 void
3625 CRB<TruthModelType>::fixedPointDual( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uNdu, std::vector<vectorN_type> & uNduold, std::vector< double > & output_vector, int K) const
3626 {
3627 
3628  double time_for_output;
3629  double time_step;
3630  double time_final;
3631  int number_of_time_step=1;
3632  size_type Qm;
3633 
3634  if ( M_model->isSteady() )
3635  {
3636  time_step = 1e30;
3637  time_for_output = 1e30;
3638  Qm = 0;
3639  //number_of_time_step=1;
3640  }
3641 
3642  else
3643  {
3644  Qm = M_model->Qm();
3645  time_step = M_model->timeStep();
3646  time_final = M_model->timeFinal();
3647 
3648  if ( K > 0 )
3649  time_for_output = K * time_step;
3650 
3651  else
3652  {
3653  number_of_time_step = time_final / time_step;
3654  time_for_output = number_of_time_step * time_step;
3655  }
3656  }
3657 
3658  beta_vector_type betaAqm;
3659  beta_vector_type betaMqm;
3660  beta_vector_type betaMFqm;
3661  std::vector<beta_vector_type> betaFqm, betaLqm;
3662 
3663  matrixN_type Adu ( ( int )N, ( int )N ) ;
3664  matrixN_type Mdu ( ( int )N, ( int )N ) ;
3665  vectorN_type Fdu ( ( int )N );
3666  vectorN_type Ldu ( ( int )N );
3667 
3668  matrixN_type Aprdu( ( int )N, ( int )N );
3669  matrixN_type Mprdu( ( int )N, ( int )N );
3670 
3671  double time;
3672  if ( M_model->isSteady() )
3673  {
3674  time = 1e30;
3675 
3676  boost::tie( betaMqm, betaAqm, betaFqm ) = M_model->computeBetaQm( mu ,time );
3677  Adu.setZero( N,N );
3678  Ldu.setZero( N );
3679 
3680  for ( size_type q = 0; q < M_model->Qa(); ++q )
3681  {
3682  for(int m=0; m < M_model->mMaxA(q); m++)
3683  Adu += betaAqm[q][m]*M_Aqm_du[q][m].block( 0,0,N,N );
3684  }
3685 
3686  for ( size_type q = 0; q < M_model->Ql( M_output_index ); ++q )
3687  {
3688  for(int m=0; m < M_model->mMaxF(M_output_index,q); m++)
3689  Ldu += betaFqm[M_output_index][q][m]*M_Lqm_du[q][m].head( N );
3690  }
3691 
3692  uNdu[0] = Adu.lu().solve( -Ldu );
3693  }
3694 
3695  else
3696  {
3697  int time_index = number_of_time_step-1;
3698 
3699 #if 0
3700  double initial_dual_time = time_for_output+time_step;
3701  //std::cout<<"initial_dual_time = "<<initial_dual_time<<std::endl;
3702  boost::tie( betaMqm, betaAqm, betaFqm, betaMFqm ) = M_model->computeBetaQm( mu ,initial_dual_time );
3703  Mdu.setZero( N,N );
3704 
3705  for ( size_type q = 0; q < M_model->Qm(); ++q )
3706  {
3707  for ( size_type m = 0; m < M_model->mMaxM( q ); ++m )
3708  {
3709  for(int m=0; m < M_model->mMaxM(q); m++)
3710  Mdu += betaMqm[q][m]*M_Mqm_du[q][m].block( 0,0,N,N );
3711  }
3712  }
3713 
3714  Ldu.setZero( N );
3715 
3716  for ( size_type q = 0; q < M_model->Ql( M_output_index ); ++q )
3717  {
3718  for ( size_type m = 0; m < M_model->mMaxF( M_output_index , q ); ++m )
3719  {
3720  for(int m=0; m < M_model->mMaxF(M_output_index,q); m++)
3721  Ldu += betaFqm[M_output_index][q][m]*M_Lqm_du[q][m].head( N );
3722  }
3723  }
3724 
3725  /*
3726  vectorN_type coeff(N);
3727  for(int i=0; i<N; i++) coeff(i) = M_coeff_du_ini_online[i];
3728  vectorN_type diff2 = uNduold[time_index] - coeff;
3729  std::cout<<"et maintenant le deuxieme diff = \n"<<diff2<<"\n";
3730  */
3731 #else
3732 
3733  for ( size_type n=0; n<N; n++ )
3734  {
3735  uNduold[time_index]( n ) = M_coeff_du_ini_online[n];
3736  }
3737 
3738 #endif
3739 
3740  for ( time=time_for_output; time>=time_step; time-=time_step )
3741  {
3742 
3743  boost::tie( betaMqm, betaAqm, betaFqm ) = M_model->computeBetaQm( mu ,time );
3744  Adu.setZero( N,N );
3745 
3746  for ( size_type q = 0; q < M_model->Qa(); ++q )
3747  {
3748  for(int m=0; m < M_model->mMaxA(q); m++)
3749  Adu += betaAqm[q][m]*M_Aqm_du[q][m].block( 0,0,N,N );
3750  }
3751 
3752  //No Rhs for adjoint problem except mass contribution
3753  Fdu.setZero( N );
3754 
3755  for ( size_type q = 0; q < Qm; ++q )
3756  {
3757  for(int m=0; m < M_model->mMaxM(q); m++)
3758  {
3759  Adu += betaMqm[q][m]*M_Mqm_du[q][m].block( 0,0,N,N )/time_step;
3760  Fdu += betaMqm[q][m]*M_Mqm_du[q][m].block( 0,0,N,N )*uNduold[time_index]/time_step;
3761  }
3762  }
3763 
3764  uNdu[time_index] = Adu.lu().solve( Fdu );
3765 
3766  if ( time_index>0 )
3767  {
3768  uNduold[time_index-1] = uNdu[time_index];
3769  }
3770 
3771  time_index--;
3772  }
3773 
3774  }//end of non steady case
3775 
3776 }
3777 
3778 template<typename TruthModelType>
3779 void
3780 CRB<TruthModelType>::fixedPointPrimal( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uN, std::vector<vectorN_type> & uNold, double& condition_number, std::vector< double > & output_vector , int K) const
3781 {
3782 
3783  double time_for_output;
3784 
3785  double time_step;
3786  double time_final;
3787  int number_of_time_step=1;
3788  size_type Qm;
3789  int time_index=0;
3790  double output=0;
3791 
3792  if ( M_model->isSteady() )
3793  {
3794  time_step = 1e30;
3795  time_for_output = 1e30;
3796  Qm = 0;
3797  //number_of_time_step=1;
3798  }
3799 
3800  else
3801  {
3802  Qm = M_model->Qm();
3803  time_step = M_model->timeStep();
3804  time_final = M_model->timeFinal();
3805 
3806  if ( K > 0 )
3807  time_for_output = K * time_step;
3808 
3809  else
3810  {
3811  number_of_time_step = time_final / time_step;
3812  time_for_output = number_of_time_step * time_step;
3813  }
3814  }
3815  beta_vector_type betaAqm;
3816  beta_vector_type betaMqm;
3817  beta_vector_type betaMFqm;
3818  beta_vector_type beta_initial_guess;
3819 
3820  std::vector<beta_vector_type> betaFqm, betaLqm;
3821 
3822  matrixN_type A ( ( int )N, ( int )N ) ;
3823  vectorN_type F ( ( int )N );
3824  vectorN_type L ( ( int )N );
3825 
3826  if ( !M_model->isSteady() )
3827  {
3828  for ( size_type n=0; n<N; n++ )
3829  uNold[0]( n ) = M_coeff_pr_ini_online[n];
3830  }
3831 
3832 
3833  int max_fixedpoint_iterations = option("crb.max-fixedpoint-iterations").template as<int>();
3834  double increment_fixedpoint_tol = option("crb.increment-fixedpoint-tol").template as<double>();
3835  double output_fixedpoint_tol = option("crb.output-fixedpoint-tol").template as<double>();
3836  bool fixedpoint_verbose = option("crb.fixedpoint-verbose").template as<bool>();
3837  double fixedpoint_critical_value = option(_name="crb.fixedpoint-critical-value").template as<double>();
3838  for ( double time=time_step; time<time_for_output+time_step; time+=time_step )
3839  {
3840 
3841  computeProjectionInitialGuess( mu , N , uN[time_index] );
3842 
3843  //vectorN_type error;
3844  //const element_type expansion_uN = this->expansion( uN[time_index] , N , M_WN);
3845  //checkInitialGuess( expansion_uN , mu , error);
3846  //std::cout<<"***************************************************************error.sum : "<<error.sum()<<std::endl;
3847 
3848  VLOG(2) << "lb: start fix point\n";
3849 
3850  vectorN_type previous_uN( M_N );
3851 
3852  int fi=0;
3853 
3854  double old_output;
3855 #if 0
3856  //in the case were we want to control output error for fixed point
3857  L.setZero( N );
3858  for ( size_type q = 0; q < M_model->Ql( M_output_index ); ++q )
3859  {
3860  for(int m=0; m < M_model->mMaxF(M_output_index,q); m++)
3861  {
3862  L += betaFqm[M_output_index][q][m]*M_Lqm_pr[q][m].head( N );
3863  }
3864  }
3865  old_output = L.dot( uN[time_index] );
3866 #endif
3867 
3868  do
3869  {
3870 
3871  boost::tie( betaMqm, betaAqm, betaFqm ) = M_model->computeBetaQm( this->expansion( uN[time_index] , N , M_WN ), mu ,time );
3872 
3873  A.setZero( N,N );
3874  for ( size_type q = 0; q < M_model->Qa(); ++q )
3875  {
3876  for(int m=0; m<M_model->mMaxA(q); m++)
3877  A += betaAqm[q][m]*M_Aqm_pr[q][m].block( 0,0,N,N );
3878  }
3879 
3880  F.setZero( N );
3881  for ( size_type q = 0; q < M_model->Ql( 0 ); ++q )
3882  {
3883  for(int m=0; m<M_model->mMaxF(0,q); m++)
3884  F += betaFqm[0][q][m]*M_Fqm_pr[q][m].head( N );
3885  }
3886 
3887  for ( size_type q = 0; q < Qm; ++q )
3888  {
3889  for(int m=0; m<M_model->mMaxM(q); m++)
3890  {
3891  A += betaMqm[q][m]*M_Mqm_pr[q][m].block( 0,0,N,N )/time_step;
3892  F += betaMqm[q][m]*M_Mqm_pr[q][m].block( 0,0,N,N )*uNold[time_index]/time_step;
3893  }
3894  }
3895 
3896  // backup uN
3897  previous_uN = uN[time_index];
3898 
3899  // solve for new fix point iteration
3900  uN[time_index] = A.lu().solve( F );
3901 
3902  if ( time_index<number_of_time_step-1 )
3903  uNold[time_index+1] = uN[time_index];
3904 
3905  L.setZero( N );
3906  for ( size_type q = 0; q < M_model->Ql( M_output_index ); ++q )
3907  {
3908  for(int m=0; m < M_model->mMaxF(M_output_index,q); m++)
3909  {
3910  L += betaFqm[M_output_index][q][m]*M_Lqm_pr[q][m].head( N );
3911  }
3912  }
3913  old_output = output;
3914  output = L.dot( uN[time_index] );
3915 
3916  //output_vector.push_back( output );
3917  output_vector[time_index] = output;
3918  DVLOG(2) << "iteration " << fi << " increment error: " << (uN[time_index]-previous_uN).norm() << "\n";
3919  fi++;
3920 
3921  if( fixedpoint_verbose && this->worldComm().globalRank()==this->worldComm().masterRank() )
3922  VLOG(2)<<"[CRB::lb] fixedpoint iteration " << fi << " increment error: " << (uN[time_index]-previous_uN).norm()<<std::endl;
3923 
3924  double residual_norm = (A * uN[time_index] - F).norm() ;
3925  VLOG(2) << " residual_norm : "<<residual_norm;
3926  }
3927  while ( (uN[time_index]-previous_uN).norm() > increment_fixedpoint_tol && fi<max_fixedpoint_iterations );
3928  //while ( math::abs(output - old_output) > output_fixedpoint_tol && fi < max_fixedpoint_iterations );
3929 
3930  if( (uN[time_index]-previous_uN).norm() > increment_fixedpoint_tol )
3931  DVLOG(2)<<"[CRB::lb] fixed point, proc "<<this->worldComm().globalRank()
3932  <<" fixed point has no converged : norm(uN-uNold) = "<<(uN[time_index]-previous_uN).norm()
3933  <<" and tolerance : "<<increment_fixedpoint_tol<<" so "<<max_fixedpoint_iterations<<" iterations were done"<<std::endl;
3934 
3935  if( (uN[time_index]-previous_uN).norm() > fixedpoint_critical_value )
3936  throw std::logic_error( "[CRB::lb] fixed point ERROR : norm(uN-uNold) > critical value " );
3937 
3938  if ( time_index<number_of_time_step-1 )
3939  time_index++;
3940  }
3941 
3942  condition_number = 0;
3943  if( option(_name="crb.compute-conditioning").template as<bool>() )
3944  condition_number = computeConditioning( A );
3945 }
3946 
3947 template<typename TruthModelType>
3948 void
3949 CRB<TruthModelType>::fixedPoint( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uN, std::vector< vectorN_type > & uNdu, std::vector<vectorN_type> & uNold, std::vector<vectorN_type> & uNduold, double& condition_number, std::vector< double > & output_vector, int K) const
3950 {
3951 
3952  double time_for_output;
3953  double time_step;
3954  double time_final;
3955  int number_of_time_step;
3956 
3957  if ( M_model->isSteady() )
3958  {
3959  time_step = 1e30;
3960  time_for_output = 1e30;
3961  number_of_time_step=1;
3962  }
3963  else
3964  {
3965  time_step = M_model->timeStep();
3966  time_final = M_model->timeFinal();
3967  if ( K > 0 )
3968  time_for_output = K * time_step;
3969  else
3970  {
3971  number_of_time_step = time_final / time_step;
3972  time_for_output = number_of_time_step * time_step;
3973  }
3974  }
3975  fixedPointPrimal( N, mu , uN , uNold , condition_number, output_vector, K ) ;
3976 
3977  int size=output_vector.size();
3978  double o =output_vector[size-1];
3979  bool solve_dual_problem = this->vm()["crb.solve-dual-problem"].template as<bool>();
3980  //if( this->worldComm().globalSize() > 1 )
3981  // solve_dual_problem=false;
3982 
3983  if( solve_dual_problem )
3984  {
3985  fixedPointDual( N, mu , uNdu , uNduold , output_vector , K ) ;
3986 
3987  int time_index=0;
3988 
3989  for ( double time=time_step; time<=time_for_output; time+=time_step )
3990  {
3991  int k = time_index+1;
3992  output_vector[time_index]+=correctionTerms(mu, uN , uNdu, uNold, k );
3993  time_index++;
3994  }
3995  }
3996 
3997 }
3998 
3999 template<typename TruthModelType>
4000 boost::tuple<double,double>
4001 CRB<TruthModelType>::lb( size_type N, parameter_type const& mu, std::vector< vectorN_type > & uN, std::vector< vectorN_type > & uNdu, std::vector<vectorN_type> & uNold, std::vector<vectorN_type> & uNduold,int K ) const
4002 {
4003 
4004  bool save_output_behavior = this->vm()["crb.save-output-behavior"].template as<bool>();
4005 
4006  //if K>0 then the time at which we want to evaluate output is defined by
4007  //time_for_output = K * time_step
4008  //else it's the default value and in this case we take final time
4009  double time_for_output;
4010 
4011  double time_step;
4012  double time_final;
4013  int number_of_time_step = 0;
4014  size_type Qm;
4015 
4016  if ( M_model->isSteady() )
4017  {
4018  time_step = 1e30;
4019  time_for_output = 1e30;
4020  Qm = 0;
4021  number_of_time_step=1;
4022  }
4023 
4024  else
4025  {
4026  Qm = M_model->Qm();
4027  time_step = M_model->timeStep();
4028  time_final = M_model->timeFinal();
4029 
4030  if ( K > 0 )
4031  time_for_output = K * time_step;
4032 
4033  else
4034  {
4035  number_of_time_step = time_final / time_step;
4036  time_for_output = number_of_time_step * time_step;
4037  }
4038  }
4039  if ( N > M_N ) N = M_N;
4040 
4041  uN.resize( number_of_time_step );
4042  uNdu.resize( number_of_time_step );
4043  uNold.resize( number_of_time_step );
4044  uNduold.resize( number_of_time_step );
4045 
4046  int index=0;
4047  BOOST_FOREACH( auto elem, uN )
4048  {
4049  uN[index].resize( N );
4050  uNdu[index].resize( N );
4051  uNold[index].resize( N );
4052  uNduold[index].resize( N );
4053  index++;
4054  }
4055  double condition_number;
4056  //-- end of initialization step
4057 
4058  //vector containing outputs from time=time_step until time=time_for_output
4059  std::vector<double>output_vector;
4060  output_vector.resize( number_of_time_step );
4061  double output;
4062  int time_index=0;
4063 
4064  // init by 1, the model could provide better init
4065  //uN[0].setOnes(M_N);
4066  uN[0].setOnes(N);
4067  if( M_use_newton )
4068  newton( N , mu , uN[0] , condition_number , output_vector[0] );
4069  else
4070  fixedPoint( N , mu , uN , uNdu , uNold , uNduold , condition_number , output_vector , K );
4071 
4072 
4073  if( M_compute_variance )
4074  {
4075 
4076  if( ! M_database_contains_variance_info )
4077  throw std::logic_error( "[CRB::offline] ERROR there are no information available in the DataBase for variance computing, please set option crb.save-information-for-variance=true and rebuild the database" );
4078 
4079  int nb_spaces = functionspace_type::nSpaces;
4080 
4081  int space=0;
4082 
4083  time_index=0;
4084  for ( double time=time_step; time<=time_for_output; time+=time_step )
4085  {
4086  vectorN_type uNsquare = uN[time_index].array().pow(2);
4087  double first = uNsquare.dot( M_variance_matrix_phi[space].block(0,0,N,N).diagonal() );
4088 
4089  double second = 0;
4090  for(int k = 1; k <= N-1; ++k)
4091  {
4092  for(int j = 1; j <= N-k; ++j)
4093  {
4094  second += 2 * uN[time_index](k-1) * uN[time_index](k+j-1) * M_variance_matrix_phi[space](k-1 , j+k-1) ;
4095  }
4096  }
4097  output_vector[time_index] = first + second;
4098 
4099  time_index++;
4100  }
4101  }
4102 
4103 
4104  if ( save_output_behavior )
4105  {
4106  time_index=0;
4107  std::ofstream file_output;
4108  std::string mu_str;
4109 
4110  for ( int i=0; i<mu.size(); i++ )
4111  {
4112  mu_str= mu_str + ( boost::format( "_%1%" ) %mu[i] ).str() ;
4113  }
4114 
4115  std::string name = "output_evolution" + mu_str;
4116  file_output.open( name.c_str(),std::ios::out );
4117 
4118  for ( double time=time_step; time<=time_for_output; time+=time_step )
4119  {
4120  file_output<<time<<"\t"<<output_vector[time_index]<<"\n";
4121  time_index++;
4122  }
4123 
4124  file_output.close();
4125  }
4126 
4127  int size=output_vector.size();
4128  return boost::make_tuple( output_vector[size-1], condition_number);
4129 
4130 }
4131 
4132 template<typename TruthModelType>
4133 typename CRB<TruthModelType>::error_estimation_type
4135  parameter_type const& mu,
4136  std::vector<vectorN_type> const& uN,
4137  std::vector<vectorN_type> const& uNdu,
4138  std::vector<vectorN_type> const& uNold,
4139  std::vector<vectorN_type> const& uNduold,
4140  int k ) const
4141 {
4142 
4143  std::vector< std::vector<double> > primal_residual_coeffs;
4144  std::vector< std::vector<double> > dual_residual_coeffs;
4145 
4146  double delta_pr=0;
4147  double delta_du=0;
4148  if ( M_error_type == CRB_NO_RESIDUAL )
4149  return boost::make_tuple( -1,primal_residual_coeffs,dual_residual_coeffs,delta_pr,delta_du );
4150 
4151  else if ( M_error_type == CRB_EMPIRICAL )
4152  return boost::make_tuple( empiricalErrorEstimation ( N, mu , k ) , primal_residual_coeffs, dual_residual_coeffs , delta_pr, delta_du);
4153 
4154  else
4155  {
4156  //we assume that we want estimate the error committed on the final output
4157  double Tf = M_model->timeFinal();
4158  //double Ti = M_model->timeInitial();
4159  double dt = M_model->timeStep();
4160 
4161  int time_index=0;
4162  double primal_sum=0;
4163  double dual_sum=0;
4164 
4165  //vectors to store residual coefficients
4166  int K = Tf/dt;
4167  primal_residual_coeffs.resize( K );
4168  dual_residual_coeffs.resize( K );
4169  for ( double time=dt; time<=Tf; time+=dt )
4170  {
4171  auto pr = transientPrimalResidual( N, mu, uN[time_index], uNold[time_index], dt, time );
4172  primal_sum += pr.template get<0>();
4173  primal_residual_coeffs[time_index].resize( pr.template get<1>().size() );
4174  primal_residual_coeffs[time_index] = pr.template get<1>() ;
4175  time_index++;
4176  }//end of time loop for primal problem
4177 
4178  time_index--;
4179 
4180  double dual_residual=0;
4181 
4182  if ( !M_model->isSteady() ) dual_residual = initialDualResidual( N,mu,uNduold[time_index],dt );
4183  bool solve_dual_problem = this->vm()["crb.solve-dual-problem"].template as<bool>() ;
4184 
4185  if( solve_dual_problem )
4186  {
4187  for ( double time=Tf; time>=dt; time-=dt )
4188  {
4189  auto du = transientDualResidual( N, mu, uNdu[time_index], uNduold[time_index], dt, time );
4190  dual_sum += du.template get<0>();
4191  dual_residual_coeffs[time_index].resize( du.template get<1>().size() );
4192  dual_residual_coeffs[time_index] = du.template get<1>();
4193  time_index--;
4194  }//end of time loop for dual problem
4195  }
4196 
4197 
4198  bool show_residual = this->vm()["crb.show-residual"].template as<bool>() ;
4199  if( ! M_offline_step && show_residual )
4200  {
4201  double sum=0;
4202  bool seek_mu_in_complement = this->vm()["crb.seek-mu-in-complement"].template as<bool>() ;
4203  LOG( INFO ) <<" =========== Residual with "<<N<<" basis functions - seek mu in complement of WNmu : "<<seek_mu_in_complement<<"============ \n";
4204  time_index=0;
4205  for ( double time=dt; time<=Tf; time+=dt )
4206  {
4207  auto pr = transientPrimalResidual( N, mu, uN[time_index], uNold[time_index], dt, time );
4208  //LOG(INFO) << "primal residual at time "<<time<<" : "<<pr.template get<0>()<<"\n";
4209  sum+=pr.template get<0>();
4210  time_index++;
4211  }
4212  LOG(INFO) << "sum of primal residuals "<<sum<<std::endl;
4213 
4214  time_index--;
4215  sum=0;
4216 
4217  if (solve_dual_problem )
4218  {
4219  for ( double time=Tf; time>=dt; time-=dt )
4220  {
4221  auto du = transientDualResidual( N, mu, uNdu[time_index], uNduold[time_index], dt, time );
4222  //LOG(INFO) << "dual residual at time "<<time<<" : "<<du.template get<0>()<<"\n";
4223  sum += du.template get<0>();
4224  time_index--;
4225  }
4226  }
4227  LOG(INFO) << "sum of dual residuals "<<sum<<std::endl;
4228  LOG( INFO ) <<" ================================= \n";
4229  //std::cout<<"[REAL ] duam_sum : "<<sum<<std::endl;
4230  }//if show_residual_convergence
4231 
4232  double alphaA=1,alphaM=1;
4233 
4234  if ( M_error_type == CRB_RESIDUAL_SCM )
4235  {
4236  double alphaA_up, lbti;
4237  M_scmA->setScmForMassMatrix( false );
4238  boost::tie( alphaA, lbti ) = M_scmA->lb( mu );
4239  if( option(_name="crb.scm.use-scm").template as<bool>() )
4240  boost::tie( alphaA_up, lbti ) = M_scmA->ub( mu );
4241  //LOG( INFO ) << "alphaA_lo = " << alphaA << " alphaA_hi = " << alphaA_up ;
4242 
4243  if ( ! M_model->isSteady() )
4244  {
4245  M_scmM->setScmForMassMatrix( true );
4246  double alphaM_up, lbti;
4247  boost::tie( alphaM, lbti ) = M_scmM->lb( mu );
4248  if( option(_name="crb.scm.use-scm").template as<bool>() )
4249  boost::tie( alphaM_up, lbti ) = M_scmM->ub( mu );
4250  //LOG( INFO ) << "alphaM_lo = " << alphaM << " alphaM_hi = " << alphaM_up ;
4251  }
4252  }
4253 
4254  double output_upper_bound;
4255  double solution_upper_bound;
4256  double solution_dual_upper_bound;
4257  //alphaA=1;
4258  //dual_residual=0;
4259  if ( M_model->isSteady() )
4260  {
4261  delta_pr = math::sqrt( primal_sum ) / math::sqrt( alphaA );
4262  if( solve_dual_problem )
4263  delta_du = math::sqrt( dual_sum ) / math::sqrt( alphaA );
4264  else
4265  delta_du = 1;
4266  output_upper_bound = delta_pr * delta_du;
4267  //solution_upper_bound = delta_pr;
4268  //solution_dual_upper_bound = delta_du;
4269  }
4270  else
4271  {
4272  delta_pr = math::sqrt( dt/alphaA * primal_sum );
4273  delta_du = math::sqrt( dt/alphaA * dual_sum + dual_residual/alphaM );
4274  output_upper_bound = delta_pr * delta_du;
4275  //solution_upper_bound = delta_pr;
4276  //solution_dual_upper_bound = delta_du;
4277  }
4278 
4279  //return boost::make_tuple( output_upper_bound, primal_residual_coeffs, dual_residual_coeffs , delta_pr, delta_du , solution_upper_bound, solution_dual_upper_bound);
4280  return boost::make_tuple( output_upper_bound, primal_residual_coeffs, dual_residual_coeffs , delta_pr, delta_du );
4281 
4282  }//end of else
4283 }
4284 
4285 template<typename TruthModelType>
4286 typename CRB<TruthModelType>::max_error_type
4288 {
4289  bool seek_mu_in_complement = this->vm()["crb.seek-mu-in-complement"].template as<bool>() ;
4290 
4291  std::vector< vectorN_type > uN;
4292  std::vector< vectorN_type > uNdu;
4293  std::vector< vectorN_type > uNold;
4294  std::vector< vectorN_type > uNduold;
4295 
4296  y_type err( M_Xi->size() );
4297  y_type vect_delta_pr( M_Xi->size() );
4298  y_type vect_delta_du( M_Xi->size() );
4299  std::vector<double> check_err( M_Xi->size() );
4300 
4301  double delta_pr=0;
4302  double delta_du=0;
4303  if ( M_error_type == CRB_EMPIRICAL )
4304  {
4305  if ( M_WNmu->size()==1 )
4306  {
4307  parameter_type mu ( M_Dmu );
4308  size_type id;
4309  boost::tie ( mu, id ) = M_Xi->max();
4310  return boost::make_tuple( 1e5, M_Xi->at( id ), id , delta_pr, delta_du);
4311  }
4312 
4313  else
4314  {
4315  err.resize( M_WNmu_complement->size() );
4316  check_err.resize( M_WNmu_complement->size() );
4317 
4318  for ( size_type k = 0; k < M_WNmu_complement->size(); ++k )
4319  {
4320  parameter_type const& mu = M_WNmu_complement->at( k );
4321  //double _err = delta( N, mu, uN, uNdu, uNold, uNduold, k);
4322  auto error_estimation = delta( N, mu, uN, uNdu, uNold, uNduold, k );
4323  double _err = error_estimation.template get<0>();
4324  vect_delta_pr( k ) = error_estimation.template get<3>();
4325  vect_delta_du( k ) = error_estimation.template get<4>();
4326  err( k ) = _err;
4327  check_err[k] = _err;
4328  }
4329  }
4330 
4331  }//end of if ( M_error_type == CRB_EMPIRICAL)
4332 
4333  else
4334  {
4335  if ( seek_mu_in_complement )
4336  {
4337  err.resize( M_WNmu_complement->size() );
4338  check_err.resize( M_WNmu_complement->size() );
4339 
4340 
4341  for ( size_type k = 0; k < M_WNmu_complement->size(); ++k )
4342  {
4343  parameter_type const& mu = M_WNmu_complement->at( k );
4344  lb( N, mu, uN, uNdu , uNold ,uNduold );
4345  auto error_estimation = delta( N, mu, uN, uNdu, uNold, uNduold, k );
4346  double _err = error_estimation.template get<0>();
4347  vect_delta_pr( k ) = error_estimation.template get<3>();
4348  vect_delta_du( k ) = error_estimation.template get<4>();
4349  err( k ) = _err;
4350  check_err[k] = _err;
4351  }
4352 
4353  }//end of seeking mu in the complement
4354 
4355  else
4356  {
4357  for ( size_type k = 0; k < M_Xi->size(); ++k )
4358  {
4359  //std::cout << "--------------------------------------------------\n";
4360  parameter_type const& mu = M_Xi->at( k );
4361  //std::cout << "[maxErrorBounds] mu=" << mu << "\n";
4362  lb( N, mu, uN, uNdu , uNold ,uNduold );
4363  //auto tuple = lb( N, mu, uN, uNdu , uNold ,uNduold );
4364  //double o = tuple.template get<0>();
4365  //std::cout << "[maxErrorBounds] output=" << o << "\n";
4366  auto error_estimation = delta( N, mu, uN, uNdu, uNold, uNduold, k );
4367  double _err = error_estimation.template get<0>();
4368  vect_delta_pr( k ) = error_estimation.template get<3>();
4369  vect_delta_du( k ) = error_estimation.template get<4>();
4370  //std::cout << "[maxErrorBounds] error=" << _err << "\n";
4371  err( k ) = _err;
4372  check_err[k] = _err;
4373  }
4374  }//else ( seek_mu_in_complement )
4375  }//else
4376 
4377  Eigen::MatrixXf::Index index;
4378  double maxerr = err.array().abs().maxCoeff( &index );
4379  delta_pr = vect_delta_pr( index );
4380  delta_du = vect_delta_du( index );
4381  parameter_type mu;
4382 
4383  std::vector<double>::iterator it = std::max_element( check_err.begin(), check_err.end() );
4384  int check_index = it - check_err.begin() ;
4385  double check_maxerr = *it;
4386 
4387  if ( index != check_index || maxerr != check_maxerr )
4388  {
4389  std::cout<<"[CRB::maxErrorBounds] index = "<<index<<" / check_index = "<<check_index<<" and maxerr = "<<maxerr<<" / "<<check_maxerr<<std::endl;
4390  throw std::logic_error( "[CRB::maxErrorBounds] index and check_index have different values" );
4391  }
4392 
4393  int _index=0;
4394 
4395  if ( seek_mu_in_complement )
4396  {
4397  LOG(INFO) << "[maxErrorBounds] WNmu_complement N=" << N << " max Error = " << maxerr << " at index = " << index << "\n";
4398  mu = M_WNmu_complement->at( index );
4399  _index = M_WNmu_complement->indexInSuperSampling( index );
4400  }
4401 
4402  else
4403  {
4404  LOG(INFO) << "[maxErrorBounds] N=" << N << " max Error = " << maxerr << " at index = " << index << "\n";
4405  mu = M_Xi->at( index );
4406  _index = index;
4407  }
4408 
4409  int proc_number = this->worldComm().globalRank();
4410  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
4411  std::cout<< std::setprecision(15)<<"[CRB maxerror] proc "<< proc_number<<" delta_pr : "<<delta_pr<<" - delta_du : "<<delta_du<<" at index : "<<_index<<std::endl;
4412  lb( N, mu, uN, uNdu , uNold ,uNduold );
4413 
4414  return boost::make_tuple( maxerr, mu , _index , delta_pr, delta_du);
4415 
4416 
4417 }
4418 template<typename TruthModelType>
4419 double
4421 {
4422  int proc_number = this->worldComm().globalRank();
4423  if( proc_number == 0 ) std::cout << " -- orthonormalization (Gram-Schmidt)\n";
4424  DVLOG(2) << "[CRB::orthonormalize] orthonormalize basis for N=" << N << "\n";
4425  DVLOG(2) << "[CRB::orthonormalize] orthonormalize basis for WN="
4426  << wn.size() << "\n";
4427  DVLOG(2) << "[CRB::orthonormalize] starting ...\n";
4428 
4429  for ( size_type i = 0; i < N; ++i )
4430  {
4431  for ( size_type j = std::max( i+1,N-Nm ); j < N; ++j )
4432  {
4433  value_type __rij_pr = M_model->scalarProduct( wn[i], wn[ j ] );
4434  wn[j].add( -__rij_pr, wn[i] );
4435  }
4436  }
4437  // normalize
4438  for ( size_type i =N-Nm; i < N; ++i )
4439  {
4440  value_type __rii_pr = math::sqrt( M_model->scalarProduct( wn[i], wn[i] ) );
4441  wn[i].scale( 1./__rii_pr );
4442  }
4443 
4444  DVLOG(2) << "[CRB::orthonormalize] finished ...\n";
4445  DVLOG(2) << "[CRB::orthonormalize] copying back results in basis\n";
4446 
4447  //if ( this->vm()["crb.check.gs"].template as<int>() )
4448  //return the norm of the matrix A(i,j)=M_model->scalarProduct( wn[j], wn[i] )
4449  return checkOrthonormality( N , wn );
4450 }
4451 
4452 template <typename TruthModelType>
4453 double
4454 CRB<TruthModelType>::checkOrthonormality ( int N, const wn_type& wn ) const
4455 {
4456 
4457  if ( wn.size()==0 )
4458  {
4459  throw std::logic_error( "[CRB::checkOrthonormality] ERROR : size of wn is zero" );
4460  }
4461 
4462  if ( orthonormalize_primal*orthonormalize_dual==0 )
4463  {
4464  LOG(INFO)<<"Warning : calling checkOrthonormality is called but ";
4465  LOG(INFO)<<" orthonormalize_dual = "<<orthonormalize_dual;
4466  LOG(INFO)<<" and orthonormalize_primal = "<<orthonormalize_primal;
4467  }
4468 
4469  matrixN_type A, I;
4470  A.setZero( N, N );
4471  I.setIdentity( N, N );
4472 
4473  for ( int i = 0; i < N; ++i )
4474  {
4475  for ( int j = 0; j < N; ++j )
4476  {
4477  A( i, j ) = M_model->scalarProduct( wn[i], wn[j] );
4478  }
4479  }
4480 
4481  A -= I;
4482  DVLOG(2) << "orthonormalization: " << A.norm() << "\n";
4483  if ( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
4484  {
4485  LOG( INFO ) << " o check : " << A.norm() << " (should be 0)";
4486  }
4487  //FEELPP_ASSERT( A.norm() < 1e-14 )( A.norm() ).error( "orthonormalization failed.");
4488 
4489  return A.norm();
4490 }
4491 
4492 
4493 template <typename TruthModelType>
4494 void
4495 CRB<TruthModelType>::exportBasisFunctions( const export_vector_wn_type& export_vector_wn )const
4496 {
4497 
4498 
4499  std::vector<wn_type> vect_wn=export_vector_wn.template get<0>();
4500  std::vector<std::string> vect_names=export_vector_wn.template get<1>();
4501 
4502  if ( vect_wn.size()==0 )
4503  {
4504  throw std::logic_error( "[CRB::exportBasisFunctions] ERROR : there are no wn_type to export" );
4505  }
4506 
4507 
4508  auto first_wn = vect_wn[0];
4509  auto first_element = first_wn[0];
4510 
4511  exporter->step( 0 )->setMesh( first_element.functionSpace()->mesh() );
4512  int basis_number=0;
4513  BOOST_FOREACH( auto wn , vect_wn )
4514  {
4515 
4516  if ( wn.size()==0 )
4517  {
4518  throw std::logic_error( "[CRB::exportBasisFunctions] ERROR : there are no element to export" );
4519  }
4520 
4521  int element_number=0;
4522  parameter_type mu;
4523 
4524  BOOST_FOREACH( auto element, wn )
4525  {
4526 
4527  std::string basis_name = vect_names[basis_number];
4528  std::string number = ( boost::format( "%1%_with_parameters" ) %element_number ).str() ;
4529  mu = M_WNmu->at( element_number );
4530  std::string mu_str;
4531 
4532  for ( int i=0; i<mu.size(); i++ )
4533  {
4534  mu_str= mu_str + ( boost::format( "_%1%" ) %mu[i] ).str() ;
4535  }
4536 
4537  std::string name = basis_name + number + mu_str;
4538  exporter->step( 0 )->add( name, element );
4539  element_number++;
4540  }
4541  basis_number++;
4542  }
4543 
4544  exporter->save();
4545 
4546 }
4547 
4548 
4549 //error estimation only to build reduced basis
4550 template <typename TruthModelType>
4551 typename CRB<TruthModelType>::value_type
4552 CRB<TruthModelType>::empiricalErrorEstimation ( int Nwn, parameter_type const& mu , int second_index ) const
4553 {
4554  std::vector<vectorN_type> Un;
4555  std::vector<vectorN_type> Undu;
4556  std::vector<vectorN_type> Unold;
4557  std::vector<vectorN_type> Unduold;
4558  auto o = lb( Nwn, mu, Un, Undu, Unold, Unduold );
4559  double sn = o.template get<0>();
4560 
4561  int nb_element =Nwn/M_factor*( M_factor>0 ) + ( Nwn+M_factor )*( M_factor<0 && ( int )Nwn>( -M_factor ) ) + 1*( M_factor<0 && ( int )Nwn<=( -M_factor ) ) ;
4562 
4563  std::vector<vectorN_type> Un2;
4564  std::vector<vectorN_type> Undu2;//( nb_element );
4565 
4566  //double output_smaller_basis = lb(nb_element, mu, Un2, Undu2, Unold, Unduold);
4567  auto tuple = lb( nb_element, mu, Un2, Undu2, Unold, Unduold );
4568  double output_smaller_basis = tuple.template get<0>();
4569 
4570  double error_estimation = math::abs( sn-output_smaller_basis );
4571 
4572  return error_estimation;
4573 
4574 }
4575 
4576 
4577 
4578 
4579 template<typename TruthModelType>
4580 typename CRB<TruthModelType>::value_type
4581 CRB<TruthModelType>::initialDualResidual( int Ncur, parameter_type const& mu, vectorN_type const& Unduini, double time_step ) const
4582 {
4583  beta_vector_type betaAqm;
4584  beta_vector_type betaMqm;
4585  beta_vector_type betaMFqm;
4586  std::vector<beta_vector_type> betaFqm;
4587  double time = M_model->timeFinal();
4588  boost::tie( betaMqm, betaAqm, betaFqm) = M_model->computeBetaQm( mu, time );
4589 
4590  int __QLhs = M_model->Qa();
4591  int __QOutput = M_model->Ql( M_output_index );
4592  int __Qm = M_model->Qm();
4593  int __N = Ncur;
4594 
4595 
4596  value_type __c0_du = 0.0;
4597 
4598  for ( int __q1 = 0; __q1 < __QOutput; ++__q1 )
4599  {
4600  for ( int __m1 = 0; __m1 < M_model->mMaxF(M_output_index,__q1); ++__m1 )
4601  {
4602  value_type fq1 = betaFqm[M_output_index][__q1][__m1];
4603 
4604  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
4605  {
4606  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
4607  {
4608  value_type fq2 = betaFqm[M_output_index][__q2][__m2];
4609  //__c0_du += 1./(time_step*time_step) * M_C0_du[__q1][__q2]*fq1*fq2;
4610  //__c0_du += 1./(time_step*time_step) * M_C0_du[__q1][__q2]*fq1*fq2;
4611  __c0_du += M_C0_du[__q1][__m1][__q2][__m2]*fq1*fq2;
4612  }//end of loop __m2
4613  }//end of loop __q2
4614  }//end of loop __m1
4615  }//end of loop __q1
4616 
4617 #if 0
4618  value_type __Caf_du = 0.0;
4619  value_type __Caa_du = 0.0;
4620 
4621  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
4622  {
4623  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1) ; ++__m1 )
4624  {
4625 
4626  value_type a_q1 = betaAqm[__q1][__m1];
4627 
4628  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
4629  {
4630 
4631  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
4632  {
4633  value_type f_q2 = betaFqm[M_output_index][__q2][__m2];
4634  __Caf_du += 1./time_step * a_q1*f_q2*M_Lambda_du[__q1][__m1][__q2][__m2].dot( Unduini );
4635  }
4636  }
4637 
4638 
4639  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
4640  {
4641  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
4642  {
4643  value_type a_q2 = betaAqm[__q2][__m2];
4644  auto m = M_Gamma_du[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Unduini;
4645  __Caa_du += a_q1 * a_q2 * Unduini.dot( m );
4646  }
4647  }
4648  }
4649  }
4650 
4651 
4652  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
4653  {
4654  for ( int __m2=0 ; __m2< M_model->mMaxA(__q2); ++__m2 )
4655  {
4656  value_type a_q2 = betaAqm[__q2][__m2];
4657  auto m = M_Cma_du[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Unduini;
4658  //__Cma_du += 1./time_step * m_q1 * a_q2 * Unduini.dot(m);
4659  __Cma_du += m_q1 * a_q2 * Unduini.dot( m );
4660  }//m2
4661  }//q2
4662 
4663 #endif
4664 
4665  value_type __Cmf_du=0;
4666  value_type __Cmm_du=0;
4667  value_type __Cma_du=0;
4668 
4669  for ( int __q1=0 ; __q1<__Qm; ++__q1 )
4670  {
4671  for ( int __m1=0 ; __m1< M_model->mMaxM(__q1); ++__m1 )
4672  {
4673 
4674  value_type m_q1 = betaMqm[__q1][__m1];
4675 
4676  for ( int __q2=0 ; __q2<__QOutput; ++__q2 )
4677  {
4678  for ( int __m2=0 ; __m2< M_model->mMaxF(M_output_index,__q2); ++__m2 )
4679  {
4680  value_type f_q2 = betaFqm[M_output_index][__q2][__m2];
4681  //__Cmf_du += 1./(time_step*time_step) * m_q1 * f_q2 * M_Cmf_du[__q1][__m1][__q2][__m2].head(__N).dot( Unduini );
4682  __Cmf_du += m_q1 * f_q2 * M_Cmf_du_ini[__q1][__m1][__q2][__m2].head( __N ).dot( Unduini );
4683  }//m2
4684  }//q2
4685 
4686  for ( int __q2 = 0; __q2 < __Qm; ++__q2 )
4687  {
4688  for ( int __m2=0 ; __m2< M_model->mMaxM(__q2); ++__m2 )
4689  {
4690  value_type m_q2 = betaMqm[__q2][__m2];
4691  auto m = M_Cmm_du[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Unduini;
4692  //__Cmm_du += 1./(time_step*time_step) * m_q1 * m_q2 * Unduini.dot(m);
4693  __Cmm_du += m_q1 * m_q2 * Unduini.dot( m );
4694  }//m2
4695  }// q2
4696 
4697  }//m1
4698  }//q1
4699 
4700  //return math::abs(__c0_du+__Cmf_du+__Caf_du+__Cmm_du+__Cma_du+__Caa_du) ;
4701  return math::abs( __c0_du+__Cmf_du+__Cmm_du ) ;
4702 
4703 }
4704 
4705 
4706 
4707 
4708 template<typename TruthModelType>
4709 typename CRB<TruthModelType>::residual_error_type
4710 CRB<TruthModelType>::transientPrimalResidual( int Ncur,parameter_type const& mu, vectorN_type const& Un ,vectorN_type const& Unold , double time_step, double time ) const
4711 {
4712 
4713  beta_vector_type betaAqm;
4714  beta_vector_type betaMqm;
4715  beta_vector_type betaMFqm;
4716  std::vector<beta_vector_type> betaFqm, betaLqm;
4717 
4718  boost::tie( betaMqm, betaAqm, betaFqm ) = M_model->computeBetaQm( mu, time );
4719 
4720  size_type __QLhs = M_model->Qa();
4721  size_type __QRhs = M_model->Ql( 0 );
4722  size_type __Qm = M_model->Qm();
4723  size_type __N = Ncur;
4724 
4725 
4726 
4727  residual_error_type steady_residual_contribution = steadyPrimalResidual( Ncur, mu, Un, time );
4728  std::vector<double> steady_coeff_vector = steady_residual_contribution.template get<1>();
4729  value_type __c0_pr = steady_coeff_vector[0];
4730  value_type __lambda_pr = steady_coeff_vector[1];
4731  value_type __gamma_pr = steady_coeff_vector[2];
4732 
4733  value_type __Cmf_pr=0;
4734  value_type __Cma_pr=0;
4735  value_type __Cmm_pr=0;
4736 
4737 
4738  if ( ! M_model->isSteady() )
4739  {
4740 
4741  for ( size_type __q1=0 ; __q1<__Qm; ++__q1 )
4742  {
4743  for ( size_type __m1=0 ; __m1< M_model->mMaxM(__q1); ++__m1 )
4744  {
4745  value_type m_q1 = betaMqm[__q1][__m1];
4746 
4747  for ( size_type __q2=0 ; __q2<__QRhs; ++__q2 )
4748  {
4749  for ( size_type __m2=0 ; __m2< M_model->mMaxF(0,__q2); ++__m2 )
4750  {
4751  value_type f_q2 = betaFqm[0][__q2][__m2];
4752  __Cmf_pr += 1./time_step * m_q1 * f_q2 * M_Cmf_pr[__q1][__m1][__q2][__m2].head( __N ).dot( Un );
4753  __Cmf_pr -= 1./time_step * m_q1 * f_q2 * M_Cmf_pr[__q1][__m1][__q2][__m2].head( __N ).dot( Unold );
4754  }//m2
4755  }//q2
4756 
4757  for ( size_type __q2 = 0; __q2 < __QLhs; ++__q2 )
4758  {
4759  for ( size_type __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
4760  {
4761  value_type a_q2 = betaAqm[__q2][__m2];
4762  auto m = M_Cma_pr[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Un;
4763  __Cma_pr += 1./time_step * m_q1 * a_q2 * Un.dot( m );
4764  __Cma_pr -= 1./time_step * m_q1 * a_q2 * Unold.dot( m );
4765  }//m2
4766  }//q2
4767 
4768  for ( size_type __q2 = 0; __q2 < __Qm; ++__q2 )
4769  {
4770  for ( size_type __m2 = 0; __m2 < M_model->mMaxM(__q2); ++__m2 )
4771  {
4772  value_type m_q2 = betaMqm[__q2][__m2];
4773  auto m1 = M_Cmm_pr[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Un;
4774  auto m2 = M_Cmm_pr[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Unold;
4775  __Cmm_pr += 1./( time_step*time_step ) * m_q1 * m_q2 * Un.dot( m1 );
4776  __Cmm_pr -= 1./( time_step*time_step ) * m_q1 * m_q2 * Un.dot( m2 );
4777  __Cmm_pr -= 1./( time_step*time_step ) * m_q1 * m_q2 * Unold.dot( m1 );
4778  __Cmm_pr += 1./( time_step*time_step ) * m_q1 * m_q2 * Unold.dot( m2 );
4779  }//m2
4780  }//q2
4781  }//m1
4782  }//q1
4783  }//end of if(! M_model->isSteady() )
4784 
4785 #if 0
4786  std::cout<<"[transientResidual] time "<<time<<std::endl;
4787  std::cout<<"Un = \n"<<Un<<std::endl;
4788  std::cout<<"Unold = \n"<<Unold<<std::endl;
4789  std::cout<<"__C0_pr = "<<__c0_pr<<std::endl;
4790  std::cout<<"__lambda_pr = "<<__lambda_pr<<std::endl;
4791  std::cout<<"__gamma_pr = "<<__gamma_pr<<std::endl;
4792  std::cout<<"__Cmf_pr = "<<__Cmf_pr<<std::endl;
4793  std::cout<<"__Cma_pr = "<<__Cma_pr<<std::endl;
4794  std::cout<<"__Cmm_pr = "<<__Cmm_pr<<std::endl;
4795  std::cout<<"__N = "<<__N<<std::endl;
4796 #endif
4797 
4798 
4799 
4800  value_type delta_pr = math::abs( __c0_pr+__lambda_pr+__gamma_pr+__Cmf_pr+__Cma_pr+__Cmm_pr ) ;
4801  std::vector<double> transient_coeffs_vector;
4802  transient_coeffs_vector.push_back( __c0_pr );
4803  transient_coeffs_vector.push_back( __lambda_pr );
4804  transient_coeffs_vector.push_back( __gamma_pr );
4805  transient_coeffs_vector.push_back( __Cmf_pr );
4806  transient_coeffs_vector.push_back( __Cma_pr );
4807  transient_coeffs_vector.push_back( __Cmm_pr );
4808 
4809  return boost::make_tuple( delta_pr , transient_coeffs_vector ) ;
4810 }
4811 
4812 
4813 
4814 template<typename TruthModelType>
4815 typename CRB<TruthModelType>::residual_error_type
4816 CRB<TruthModelType>::steadyPrimalResidual( int Ncur,parameter_type const& mu, vectorN_type const& Un, double time ) const
4817 {
4818 
4819  beta_vector_type betaAqm;
4820  std::vector<beta_vector_type> betaFqm, betaLqm;
4821  boost::tie( boost::tuples::ignore, betaAqm, betaFqm ) = M_model->computeBetaQm( mu , time );
4822 
4823  int __QLhs = M_model->Qa();
4824  int __QRhs = M_model->Ql( 0 );
4825  int __N = Ncur;
4826 
4827  // primal terms
4828  value_type __c0_pr = 0.0;
4829 
4830  for ( int __q1 = 0; __q1 < __QRhs; ++__q1 )
4831  {
4832  for ( int __m1 = 0; __m1 < M_model->mMaxF(0,__q1); ++__m1 )
4833  {
4834  value_type fq1 = betaFqm[0][__q1][__m1];
4835  for ( int __q2 = 0; __q2 < __QRhs; ++__q2 )
4836  {
4837  for ( int __m2 = 0; __m2 < M_model->mMaxF(0,__q2); ++__m2 )
4838  {
4839  value_type fq2 = betaFqm[0][__q2][__m2];
4840  __c0_pr += M_C0_pr[__q1][__m1][__q2][__m2]*fq1*fq2;
4841  }//m2
4842  }//q2
4843  }//m1
4844  }//q1
4845 
4846  value_type __lambda_pr = 0.0;
4847  value_type __gamma_pr = 0.0;
4848 
4849 
4850  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
4851  {
4852  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1); ++__m1 )
4853  {
4854  value_type a_q1 = betaAqm[__q1][__m1];
4855 
4856  for ( int __q2 = 0; __q2 < __QRhs; ++__q2 )
4857  {
4858  for ( int __m2 = 0; __m2 < M_model->mMaxF(0,__q2); ++__m2 )
4859  {
4860  value_type f_q2 = betaFqm[0][__q2][__m2];
4861  __lambda_pr += a_q1*f_q2*M_Lambda_pr[__q1][__m1][__q2][__m2].head( __N ).dot( Un );
4862  }//m2
4863  }//q2
4864 
4865  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
4866  {
4867  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
4868  {
4869  value_type a_q2 = betaAqm[__q2][__m2];
4870  auto m = M_Gamma_pr[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Un;
4871  __gamma_pr += a_q1 * a_q2 * Un.dot( m );
4872  }//m2
4873  }//q2
4874  }//m1
4875  }//q1
4876 
4877  //value_type delta_pr = math::sqrt( math::abs(__c0_pr+__lambda_pr+__gamma_pr) );
4878  value_type delta_pr = math::abs( __c0_pr+__lambda_pr+__gamma_pr ) ;
4879 #if(0)
4880 
4881  if ( !boost::math::isfinite( delta_pr ) )
4882  {
4883  std::cout << "delta_pr is not finite:\n"
4884  << " - c0_pr = " << __c0_pr << "\n"
4885  << " - lambda_pr = " << __lambda_pr << "\n"
4886  << " - gamma_pr = " << __gamma_pr << "\n";
4887  std::cout << " - betaAqm = " << betaAqm << "\n"
4888  << " - betaFqm = " << betaFqm << "\n";
4889  std::cout << " - Un : " << Un << "\n";
4890  }
4891 
4892  //std::cout << "delta_pr=" << delta_pr << std::endl;
4893 #endif
4894 
4895  std::vector<double> coeffs_vector;
4896  coeffs_vector.push_back( __c0_pr );
4897  coeffs_vector.push_back( __lambda_pr );
4898  coeffs_vector.push_back( __gamma_pr );
4899 
4900  return boost::make_tuple( delta_pr,coeffs_vector );
4901 }
4902 
4903 
4904 template<typename TruthModelType>
4905 typename CRB<TruthModelType>::residual_error_type
4906 CRB<TruthModelType>::transientDualResidual( int Ncur,parameter_type const& mu, vectorN_type const& Undu ,vectorN_type const& Unduold , double time_step, double time ) const
4907 {
4908  int __QLhs = M_model->Qa();
4909  int __QOutput = M_model->Ql( M_output_index );
4910  int __Qm = M_model->Qm();
4911  int __N = Ncur;
4912 
4913  beta_vector_type betaAqm;
4914  beta_vector_type betaMqm;
4915  beta_vector_type betaMFqm;
4916  std::vector<beta_vector_type> betaFqm;
4917  boost::tie( betaMqm, betaAqm, betaFqm) = M_model->computeBetaQm( mu, time );
4918 
4919  residual_error_type steady_residual_contribution = steadyDualResidual( Ncur, mu, Undu, time );
4920  std::vector<double> steady_coeff_vector = steady_residual_contribution.template get<1>();
4921  value_type __c0_du = steady_coeff_vector[0];
4922  value_type __lambda_du = steady_coeff_vector[1];
4923  value_type __gamma_du = steady_coeff_vector[2];
4924 
4925 
4926  value_type __Cmf_du=0;
4927  value_type __Cma_du=0;
4928  value_type __Cmm_du=0;
4929 
4930 #if 1
4931 
4932  if ( ! M_model->isSteady() )
4933  {
4934 
4935  for ( int __q1=0 ; __q1<__Qm; ++__q1 )
4936  {
4937  for ( int __m1=0 ; __m1< M_model->mMaxM(__q1); ++__m1 )
4938  {
4939  value_type m_q1 = betaMqm[__q1][__m1];
4940 
4941  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
4942  {
4943  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
4944  {
4945  value_type a_q2 = betaAqm[__q2][__m2];
4946  auto m = M_Cma_du[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Undu;
4947  __Cma_du += 1./time_step * m_q1 * a_q2 * Undu.dot( m );
4948  __Cma_du -= 1./time_step * m_q1 * a_q2 * Unduold.dot( m );
4949  }//m2
4950  }//q2
4951 
4952  for ( int __q2 = 0; __q2 < __Qm; ++__q2 )
4953  {
4954  for ( int __m2 = 0; __m2 < M_model->mMaxM(__q2); ++__m2 )
4955  {
4956  value_type m_q2 = betaMqm[__q2][__m2];
4957  auto m1 = M_Cmm_du[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Undu;
4958  auto m2 = M_Cmm_du[__q1][__m1][__q2][__m2].block( 0,0,__N,__N )*Unduold;
4959  __Cmm_du += 1./( time_step*time_step ) * m_q1 * m_q2 * Undu.dot( m1 );
4960  __Cmm_du -= 1./( time_step*time_step ) * m_q1 * m_q2 * Undu.dot( m2 );
4961  __Cmm_du -= 1./( time_step*time_step ) * m_q1 * m_q2 * Unduold.dot( m1 );
4962  __Cmm_du += 1./( time_step*time_step ) * m_q1 * m_q2 * Unduold.dot( m2 );
4963  } //m2
4964  } //q2
4965 
4966  } //m1
4967  }//end of loop over q1
4968  }//end of if(! M_model->isSteady() )
4969 
4970 #else
4971 #endif
4972 
4973  value_type delta_du;
4974 
4975  if ( M_model->isSteady() )
4976  delta_du = math::abs( __c0_du+__lambda_du+__gamma_du ) ;
4977  else
4978  delta_du = math::abs( __gamma_du+__Cma_du+__Cmm_du ) ;
4979 
4980 
4981 
4982 #if 0
4983  std::cout<<"[dualN2Q2] time "<<time<<std::endl;
4984  std::cout<<"Undu = \n"<<Undu<<std::endl;
4985  std::cout<<"Unduold = \n"<<Unduold<<std::endl;
4986  std::cout<<"__c0_du = "<<__c0_du<<std::endl;
4987  std::cout<<"__lambda_du = "<<__lambda_du<<std::endl;
4988  std::cout<<"__gamma_du = "<<__gamma_du<<std::endl;
4989  std::cout<<"__Cma_du = "<<__Cma_du<<std::endl;
4990  std::cout<<"__Cmm_du = "<<__Cmm_du<<std::endl;
4991 #endif
4992 
4993 
4994  std::vector<double> coeffs_vector;
4995  coeffs_vector.push_back( __c0_du );
4996  coeffs_vector.push_back( __lambda_du );
4997  coeffs_vector.push_back( __gamma_du );
4998  coeffs_vector.push_back( __Cmf_du );
4999  coeffs_vector.push_back( __Cma_du );
5000  coeffs_vector.push_back( __Cmm_du );
5001 
5002  return boost::make_tuple( delta_du,coeffs_vector );
5003 }
5004 
5005 
5006 
5007 
5008 template<typename TruthModelType>
5009 typename CRB<TruthModelType>::residual_error_type
5010 CRB<TruthModelType>::steadyDualResidual( int Ncur,parameter_type const& mu, vectorN_type const& Undu, double time ) const
5011 {
5012 
5013  int __QLhs = M_model->Qa();
5014  int __QOutput = M_model->Ql( M_output_index );
5015  int __N = Ncur;
5016 
5017  beta_vector_type betaAqm;
5018  beta_vector_type betaMqm;
5019  std::vector<beta_vector_type> betaFqm, betaLqm;
5020  boost::tie( boost::tuples::ignore, betaAqm, betaFqm ) = M_model->computeBetaQm( mu , time );
5021 
5022  value_type __c0_du = 0.0;
5023 
5024  for ( int __q1 = 0; __q1 < __QOutput; ++__q1 )
5025  {
5026  for ( int __m1 = 0; __m1 < M_model->mMaxF(M_output_index,__q1); ++__m1 )
5027  {
5028  value_type fq1 = betaFqm[M_output_index][__q1][__m1];
5029  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
5030  {
5031  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
5032  {
5033  value_type fq2 = betaFqm[M_output_index][__q2][__m2];
5034  __c0_du += M_C0_du[__q1][__m1][__q2][__m2]*fq1*fq2;
5035  }//m2
5036  }//q2
5037  } //m1
5038  } //q1
5039 
5040  value_type __lambda_du = 0.0;
5041  value_type __gamma_du = 0.0;
5042 
5043  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
5044  {
5045  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1); ++__m1 )
5046  {
5047  value_type a_q1 = betaAqm[__q1][__m1];
5048  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
5049  {
5050  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
5051  {
5052  value_type a_q2 = betaFqm[M_output_index][__q2][__m2]*a_q1;
5053  __lambda_du += a_q2 * M_Lambda_du[__q1][__m1][__q2][__m2].head( __N ).dot( Undu );
5054  }//m2
5055  }//q2
5056 
5057  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
5058  {
5059  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
5060  {
5061  value_type a_q2 = betaAqm[__q2][__m2]*a_q1;
5062  auto m = M_Gamma_du[ __q1][ __m1][ __q2][ __m2].block( 0,0,__N,__N )*Undu;
5063  __gamma_du += a_q2*Undu.dot( m );
5064  }//m2
5065  }//q2
5066  }//m1
5067  }//q1
5068 
5069  value_type delta_du = math::abs( __c0_du+__lambda_du+__gamma_du );
5070 
5071 #if(0)
5072 
5073  if ( !boost::math::isfinite( delta_du ) )
5074  {
5075  std::cout << "delta_du is not finite:\n"
5076  << " - c0_du = " << __c0_du << "\n"
5077  << " - lambda_du = " << __lambda_du << "\n"
5078  << " - gamma_du = " << __gamma_du << "\n";
5079  std::cout << " - betaAqm = " << betaAqm << "\n"
5080  << " - betaFqm = " << betaFqm << "\n";
5081  std::cout << " - Undu : " << Undu << "\n";
5082  }
5083 
5084 #endif
5085 
5086  std::vector<double> coeffs_vector;
5087  coeffs_vector.push_back( __c0_du );
5088  coeffs_vector.push_back( __lambda_du );
5089  coeffs_vector.push_back( __gamma_du );
5090  return boost::make_tuple( delta_du,coeffs_vector );
5091 }
5092 
5093 template<typename TruthModelType>
5094 void
5095 CRB<TruthModelType>::offlineResidual( int Ncur ,int number_of_added_elements )
5096 {
5097  return offlineResidual( Ncur, mpl::bool_<model_type::is_time_dependent>(), number_of_added_elements );
5098 }
5099 
5100 template<typename TruthModelType>
5101 void
5102 CRB<TruthModelType>::offlineResidual( int Ncur, mpl::bool_<true>, int number_of_added_elements )
5103 {
5104 
5105  boost::timer ti;
5106  int __QLhs = M_model->Qa();
5107  int __QRhs = M_model->Ql( 0 );
5108  int __QOutput = M_model->Ql( M_output_index );
5109  int __Qm = M_model->Qm();
5110  int __N = Ncur;
5111 
5112  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5113  std::cout << " o N=" << Ncur << " QLhs=" << __QLhs
5114  << " QRhs=" << __QRhs << " Qoutput=" << __QOutput
5115  << " Qm=" << __Qm << "\n";
5116 
5117  vector_ptrtype __X( M_backend->newVector( M_model->functionSpace() ) );
5118  vector_ptrtype __Fdu( M_backend->newVector( M_model->functionSpace() ) );
5119  vector_ptrtype __Z1( M_backend->newVector( M_model->functionSpace() ) );
5120  vector_ptrtype __Z2( M_backend->newVector( M_model->functionSpace() ) );
5121  vector_ptrtype __W( M_backend->newVector( M_model->functionSpace() ) );
5122  namespace ublas = boost::numeric::ublas;
5123 
5124  std::vector< std::vector<sparse_matrix_ptrtype> > Aqm;
5125  std::vector< std::vector<sparse_matrix_ptrtype> > Mqm;
5126  std::vector< std::vector<std::vector<vector_ptrtype> > > Fqm;
5127  std::vector<std::vector<vector_ptrtype> > MFqm;
5128  boost::tie( Mqm, Aqm, Fqm ) = M_model->computeAffineDecomposition();
5129  __X->zero();
5130  __X->add( 1.0 );
5131  //std::cout << "measure of domain= " << M_model->scalarProduct( __X, __X ) << "\n";
5132 #if 0
5133  ublas::vector<value_type> mu( P );
5134 
5135  for ( int q = 0; q < P; ++q )
5136  {
5137  mu[q] = mut( 0.0 );
5138  }
5139 
5140 #endif
5141 
5142  offlineResidual( Ncur, mpl::bool_<false>(), number_of_added_elements );
5143 
5144 
5145  for ( int __q1 = 0; __q1 < __Qm; ++__q1 )
5146  {
5147  for ( int __m1 = 0; __m1 < M_model->mMaxM(__q1); ++__m1 )
5148  {
5149 
5150  for ( int __q2 = 0; __q2 < __QRhs; ++__q2 )
5151  {
5152  for ( int __m2 = 0; __m2 < M_model->mMaxF(0,__q2); ++__m2 )
5153  {
5154 
5155  M_Cmf_pr[__q1][__m1][__q2][__m2].conservativeResize( __N );
5156 
5157  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5158  {
5159  *__X=M_WN[elem];
5160  Mqm[__q1][__m1]->multVector( __X, __W );
5161  __W->scale( -1. );
5162  M_model->l2solve( __Z1, __W );
5163 
5164  M_model->l2solve( __Z2, Fqm[0][__q2][__m2] );
5165 
5166  M_Cmf_pr[ __q1][ __m1][ __q2][ __m2]( elem ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5167  }// elem
5168  }//m2
5169  }//q2
5170  }//m1
5171  }//q1
5172 
5173  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5174  std::cout << " o M_Cmf_pr updated in " << ti.elapsed() << "s\n";
5175  ti.restart();
5176 
5177 
5178  for ( int __q1 = 0; __q1 < __Qm; ++__q1 )
5179  {
5180  for ( int __m1 = 0; __m1 < M_model->mMaxM(__q1); ++__m1 )
5181  {
5182 
5183  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
5184  {
5185  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
5186  {
5187 
5188  M_Cma_pr[__q1][__m1][__q2][__m2].conservativeResize( __N, __N );
5189 
5190  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5191  {
5192  *__X=M_WN[elem];
5193  Mqm[__q1][__m1]->multVector( __X, __W );
5194  __W->scale( -1. );
5195  M_model->l2solve( __Z1, __W );
5196 
5197  for ( int __l = 0; __l < ( int )__N; ++__l )
5198  {
5199  *__X=M_WN[__l];
5200  Aqm[__q2][__m2]->multVector( __X, __W );
5201  __W->scale( -1. );
5202  M_model->l2solve( __Z2, __W );
5203 
5204  M_Cma_pr[ __q1][ __m1][ __q2][ __m2]( elem,__l ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5205  }// l
5206  }//end of loop over elem
5207 
5208  for ( int __j = 0; __j < ( int )__N; ++__j )
5209  {
5210  *__X=M_WN[__j];
5211  Mqm[__q1][ __m1]->multVector( __X, __W );
5212  __W->scale( -1. );
5213  M_model->l2solve( __Z1, __W );
5214 
5215  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5216  {
5217  *__X=M_WN[elem];
5218  Aqm[__q2][ __m2]->multVector( __X, __W );
5219  __W->scale( -1. );
5220  M_model->l2solve( __Z2, __W );
5221 
5222  M_Cma_pr[ __q1][ __m1][ __q2][ __m2]( __j,elem ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5223  }//elem
5224  }// __j
5225 
5226  }// on m2
5227  }// on q2
5228  }// on m1
5229  } // on q1
5230 
5231  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5232  std::cout << " o M_Cma_pr updated in " << ti.elapsed() << "s\n";
5233  ti.restart();
5234 
5235  for ( int __q1 = 0; __q1 < __Qm; ++__q1 )
5236  {
5237  for ( int __m1 = 0; __m1 < M_model->mMaxM(__q1); ++__m1 )
5238  {
5239 
5240  for ( int __q2 = 0; __q2 < __Qm; ++__q2 )
5241  {
5242 
5243  for ( int __m2 = 0; __m2 < M_model->mMaxM(__q2); ++__m2 )
5244  {
5245 
5246  M_Cmm_pr[__q1][__m1][__q2][__m2].conservativeResize( __N, __N );
5247 
5248  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5249  {
5250  *__X=M_WN[elem];
5251  Mqm[__q1][__m1]->multVector( __X, __W );
5252  __W->scale( -1. );
5253  M_model->l2solve( __Z1, __W );
5254 
5255  for ( int __l = 0; __l < ( int )__N; ++__l )
5256  {
5257  *__X=M_WN[__l];
5258  Mqm[__q2][__m2]->multVector( __X, __W );
5259  __W->scale( -1. );
5260  M_model->l2solve( __Z2, __W );
5261 
5262  M_Cmm_pr[ __q1][ __m1][ __q2][ __m2]( elem,__l ) = M_model->scalarProduct( __Z1, __Z2 );
5263  }// l
5264  }//end of loop over elem
5265 
5266  for ( int __j = 0; __j < ( int )__N; ++__j )
5267  {
5268  *__X=M_WN[__j];
5269  Mqm[__q1][ __m1]->multVector( __X, __W );
5270  __W->scale( -1. );
5271  M_model->l2solve( __Z1, __W );
5272 
5273  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5274  {
5275  *__X=M_WN[elem];
5276  Mqm[__q2][ __m2]->multVector( __X, __W );
5277  __W->scale( -1. );
5278  M_model->l2solve( __Z2, __W );
5279 
5280  M_Cmm_pr[ __q1][ __m1][ __q2][ __m2]( __j,elem ) = M_model->scalarProduct( __Z1, __Z2 );
5281 
5282  }//elem
5283  }//j
5284 
5285  }// on m2
5286  } // on q2
5287  }// on m1
5288  } // on q1
5289 
5290  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5291  std::cout << " o M_Cmm_pr updated in " << ti.elapsed() << "s\n";
5292  ti.restart();
5293 
5294 
5295  sparse_matrix_ptrtype Atq1 = M_model->newMatrix();
5296  sparse_matrix_ptrtype Atq2 = M_model->newMatrix();
5297  sparse_matrix_ptrtype Mtq1 = M_model->newMatrix();
5298  sparse_matrix_ptrtype Mtq2 = M_model->newMatrix();
5299  //
5300  // Dual
5301  //
5302 
5303 
5304  LOG(INFO) << "[offlineResidual] Cmf_du Cma_du Cmm_du\n";
5305 
5306  for ( int __q1 = 0; __q1 < __Qm; ++__q1 )
5307  {
5308 
5309  for ( int __m1 = 0; __m1 < M_model->mMaxM(__q1); ++__m1 )
5310  {
5311 
5312  if( option("crb.use-symmetric-matrix").template as<bool>() )
5313  Mtq1 = Mqm[__q1][__m1];
5314  else
5315  Mqm[__q1][__m1]->transpose( Mtq1 );
5316 
5317  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
5318  {
5319  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
5320  {
5321 
5322  M_Cmf_du[__q1][__m1][__q2][__m2].conservativeResize( __N );
5323  M_Cmf_du_ini[__q1][__m1][__q2][__m2].conservativeResize( __N );
5324 
5325  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5326  {
5327  *__X=M_WNdu[elem];
5328  Mtq1->multVector( __X, __W );
5329  __W->close();
5330  __W->scale( -1. );
5331  M_model->l2solve( __Z1, __W );
5332 
5333  *__Fdu = *Fqm[M_output_index][__q2][__m2];
5334  __Fdu->close();
5335  __Fdu->scale( -1.0 );
5336  M_model->l2solve( __Z2, __Fdu );
5337 
5338  M_Cmf_du[ __q1][__m1][ __q2][__m2]( elem ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5339 
5340  *__Fdu = *Fqm[M_output_index][__q2][__m2];
5341  __Fdu->close();
5342  M_model->l2solve( __Z2, __Fdu );
5343  M_Cmf_du_ini[ __q1][__m1][ __q2][__m2]( elem ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5344  }//elem
5345  } // m2
5346  } // q2
5347  } // m1
5348  } // q1
5349 
5350 
5351  for ( int __q1 = 0; __q1 < __Qm; ++__q1 )
5352  {
5353  for ( int __m1 = 0; __m1 < M_model->mMaxM(__q1); ++__m1 )
5354  {
5355 
5356  if( option("crb.use-symmetric-matrix").template as<bool>() )
5357  Mtq1 = Mqm[__q1][__m1];
5358  else
5359  Mqm[__q1][__m1]->transpose( Mtq1 );
5360 
5361  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
5362  {
5363  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
5364  {
5365 
5366  if( option("crb.use-symmetric-matrix").template as<bool>() )
5367  Atq2 = Aqm[__q2][__m2];
5368  else
5369  Aqm[__q2][__m2]->transpose( Atq2 );
5370 
5371  M_Cma_du[__q1][__m1][__q2][__m2].conservativeResize( __N, __N );
5372 
5373  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5374  {
5375 
5376  *__X=M_WNdu[elem];
5377  Mtq1->multVector( __X, __W );
5378  __W->scale( -1. );
5379  M_model->l2solve( __Z1, __W );
5380 
5381  for ( int __l = 0; __l < ( int )__N; ++__l )
5382  {
5383  *__X=M_WNdu[__l];
5384  Atq2->multVector( __X, __W );
5385  __W->scale( -1. );
5386  M_model->l2solve( __Z2, __W );
5387 
5388  M_Cma_du[ __q1][__m1][__q2][ __m2]( elem,__l ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5389  }//j
5390  }//elem
5391 
5392  for ( int __j = 0; __j < ( int )__N; ++__j )
5393  {
5394  *__X=M_WNdu[__j];
5395  Mtq1->multVector( __X, __W );
5396  __W->scale( -1. );
5397  M_model->l2solve( __Z1, __W );
5398 
5399  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5400  {
5401  *__X=M_WNdu[elem];
5402  Atq2->multVector( __X, __W );
5403  __W->scale( -1. );
5404  M_model->l2solve( __Z2, __W );
5405 
5406  M_Cma_du[ __q1][__m1][__q2][ __m2]( __j,elem ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5407  }//elem
5408  }//j
5409 
5410  }// m2
5411  } // q2
5412  }// m1
5413  } // q1
5414 
5415  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5416  std::cout << " o Cma_du updated in " << ti.elapsed() << "s\n";
5417 
5418  ti.restart();
5419 
5420 
5421 
5422  for ( int __q1 = 0; __q1 < __Qm; ++__q1 )
5423  {
5424  for ( int __m1 = 0; __m1 < M_model->mMaxM(__q1); ++__m1 )
5425  {
5426  if( option("crb.use-symmetric-matrix").template as<bool>() )
5427  Mtq1 = Mqm[__q1][__m1];
5428  else
5429  Mqm[__q1][__m1]->transpose( Mtq1 );
5430 
5431  for ( int __q2 = 0; __q2 < __Qm; ++__q2 )
5432  {
5433  for ( int __m2 = 0; __m2 < M_model->mMaxM(__q2); ++__m2 )
5434  {
5435 
5436  if( option("crb.use-symmetric-matrix").template as<bool>() )
5437  Mtq2 = Mqm[__q2][__m2];
5438  else
5439  Mqm[__q2][__m2]->transpose( Mtq2 );
5440 
5441  M_Cmm_du[__q1][__m1][__q2][__m2].conservativeResize( __N, __N );
5442 
5443  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5444  {
5445  *__X=M_WNdu[elem];
5446  Mtq1->multVector( __X, __W );
5447  __W->scale( -1. );
5448  M_model->l2solve( __Z1, __W );
5449 
5450  for ( int __l = 0; __l < ( int )__N; ++__l )
5451  {
5452  *__X=M_WNdu[__l];
5453  Mtq2->multVector( __X, __W );
5454  __W->scale( -1. );
5455  M_model->l2solve( __Z2, __W );
5456 
5457  M_Cmm_du[ __q1][ __m1][ __q2][ __m2]( elem,__l ) = M_model->scalarProduct( __Z1, __Z2 );
5458  }//l
5459  }//elem
5460 
5461  for ( int __j = 0; __j < ( int )__N; ++__j )
5462  {
5463  *__X=M_WNdu[__j];
5464  Mtq1->multVector( __X, __W );
5465  __W->scale( -1. );
5466  M_model->l2solve( __Z1, __W );
5467 
5468  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5469  {
5470  *__X=M_WNdu[elem];
5471  Mtq2->multVector( __X, __W );
5472  __W->scale( -1. );
5473  M_model->l2solve( __Z2, __W );
5474 
5475  M_Cmm_du[ __q1][ __m1][ __q2][ __m2]( __j,elem ) = M_model->scalarProduct( __Z1, __Z2 );
5476  }// elem
5477  }// j
5478 
5479  }// m2
5480  } // q2
5481  }// m1
5482  } // q1
5483 
5484  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5485  std::cout << " o Cmm_du updated in " << ti.elapsed() << "s\n";
5486  ti.restart();
5487 
5488  LOG(INFO) << "[offlineResidual] Done.\n";
5489 
5490 }
5491 
5492 
5493 
5494 template<typename TruthModelType>
5495 void
5496 CRB<TruthModelType>::offlineResidual( int Ncur, mpl::bool_<false> , int number_of_added_elements )
5497 {
5498  boost::timer ti;
5499  int __QLhs = M_model->Qa();
5500  int __QRhs = M_model->Ql( 0 );
5501  int __QOutput = M_model->Ql( M_output_index );
5502  int __N = Ncur;
5503 
5504  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5505  std::cout << " o N=" << Ncur << " QLhs=" << __QLhs
5506  << " QRhs=" << __QRhs << " Qoutput=" << __QOutput << "\n";
5507 
5508  vector_ptrtype __X( M_backend->newVector( M_model->functionSpace() ) );
5509  vector_ptrtype __Fdu( M_backend->newVector( M_model->functionSpace() ) );
5510  vector_ptrtype __Z1( M_backend->newVector( M_model->functionSpace() ) );
5511  vector_ptrtype __Z2( M_backend->newVector( M_model->functionSpace() ) );
5512  vector_ptrtype __W( M_backend->newVector( M_model->functionSpace() ) );
5513  namespace ublas = boost::numeric::ublas;
5514 
5515  std::vector< std::vector<sparse_matrix_ptrtype> > Aqm,Mqm;
5516  std::vector< std::vector<vector_ptrtype> > MFqm;
5517  std::vector< std::vector<std::vector<vector_ptrtype> > > Fqm,Lqm;
5518  boost::tie( Mqm, Aqm, Fqm ) = M_model->computeAffineDecomposition();
5519  __X->zero();
5520  __X->add( 1.0 );
5521  //std::cout << "measure of domain= " << M_model->scalarProduct( __X, __X ) << "\n";
5522 #if 0
5523  ublas::vector<value_type> mu( P );
5524 
5525  for ( int q = 0; q < P; ++q )
5526  {
5527  mu[q] = mut( 0.0 );
5528  }
5529 
5530 #endif
5531 
5532  // Primal
5533  // no need to recompute this term each time
5534  if ( Ncur == 1 )
5535  {
5536  LOG(INFO) << "[offlineResidual] Compute Primal residual data\n";
5537  LOG(INFO) << "[offlineResidual] C0_pr\n";
5538 
5539  // see above Z1 = C^-1 F and Z2 = F
5540  for ( int __q1 = 0; __q1 < __QRhs; ++__q1 )
5541  {
5542  for ( int __m1 = 0; __m1 < M_model->mMaxF(0,__q1); ++__m1 )
5543  {
5544  //LOG(INFO) << "__Fq->norm1=" << Fq[0][__q1][__m1]->l2Norm() << "\n";
5545  M_model->l2solve( __Z1, Fqm[0][__q1][__m1] );
5546  //for ( int __q2 = 0;__q2 < __q1;++__q2 )
5547  for ( int __q2 = 0; __q2 < __QRhs; ++__q2 )
5548  {
5549  for ( int __m2 = 0; __m2 < M_model->mMaxF(0,__q2); ++__m2 )
5550  {
5551  //LOG(INFO) << "__Fq->norm 2=" << Fq[0][__q2][__m2]->l2Norm() << "\n";
5552  M_model->l2solve( __Z2, Fqm[0][__q2][__m2] );
5553  //M_C0_pr[__q1][__m1][__q2][__m2] = M_model->scalarProduct( __X, Fq[0][__q2][__m2] );
5554  M_C0_pr[__q1][__m1][__q2][__m2] = M_model->scalarProduct( __Z1, __Z2 );
5555  //M_C0_pr[__q2][__q1] = M_C0_pr[__q1][__q2];
5556  //VLOG(1) <<"M_C0_pr[" << __q1 << "][" << __m1 << "]["<< __q2 << "][" << __m2 << "]=" << M_C0_pr[__q1][__m1][__q2][__m2] << "\n";
5557  //LOG(INFO) << "M_C0_pr[" << __q1 << "][" << __m1 << "]["<< __q2 << "][" << __m2 << "]=" << M_C0_pr[__q1][__m1][__q2][__m2] << "\n";
5558  }//end of loop __m2
5559  }//end of loop __q2
5560  //M_C0_pr[__q1][__q1] = M_model->scalarProduct( __X, __X );
5561  }//end of loop __m1
5562  }//end of loop __q1
5563  }// Ncur==1
5564 
5565  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5566  std::cout << " o initialize offlineResidual in " << ti.elapsed() << "s\n";
5567  ti.restart();
5568 
5569 #if 0
5570  parameter_type const& mu = M_WNmu->at( 0 );
5571  //std::cout << "[offlineResidual] mu=" << mu << "\n";
5572  beta_vector_type betaAqm;
5573  std::vector<beta_vector_type> betaFqm;
5574  boost::tie( boost::tuples::ignore, betaAqm, betaFqm ) = M_model->computeBetaQm( mu );
5575  value_type __c0_pr = 0.0;
5576 
5577  for ( int __q1 = 0; __q1 < __QRhs; ++__q1 )
5578  {
5579  for ( int __m1 = 0; __m1 < M_model->mMaxF(0,__q1); ++__m1 )
5580  {
5581  value_type fq1 = betaFqm[0][__q1][__m1];
5582 
5583  for ( int __q2 = 0; __q2 < __QRhs; ++__q2 )
5584  {
5585  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
5586  {
5587  value_type fq2 = betaFqm[0][__q2][__m2];
5588  __c0_pr += M_C0_pr[__q1][__m1][__q2][__m2]*fq1*fq2;
5589  }
5590  }
5591  }//end of loop __m1
5592  }//end of loop __q1
5593 
5594 
5595  //std::cout << "c0=" << __c0_pr << std::endl;
5596 
5597  std::vector< sparse_matrix_ptrtype > A;
5598  std::vector< std::vector<vector_ptrtype> > F;
5599  boost::tie( A, F ) = M_model->update( mu );
5600  M_model->l2solve( __X, F[0] );
5601  //std::cout << "c0 2 = " << M_model->scalarProduct( __X, __X ) << "\n";;
5602 #endif
5603 
5604  //
5605  // Primal
5606  //
5607  LOG(INFO) << "[offlineResidual] Lambda_pr, Gamma_pr\n";
5608 
5609  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5610  {
5611  *__X=M_WN[elem];
5612 
5613  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
5614  {
5615  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1) ; ++__m1 )
5616  {
5617  Aqm[__q1][__m1]->multVector( __X, __W );
5618  __W->scale( -1. );
5619  //std::cout << "__W->norm=" << __W->l2Norm() << "\n";
5620  M_model->l2solve( __Z1, __W );
5621  for ( int __q2 = 0; __q2 < __QRhs; ++__q2 )
5622  {
5623  for ( int __m2 = 0; __m2 < M_model->mMaxF(0, __q2); ++__m2 )
5624  {
5625  M_Lambda_pr[__q1][__m1][__q2][__m2].conservativeResize( __N );
5626  //__Y = Fq[0][__q2];
5627  //std::cout << "__Fq->norm=" << Fq[0][__q2]->l2Norm() << "\n";
5628  M_model->l2solve( __Z2, Fqm[0][__q2][__m2] );
5629  M_Lambda_pr[ __q1][ __m1][ __q2][ __m2]( elem ) = 2.0*M_model->scalarProduct( __Z1, __Z2 );
5630  //VLOG(1) << "M_Lambda_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "]=" << M_Lambda_pr[__q1][__m1][__q2][__m2][__j] << "\n";
5631  //std::cout << "M_Lambda_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "]=" << M_Lambda_pr[__q1][__m1][__q2][__m2][__j] << "\n";
5632  }//m2
5633  }//end of __q2
5634  }//end of loop __m1
5635  }//end of __q1
5636  }//elem
5637 
5638  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5639  std::cout << " o Lambda_pr updated in " << ti.elapsed() << "s\n";
5640 
5641  ti.restart();
5642 
5643  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
5644  {
5645  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1); ++__m1 )
5646  {
5647 
5648  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
5649  {
5650 
5651  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
5652  {
5653 
5654  M_Gamma_pr[__q1][__m1][__q2][__m2].conservativeResize( __N, __N );
5655 
5656  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5657  {
5658  *__X=M_WN[elem];
5659  Aqm[__q1][__m1]->multVector( __X, __W );
5660  __W->scale( -1. );
5661  //std::cout << "__W->norm=" << __W->l2Norm() << "\n";
5662  M_model->l2solve( __Z1, __W );
5663 
5664  //Aq[__q2]->multVector( __Z1, __W );
5665  for ( int __l = 0; __l < ( int )__N; ++__l )
5666  {
5667  *__X=M_WN[__l];
5668  Aqm[__q2][__m2]->multVector( __X, __W );
5669  __W->scale( -1. );
5670  //std::cout << "__W2_pr->norm=" << __W->l2Norm() << "\n";
5671  M_model->l2solve( __Z2, __W );
5672  M_Gamma_pr[ __q1][ __m1][ __q2][ __m2]( elem,__l ) = M_model->scalarProduct( __Z1, __Z2 );
5673  //M_Gamma_pr[ __q2][ __q1][ __j ][__l] = M_Gamma_pr[ __q1][ __q2][ __j ][__l];
5674  //VLOG(1) << "M_Gamma_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_pr[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5675  //std::cout << "M_Gamma_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_pr[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5676  }//end of loop over l
5677  }//end of loop over elem
5678 
5679  for ( int __j = 0; __j < ( int )__N; ++__j )
5680  {
5681  *__X=M_WN[__j];
5682  Aqm[__q1][__m1]->multVector( __X, __W );
5683  __W->scale( -1. );
5684  //std::cout << "__W->norm=" << __W->l2Norm() << "\n";
5685  M_model->l2solve( __Z1, __W );
5686 
5687  //Aq[__q2]->multVector( __Z1, __W );
5688  //column N-1
5689  //int __l = __N-1;
5690  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5691  {
5692  *__X=M_WN[elem];
5693  Aqm[__q2][__m2]->multVector( __X, __W );
5694  __W->scale( -1. );
5695  //std::cout << "__W2_pr->norm=" << __W->l2Norm() << "\n";
5696  M_model->l2solve( __Z2, __W );
5697  M_Gamma_pr[ __q1][ __m1][ __q2][ __m2]( __j,elem ) = M_model->scalarProduct( __Z1, __Z2 );
5698  //M_Gamma_pr[ __q2][ __q1][ __j ][__l] = M_Gamma_pr[ __q1][ __q2][ __j ][__l];
5699  //VLOG(1) << "M_Gamma_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_pr[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5700  //std::cout << "M_Gamma_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_pr[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5701  }// end of loop elem
5702  }// end of loop __j
5703  }// end of loop __m2
5704  }// end of loop __q2
5705  }// on m1
5706  } // on q1
5707 
5708  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5709  std::cout << " o Gamma_pr updated in " << ti.elapsed() << "s\n";
5710  ti.restart();
5711  sparse_matrix_ptrtype Atq1 = M_model->newMatrix();
5712  sparse_matrix_ptrtype Atq2 = M_model->newMatrix();
5713 
5714  //
5715  // Dual
5716  //
5717  // compute this only once
5718  if( solve_dual_problem )
5719  {
5720  if ( Ncur == 1 )
5721  {
5722  LOG(INFO) << "[offlineResidual] Compute Dual residual data\n";
5723  LOG(INFO) << "[offlineResidual] C0_du\n";
5724 
5725  for ( int __q1 = 0; __q1 < __QOutput; ++__q1 )
5726  {
5727  for ( int __m1 = 0; __m1 < M_model->mMaxF(M_output_index,__q1); ++__m1 )
5728  {
5729  *__Fdu = *Fqm[M_output_index][__q1][__m1];
5730  __Fdu->close();
5731  __Fdu->scale( -1.0 );
5732  M_model->l2solve( __Z1, __Fdu );
5733 
5734  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
5735  {
5736  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2); ++__m2 )
5737  {
5738  *__Fdu = *Fqm[M_output_index][__q2][__m2];
5739  __Fdu->close();
5740  __Fdu->scale( -1.0 );
5741  M_model->l2solve( __Z2, __Fdu );
5742  M_C0_du[__q1][__m1][__q2][__m2] = M_model->scalarProduct( __Z1, __Z2 );
5743  //M_C0_du[__q2][__q1] = M_C0_du[__q1][__q2];
5744  //M_C0_du[__q1][__q1] = M_model->scalarProduct( __Xdu, __Xdu );
5745  }//end of loop __m2
5746  }//end of loop __q2
5747  }//end of loop __m1
5748  }//end of loop __q1
5749 
5750  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5751  std::cout << " o C0_du updated in " << ti.elapsed() << "s\n";
5752  ti.restart();
5753  }
5754 
5755  LOG(INFO) << "[offlineResidual] Lambda_du, Gamma_du\n";
5756 
5757  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5758  {
5759  *__X=M_WNdu[elem];
5760 
5761  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
5762  {
5763  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1); ++__m1 )
5764  {
5765 
5766  if( option("crb.use-symmetric-matrix").template as<bool>() )
5767  Atq1 = Aqm[__q1][__m1];
5768  else
5769  Aqm[__q1][__m1]->transpose( Atq1 );
5770 
5771  Atq1->multVector( __X, __W );
5772  __W->close();
5773  __W->scale( -1. );
5774  //std::cout << "__W->norm=" << __W->l2Norm() << "\n";
5775  M_model->l2solve( __Z1, __W );
5776 
5777  for ( int __q2 = 0; __q2 < __QOutput; ++__q2 )
5778  {
5779  for ( int __m2 = 0; __m2 < M_model->mMaxF(M_output_index,__q2) ; ++__m2 )
5780  {
5781  M_Lambda_du[__q1][__m1][__q2][__m2].conservativeResize( __N );
5782 
5783  *__Fdu = *Fqm[M_output_index][__q2][__m2];
5784  __Fdu->close();
5785  __Fdu->scale( -1.0 );
5786  M_model->l2solve( __Z2, __Fdu );
5787  M_Lambda_du[ __q1][ __m1][ __q2][ __m2]( elem ) = 2.0*M_model->scalarProduct( __Z2, __Z1 );
5788  //VLOG(1) << "M_Lambda_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "]=" << M_Lambda_pr[__q1][__m1][__q2][__m2][__j] << "\n";
5789  //std::cout << "M_Lambda_pr[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "]=" << M_Lambda_pr[__q1][__m1][__q2][__m2][__j] << "\n";
5790  } // m2
5791  } // q2
5792  } // m1
5793  } // q1
5794  }//elem
5795 
5796  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5797  std::cout << " o Lambda_du updated in " << ti.elapsed() << "s\n";
5798  ti.restart();
5799 
5800  for ( int __q1 = 0; __q1 < __QLhs; ++__q1 )
5801  {
5802  for ( int __m1 = 0; __m1 < M_model->mMaxA(__q1); ++__m1 )
5803  {
5804 
5805  if( option("crb.use-symmetric-matrix").template as<bool>() )
5806  Atq1=Aqm[__q1][__m1];
5807  else
5808  Aqm[__q1][__m1]->transpose( Atq1 );
5809 
5810  for ( int __q2 = 0; __q2 < __QLhs; ++__q2 )
5811  {
5812  for ( int __m2 = 0; __m2 < M_model->mMaxA(__q2); ++__m2 )
5813  {
5814 
5815  if( option("crb.use-symmetric-matrix").template as<bool>() )
5816  Atq2 = Aqm[__q2][__m2];
5817  else
5818  Aqm[__q2][__m2]->transpose( Atq2 );
5819 
5820  M_Gamma_du[__q1][__m1][__q2][__m2].conservativeResize( __N, __N );
5821 
5822  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5823  {
5824  //int __j = __N-1;
5825  *__X=M_WNdu[elem];
5826  Atq1->multVector( __X, __W );
5827  __W->scale( -1. );
5828  //std::cout << "__W->norm=" << __W->l2Norm() << "\n";
5829  M_model->l2solve( __Z1, __W );
5830 
5831  //Aq[__q2][__m2]->multVector( __Z1, __W );
5832 
5833  for ( int __l = 0; __l < ( int )__N; ++__l )
5834  {
5835  *__X=M_WNdu[__l];
5836  Atq2->multVector( __X, __W );
5837  __W->scale( -1. );
5838  //std::cout << "__W2_pr->norm=" << __W->l2Norm() << "\n";
5839  M_model->l2solve( __Z2, __W );
5840  M_Gamma_du[ __q1][ __m1][ __q2][ __m2]( elem,__l ) = M_model->scalarProduct( __Z1, __Z2 );
5841  //M_Gamma_pr[ __q2][ __q1][ __j ][__l] = M_Gamma_pr[ __q1][ __q2][ __j ][__l];
5842  //VLOG(1) << "M_Gamma_du[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_du[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5843  //std::cout << "M_Gamma_du[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_du[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5844  } // __l
5845  }// elem
5846 
5847  // update column __N-1
5848  for ( int __j = 0; __j < ( int )__N; ++__j )
5849  {
5850  *__X=M_WNdu[__j];
5851  Atq1->multVector( __X, __W );
5852  __W->scale( -1. );
5853  //std::cout << "__W->norm=" << __W->l2Norm() << "\n";
5854  M_model->l2solve( __Z1, __W );
5855 
5856  //Aq[__q2][__m2]->multVector( __Z1, __W );
5857  //int __l = __N-1;
5858  for ( int elem=__N-number_of_added_elements; elem<__N; elem++ )
5859  {
5860  *__X=M_WNdu[elem];
5861  Atq2->multVector( __X, __W );
5862  __W->scale( -1. );
5863  //std::cout << "__W2_pr->norm=" << __W->l2Norm() << "\n";
5864  M_model->l2solve( __Z2, __W );
5865  M_Gamma_du[ __q1][ __m1][ __q2][ __m2]( __j,elem ) = M_model->scalarProduct( __Z1, __Z2 );
5866  //M_Gamma_pr[ __q2][ __q1][ __j ][__l] = M_Gamma_pr[ __q1][ __q2][ __j ][__l];
5867  //VLOG(1) << "M_Gamma_du[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_du[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5868  //std::cout << "M_Gamma_du[" << __q1 << "][" << __m1 << "][" << __q2 << "][" << __m2 << "][" << __j << "][" << __l << "]=" << M_Gamma_du[__q1][__m1][__q2][__m2][__j][__l] << "\n";
5869  }//elem
5870  }// __j
5871  }// on m2
5872  }// on q2
5873  }// on m1
5874  } // on q1
5875 
5876  if( Environment::worldComm().globalRank() == Environment::worldComm().masterRank() )
5877  std::cout << " o Gamma_du updated in " << ti.elapsed() << "s\n";
5878  ti.restart();
5879  LOG(INFO) << "[offlineResidual] Done.\n";
5880 
5881  }//end of if (solve_dual_problem)
5882 }
5883 
5884 template<typename TruthModelType>
5885 void
5887 {
5888 
5889  if( M_rbconv_contains_primal_and_dual_contributions )
5890  {
5891  typedef convergence_type::left_map::const_iterator iterator;
5892  LOG(INFO)<<"\nMax error during offline stage\n";
5893  for(iterator it = M_rbconv.left.begin(); it != M_rbconv.left.end(); ++it)
5894  LOG(INFO)<<"N : "<<it->first<<" - maxerror : "<<it->second.template get<0>()<<"\n";
5895 
5896  LOG(INFO)<<"\nPrimal contribution\n";
5897  for(iterator it = M_rbconv.left.begin(); it != M_rbconv.left.end(); ++it)
5898  LOG(INFO)<<"N : "<<it->first<<" - delta_pr : "<<it->second.template get<1>()<<"\n";
5899 
5900  LOG(INFO)<<"\nDual contribution\n";
5901  for(iterator it = M_rbconv.left.begin(); it != M_rbconv.left.end(); ++it)
5902  LOG(INFO)<<"N : "<<it->first<<" - delta_du : "<<it->second.template get<2>()<<"\n";
5903  LOG(INFO)<<"\n";
5904  }
5905  else
5906  throw std::logic_error( "[CRB::printErrorsDuringRbConstruction] ERROR, the database is too old to print the error during offline step, use the option rebuild-database = true" );
5907 
5908 }
5909 
5910 
5911 
5912 template<typename TruthModelType>
5913 void
5915 {
5916  LOG(INFO)<<" List of parameter selectionned during the offline algorithm \n";
5917  for(int k=0;k<M_WNmu->size();k++)
5918  {
5919  std::cout<<" mu "<<k<<" = [ ";
5920  LOG(INFO)<<" mu "<<k<<" = [ ";
5921  parameter_type const& _mu = M_WNmu->at( k );
5922  for( int i=0; i<_mu.size()-1; i++ )
5923  {
5924  LOG(INFO)<<_mu(i)<<" , ";
5925  std::cout<<_mu(i)<<" , ";
5926  }
5927  LOG(INFO)<<_mu( _mu.size()-1 )<<" ] \n";
5928  std::cout<<_mu( _mu.size()-1 )<<" ] "<<std::endl;
5929  }
5930 }
5931 
5932 
5933 template<typename TruthModelType>
5935 CRB<TruthModelType>::expansion( parameter_type const& mu , int N , int time_index )
5936 {
5937  int Nwn;
5938 
5939  if( N > 0 )
5940  Nwn = N;
5941  else
5942  Nwn = M_N;
5943 
5944  std::vector<vectorN_type> uN;
5945  std::vector<vectorN_type> uNdu;
5946  std::vector<vectorN_type> uNold;
5947  std::vector<vectorN_type> uNduold;
5948 
5949  auto o = lb( Nwn, mu, uN, uNdu , uNold, uNduold );
5950  int size = uN.size();
5951  FEELPP_ASSERT( N <= M_WN.size() )( N )( M_WN.size() ).error( "invalid expansion size ( N and M_WN ) ");
5952  element_type ucrb;
5953  if( time_index == -1 )
5954  ucrb = Feel::expansion( M_WN, uN[size-1] , Nwn);
5955  else
5956  {
5957  CHECK( time_index < size )<<" call crb::expansion with a wrong value of time index : "<<time_index<<" or size of uN vector is only "<<size;
5958  ucrb = Feel::expansion( M_WN, uN[time_index] , Nwn);
5959  }
5960  return ucrb;
5961 }
5962 
5963 
5964 template<typename TruthModelType>
5966 CRB<TruthModelType>::expansion( vectorN_type const& u , int const N, wn_type const & WN ) const
5967 {
5968  int Nwn;
5969 
5970  if( N > 0 )
5971  Nwn = N;
5972  else
5973  Nwn = M_N;
5974 
5975  //FEELPP_ASSERT( M_WN.size() == u.size() )( M_WN.size() )( u.size() ).error( "invalid expansion size");
5976  FEELPP_ASSERT( Nwn <= WN.size() )( Nwn )( WN.size() ).error( "invalid expansion size ( Nwn and WN ) ");
5977  FEELPP_ASSERT( Nwn <= u.size() )( Nwn )( WN.size() ).error( "invalid expansion size ( Nwn and u ) ");
5978  //FEELPP_ASSERT( Nwn == u.size() )( Nwn )( u.size() ).error( "invalid expansion size");
5979  return Feel::expansion( WN, u, N );
5980 }
5981 
5982 
5983 template<typename TruthModelType>
5984 boost::tuple<double,double, typename CRB<TruthModelType>::solutions_tuple, double, double, double, typename CRB<TruthModelType>::upper_bounds_tuple >
5985 CRB<TruthModelType>::run( parameter_type const& mu, double eps , int N)
5986 {
5987 
5988  M_compute_variance = this->vm()["crb.compute-variance"].template as<bool>();
5989 
5990  //int Nwn = M_N;
5991  int Nwn_max = vm()["crb.dimension-max"].template as<int>();
5992 #if 0
5993  if ( M_error_type!=CRB_EMPIRICAL )
5994  {
5995  auto lo = M_rbconv.right.range( boost::bimaps::unbounded, boost::bimaps::_key <= eps );
5996 
5997  for ( auto it = lo.first; it != lo.second; ++it )
5998  {
5999  std::cout << "rbconv[" << it->first <<"]=" << it->second << "\n";
6000  }
6001 
6002  auto it = M_rbconv.project_left( lo.first );
6003  Nwn = it->first;
6004  std::cout << "Nwn = "<< Nwn << " error = "<< it->second.template get<0>() << " eps=" << eps << "\n";
6005  }
6006 
6007  if ( this->vm()["crb.check.residual"].template as<bool>() )
6008  {
6009  std::vector< std::vector<double> > primal_residual_coefficients = error_estimation.template get<1>();
6010  std::vector< std::vector<double> > dual_residual_coefficients = error_estimation.template get<2>();
6011  std::vector<element_ptrtype> Un,Unold,Undu,Unduold;
6012  buildFunctionFromRbCoefficients(Nwn, uN, M_WN, Un );
6013  buildFunctionFromRbCoefficients(Nwn, uNold, M_WN, Unold );
6014  buildFunctionFromRbCoefficients(Nwn, uNdu, M_WNdu, Undu );
6015  buildFunctionFromRbCoefficients(Nwn, uNduold, M_WNdu, Unduold );
6016  compareResidualsForTransientProblems(Nwn, mu , Un, Unold, Undu, Unduold, primal_residual_coefficients, dual_residual_coefficients );
6017  }
6018 #endif
6019 
6020  std::vector<vectorN_type> uN;
6021  std::vector<vectorN_type> uNdu;
6022  std::vector<vectorN_type> uNold;
6023  std::vector<vectorN_type> uNduold;
6024 
6025  int Nwn;
6026  if( N > 0 )
6027  {
6028  //in this case we want to fix Nwn
6029  Nwn = N;
6030  }
6031  else
6032  {
6033  //Nwn = Nwn_max;
6034  //M_N may be different of dimension-max
6035  Nwn = M_N;
6036  }
6037  auto o = lb( Nwn, mu, uN, uNdu , uNold, uNduold );
6038  double output = o.template get<0>();
6039 
6040  auto error_estimation = delta( Nwn, mu, uN, uNdu , uNold, uNduold );
6041  double output_upper_bound = error_estimation.template get<0>();
6042  double condition_number = o.template get<1>();
6043  auto primal_coefficients = error_estimation.template get<1>();
6044  auto dual_coefficients = error_estimation.template get<2>();
6045 
6046  //compute dual norm of primal/dual residual at final time
6047  int nb_dt = primal_coefficients.size();
6048  int final_time_index = nb_dt-1;
6049  double primal_residual_norm = 0;
6050  double dual_residual_norm = 0;
6051 
6052  if ( M_error_type == CRB_RESIDUAL || M_error_type == CRB_RESIDUAL_SCM )
6053  {
6054  int nb_coeff = primal_coefficients[final_time_index].size();
6055  for(int i=0 ; i<nb_coeff ; i++)
6056  primal_residual_norm += primal_coefficients[final_time_index][i] ;
6057 
6058  bool solve_dual_problem = this->vm()["crb.solve-dual-problem"].template as<bool>() ;
6059  if( solve_dual_problem )
6060  {
6061  if ( M_model->isSteady() )
6062  dual_residual_norm = math::abs( dual_coefficients[0][0]+dual_coefficients[0][1]+dual_coefficients[0][2] ) ;
6063  else
6064  dual_residual_norm = math::abs( dual_coefficients[0][2]+dual_coefficients[0][4]+dual_coefficients[0][5] ) ;
6065  }
6066  primal_residual_norm = math::sqrt( math::abs(primal_residual_norm) );
6067  dual_residual_norm = math::sqrt( math::abs(dual_residual_norm) );
6068  }
6069  double delta_pr = error_estimation.template get<3>();
6070  double delta_du = error_estimation.template get<4>();
6071  int size = uN.size();
6072 
6073  auto upper_bounds = boost::make_tuple(output_upper_bound , delta_pr, delta_du , primal_coefficients , dual_coefficients );
6074  auto solutions = boost::make_tuple( uN , uNdu, uNold, uNduold);
6075  return boost::make_tuple( output , Nwn , solutions, condition_number , primal_residual_norm , dual_residual_norm, upper_bounds );
6076 }
6077 
6078 
6079 template<typename TruthModelType>
6080 void
6081 CRB<TruthModelType>::run( const double * X, unsigned long N, double * Y, unsigned long P )
6082 {
6083  return run( X, N, Y, P, mpl::bool_<model_type::is_time_dependent>() );
6084 }
6085 
6086 
6087 
6088 template<typename TruthModelType>
6089 void
6090 CRB<TruthModelType>::run( const double * X, unsigned long N, double * Y, unsigned long P, mpl::bool_<true> )
6091 {
6092  //std::cout<<"N = "<<N<<" et P = "<<P<<std::endl;
6093 
6094  for ( unsigned long p= 0; p < N-5; ++p ) std::cout<<"mu["<<p<<"] = "<<X[p]<<std::endl;
6095 
6096 
6097  parameter_type mu( M_Dmu );
6098 
6099  // the last parameter is the max error
6100  for ( unsigned long p= 0; p < N-5; ++p )
6101  mu( p ) = X[p];
6102 
6103 
6104  //double meshSize = X[N-4];
6105  //M_model->setMeshSize(meshSize);
6106  // setOutputIndex( ( int )X[N-3] );
6107  // std::cout<<"output index = "<<X[N-3]<<std::endl;
6108  // int Nwn = X[N-2];
6109  // std::cout<<"Nwn : "<<X[N-2]<<std::endl;
6110  // size_type maxerror = X[N-1];
6111  // std::cout<<"maxerror = "<<X[N-1]<<std::endl;
6112  //CRBErrorType errorType =(CRBErrorType)X[N-1];
6113  //setCRBErrorType(errorType);
6114 
6115  setOutputIndex( ( int )X[N-5] );
6116  //std::cout<<"output_index = "<<X[N-5]<<std::endl;
6117  int Nwn = X[N-4];
6118  //std::cout<<" Nwn = "<<Nwn<<std::endl;
6119  int maxerror = X[N-3];
6120  //std::cout<<" maxerror = "<<maxerror<<std::endl;
6121  CRBErrorType errorType =( CRBErrorType )X[N-2];
6122  //std::cout<<"errorType = "<<X[N-2]<<std::endl;
6123  setCRBErrorType( errorType );
6124  M_compute_variance = X[N-1];
6125  //std::cout<<"M_compute_variance = "<<M_compute_variance<<std::endl;
6126 
6127 
6128 #if 0
6129 
6130  if ( M_error_type!=CRB_EMPIRICAL )
6131  {
6132  auto lo = M_rbconv.right.range( boost::bimaps::unbounded,boost::bimaps::_key <= maxerror );
6133 
6134  for ( auto it = lo.first; it != lo.second; ++it )
6135  {
6136  std::cout << "rbconv[" << it->first <<"]=" << it->second << "\n";
6137  }
6138 
6139  auto it = M_rbconv.project_left( lo.first );
6140  Nwn = it->first;
6141  }
6142 
6143 #endif
6144 
6145  std::vector<vectorN_type> uN;
6146  std::vector<vectorN_type> uNdu;
6147  std::vector<vectorN_type> uNold ;
6148  std::vector<vectorN_type> uNduold;
6149 
6150  FEELPP_ASSERT( P == 2 )( P ).warn( "invalid number of outputs" );
6151  auto o = lb( Nwn, mu, uN, uNdu , uNold, uNduold );
6152  auto e = delta( Nwn, mu, uN, uNdu , uNold, uNduold );
6153  Y[0] = o.template get<0>();
6154  Y[1] = e.template get<0>();
6155 }
6156 
6157 
6158 template<typename TruthModelType>
6159 void
6160 CRB<TruthModelType>::run( const double * X, unsigned long N, double * Y, unsigned long P, mpl::bool_<false> )
6161 {
6162 
6163  parameter_type mu( M_Dmu );
6164 
6165  for ( unsigned long p= 0; p < N-5; ++p )
6166  {
6167  mu( p ) = X[p];
6168  std::cout << "mu( " << p << " ) = " << mu( p ) << std::endl;
6169  }
6170 
6171  // std::cout<<" list of parameters : [";
6172  // for ( unsigned long i=0; i<N-1; i++ ) std::cout<<X[i]<<" , ";
6173  // std::cout<<X[N-1]<<" ] "<<std::endl;
6174 
6175 
6176  setOutputIndex( ( int )X[N-5] );
6177  //std::cout<<"output_index = "<<X[N-5]<<std::endl;
6178  int Nwn = X[N-4];
6179  //std::cout<<" Nwn = "<<Nwn<<std::endl;
6180  int maxerror = X[N-3];
6181  //std::cout<<" maxerror = "<<maxerror<<std::endl;
6182  CRBErrorType errorType =( CRBErrorType )X[N-2];
6183  //std::cout<<"errorType = "<<X[N-2]<<std::endl;
6184  setCRBErrorType( errorType );
6185  M_compute_variance = X[N-1];
6186  //std::cout<<"M_compute_variance = "<<M_compute_variance<<std::endl;
6187 
6188 #if 0
6189  auto lo = M_rbconv.right.range( boost::bimaps::unbounded,boost::bimaps::_key <= maxerror );
6190 
6191 
6192  for ( auto it = lo.first; it != lo.second; ++it )
6193  {
6194  std::cout << "rbconv[" << it->first <<"]=" << it->second << "\n";
6195  }
6196 
6197  auto it = M_rbconv.project_left( lo.first );
6198  Nwn = it->first;
6199  //std::cout << "Nwn = "<< Nwn << " error = "<< it->second << " maxerror=" << maxerror << " ErrorType = "<<errorType <<"\n";
6200 #endif
6201  //int Nwn = M_WN.size();
6202  std::vector<vectorN_type> uN;
6203  std::vector<vectorN_type> uNdu;
6204  std::vector<vectorN_type> uNold ;
6205  std::vector<vectorN_type> uNduold;
6206 
6207  FEELPP_ASSERT( P == 2 )( P ).warn( "invalid number of outputs" );
6208  auto o = lb( Nwn, mu, uN, uNdu , uNold, uNduold );
6209  auto e = delta( Nwn, mu, uN, uNdu , uNold, uNduold );
6210  Y[0] = o.template get<0>();
6211  Y[1] = e.template get<0>();
6212 }
6213 
6214 
6215 
6216 
6217 
6218 
6219 template<typename TruthModelType>
6220 void
6221 CRB<TruthModelType>::projectionOnPodSpace( const element_type & u , element_ptrtype& projection, const std::string& name_of_space )
6222 {
6223 
6224  projection->zero();
6225 
6226  if ( name_of_space=="dual" )
6227  {
6228  if ( orthonormalize_dual )
6229  //in this case we can simplify because elements of reduced basis are orthonormalized
6230  {
6231  BOOST_FOREACH( auto du, M_WNdu )
6232  {
6233  element_type e = du.functionSpace()->element();
6234  e = du;
6235  double k = M_model->scalarProduct( u, e );
6236  e.scale( k );
6237  projection->add( 1 , e );
6238  }
6239  }//end of if orthonormalize_dual
6240 
6241  else
6242  {
6243  matrixN_type MN ( ( int )M_N, ( int )M_N ) ;
6244  vectorN_type FN ( ( int )M_N );
6245 
6246  for ( size_type i=0; i<M_N; i++ )
6247  {
6248  for ( size_type j=0; j<i; j++ )
6249  {
6250  MN( i,j ) = M_model->scalarProduct( M_WNdu[j] , M_WNdu[i] );
6251  MN( j,i ) = MN( i,j );
6252  }
6253 
6254  MN( i,i ) = M_model->scalarProduct( M_WNdu[i] , M_WNdu[i] );
6255  FN( i ) = M_model->scalarProduct( u,M_WNdu[i] );
6256  }
6257 
6258  vectorN_type projectionN ( ( int ) M_N );
6259  projectionN = MN.lu().solve( FN );
6260  int index=0;
6261  BOOST_FOREACH( auto du, M_WNdu )
6262  {
6263  element_type e = du.functionSpace()->element();
6264  e = du;
6265  double k = projectionN( index );
6266  e.scale( k );
6267  projection->add( 1 , e );
6268  index++;
6269  }
6270  }//end of if( ! orthonormalize_dual )
6271  }//end of projection on dual POD space
6272 
6273  else
6274  {
6275  if ( orthonormalize_primal )
6276  {
6277  BOOST_FOREACH( auto pr, M_WN )
6278  {
6279  auto e = pr.functionSpace()->element();
6280  e = pr;
6281  double k = M_model->scalarProduct( u, e );
6282  e.scale( k );
6283  projection->add( 1 , e );
6284  }
6285  }//end of if orthonormalize_primal
6286 
6287  else
6288  {
6289  matrixN_type MN ( ( int )M_N, ( int )M_N ) ;
6290  vectorN_type FN ( ( int )M_N );
6291 
6292  for ( size_type i=0; i<M_N; i++ )
6293  {
6294  for ( size_type j=0; j<i; j++ )
6295  {
6296  MN( i,j ) = M_model->scalarProduct( M_WN[j] , M_WN[i] );
6297  MN( j,i ) = MN( i,j );
6298  }
6299 
6300  MN( i,i ) = M_model->scalarProduct( M_WN[i] , M_WN[i] );
6301  FN( i ) = M_model->scalarProduct( u,M_WN[i] );
6302  }
6303 
6304  vectorN_type projectionN ( ( int ) M_N );
6305  projectionN = MN.lu().solve( FN );
6306  int index=0;
6307  BOOST_FOREACH( auto pr, M_WN )
6308  {
6309  element_type e = pr.functionSpace()->element();
6310  e = pr;
6311  double k = projectionN( index );
6312  e.scale( k );
6313  projection->add( 1 , e );
6314  index++;
6315  }
6316  }//end of if( ! orthonormalize_primal )
6317  }//end of projection on primal POD space
6318 
6319 }
6320 
6321 
6322 
6323 template<typename TruthModelType>
6324 void
6326 {
6327 
6328  double min=0,max=0,mean=0,standard_deviation=0;
6329 
6330  int n_eval = option(_name="crb.computational-time-neval").template as<int>();
6331 
6332  Eigen::Matrix<double, Eigen::Dynamic, 1> time_crb;
6333  time_crb.resize( n_eval );
6334 
6335  sampling_ptrtype Sampling( new sampling_type( M_Dmu ) );
6336  Sampling->logEquidistribute( n_eval );
6337 
6338  bool cvg = option(_name="crb.cvg-study").template as<bool>();
6339  int dimension = this->dimension();
6340  double tol = option(_name="crb.online-tolerance").template as<double>();
6341 
6342  int N=dimension;//by default we perform only one time statistics
6343 
6344  if( cvg ) //if we want to compute time statistics for every crb basis then we start at 1
6345  N=1;
6346 
6347  int proc_number = Environment::worldComm().globalRank();
6348  int master = Environment::worldComm().masterRank();
6349 
6350  //write on a file
6351  std::string file_name = "cvg-timing-crb.dat";
6352 
6353  std::ofstream conv;
6354  if( proc_number == master )
6355  {
6356  conv.open(file_name, std::ios::app);
6357  conv << "NbBasis" << "\t" << "min" <<"\t"<< "max" <<"\t"<< "mean"<<"\t"<<"standard_deviation" << "\n";
6358  }
6359 
6360  //loop over basis functions (if cvg option)
6361  for(; N<=dimension; N++)
6362  {
6363 
6364  int mu_number = 0;
6365  BOOST_FOREACH( auto mu, *Sampling )
6366  {
6367  boost::mpi::timer tcrb;
6368  auto o = this->run( mu, tol , N);
6369  time_crb( mu_number ) = tcrb.elapsed() ;
6370  mu_number++;
6371  }
6372 
6373  auto stat = M_model->computeStatistics( time_crb , appname );
6374 
6375  min=stat(0);
6376  max=stat(1);
6377  mean=stat(2);
6378  standard_deviation=stat(3);
6379 
6380  if( proc_number == master )
6381  conv << N << "\t" << min << "\t" << max<< "\t"<< mean<< "\t"<< standard_deviation<<"\n";
6382  }//loop over basis functions
6383  conv.close();
6384 }
6385 
6386 
6387 template<typename TruthModelType>
6388 template<class Archive>
6389 void
6390 CRB<TruthModelType>::save( Archive & ar, const unsigned int version ) const
6391 {
6392  int proc_number = this->worldComm().globalRank();
6393 
6394  LOG(INFO) <<"[CRB::save] version : "<<version<<std::endl;
6395 
6396  auto mesh = mesh_type::New();
6397  auto is_mesh_loaded = mesh->load( _name="mymesh",_path=this->dbLocalPath(),_type="binary" );
6398 
6399  if ( ! is_mesh_loaded )
6400  {
6401  auto first_element = M_WN[0];
6402  mesh = first_element.functionSpace()->mesh() ;
6403  mesh->save( _name="mymesh",_path=this->dbLocalPath(),_type="binary" );
6404  }
6405 
6406 
6407  ar & boost::serialization::base_object<super>( *this );
6408  ar & BOOST_SERIALIZATION_NVP( M_output_index );
6409  ar & BOOST_SERIALIZATION_NVP( M_N );
6410  ar & BOOST_SERIALIZATION_NVP( M_rbconv );
6411  ar & BOOST_SERIALIZATION_NVP( M_error_type );
6412  ar & BOOST_SERIALIZATION_NVP( M_Xi );
6413  ar & BOOST_SERIALIZATION_NVP( M_WNmu );
6414  ar & BOOST_SERIALIZATION_NVP( M_Aqm_pr );
6415  ar & BOOST_SERIALIZATION_NVP( M_Aqm_du );
6416  ar & BOOST_SERIALIZATION_NVP( M_Aqm_pr_du );
6417  ar & BOOST_SERIALIZATION_NVP( M_Fqm_pr );
6418  ar & BOOST_SERIALIZATION_NVP( M_Fqm_du );
6419  ar & BOOST_SERIALIZATION_NVP( M_Lqm_pr );
6420  ar & BOOST_SERIALIZATION_NVP( M_Lqm_du );
6421 
6422  ar & BOOST_SERIALIZATION_NVP( M_C0_pr );
6423  ar & BOOST_SERIALIZATION_NVP( M_C0_du );
6424  ar & BOOST_SERIALIZATION_NVP( M_Lambda_pr );
6425  ar & BOOST_SERIALIZATION_NVP( M_Lambda_du );
6426  ar & BOOST_SERIALIZATION_NVP( M_Gamma_pr );
6427  ar & BOOST_SERIALIZATION_NVP( M_Gamma_du );
6428 
6429 
6430  ar & BOOST_SERIALIZATION_NVP( M_Mqm_pr );
6431  ar & BOOST_SERIALIZATION_NVP( M_Mqm_du );
6432  ar & BOOST_SERIALIZATION_NVP( M_Mqm_pr_du );
6433 
6434  if ( model_type::is_time_dependent )
6435  {
6436 
6437  ar & BOOST_SERIALIZATION_NVP( M_coeff_pr_ini_online );
6438  ar & BOOST_SERIALIZATION_NVP( M_coeff_du_ini_online );
6439  ar & BOOST_SERIALIZATION_NVP( M_Cmf_pr );
6440  ar & BOOST_SERIALIZATION_NVP( M_Cma_pr );
6441  ar & BOOST_SERIALIZATION_NVP( M_Cmm_pr );
6442  ar & BOOST_SERIALIZATION_NVP( M_Cmf_du );
6443  ar & BOOST_SERIALIZATION_NVP( M_Cmf_du_ini );
6444  ar & BOOST_SERIALIZATION_NVP( M_Cma_du );
6445  ar & BOOST_SERIALIZATION_NVP( M_Cmm_du );
6446  }
6447  ar & BOOST_SERIALIZATION_NVP ( M_database_contains_variance_info );
6448  if( M_database_contains_variance_info )
6449  ar & BOOST_SERIALIZATION_NVP( M_variance_matrix_phi );
6450 
6451  ar & BOOST_SERIALIZATION_NVP( M_Fqm_pr );
6452  ar & BOOST_SERIALIZATION_NVP( M_InitialGuessV_pr );
6453 
6454  ar & BOOST_SERIALIZATION_NVP( M_current_mu );
6455  ar & BOOST_SERIALIZATION_NVP( M_no_residual_index );
6456 
6457 #if 0
6458  for(int i=0; i<M_N; i++)
6459  ar & BOOST_SERIALIZATION_NVP( M_WN[i] );
6460  for(int i=0; i<M_N; i++)
6461  ar & BOOST_SERIALIZATION_NVP( M_WNdu[i] );
6462 #endif
6463 
6464  ar & BOOST_SERIALIZATION_NVP( M_maxerror );
6465  ar & BOOST_SERIALIZATION_NVP( M_use_newton );
6466  ar & BOOST_SERIALIZATION_NVP( M_Jqm_pr );
6467  ar & BOOST_SERIALIZATION_NVP( M_Rqm_pr );
6468 }
6469 
6470 
6471 template<typename TruthModelType>
6472 template<class Archive>
6473 void
6474 CRB<TruthModelType>::load( Archive & ar, const unsigned int version )
6475 {
6476 
6477  //if( version <= 4 )
6478  // throw std::logic_error( "[CRB::load] ERROR while loading the existing database, since version 5 there was many changes. Please use the option --crb.rebuild-database=true " );
6479  int proc_number = this->worldComm().globalRank();
6480 
6481  LOG(INFO) <<"[CRB::load] version"<< version <<"\n";
6482 
6483 #if 0
6484  mesh_ptrtype mesh;
6485  space_ptrtype Xh;
6486 
6487  if ( !M_model )
6488  {
6489  LOG(INFO) << "[load] model not initialized, loading fdb files...\n";
6490  mesh = mesh_type::New();
6491  bool is_mesh_loaded = mesh->load( _name="mymesh",_path=this->dbLocalPath(),_type="binary" );
6492  Xh = space_type::New( mesh );
6493  LOG(INFO) << "[load] loading fdb files done.\n";
6494  }
6495  else
6496  {
6497  LOG(INFO) << "[load] get mesh/Xh from model...\n";
6498  mesh = M_model->functionSpace()->mesh();
6499  Xh = M_model->functionSpace();
6500  LOG(INFO) << "[load] get mesh/Xh from model done.\n";
6501  }
6502 #endif
6503 
6504  typedef boost::bimap< int, double > old_convergence_type;
6505  ar & boost::serialization::base_object<super>( *this );
6506  ar & BOOST_SERIALIZATION_NVP( M_output_index );
6507  ar & BOOST_SERIALIZATION_NVP( M_N );
6508 
6509  ar & BOOST_SERIALIZATION_NVP( M_rbconv );
6510 
6511  ar & BOOST_SERIALIZATION_NVP( M_error_type );
6512  ar & BOOST_SERIALIZATION_NVP( M_Xi );
6513  ar & BOOST_SERIALIZATION_NVP( M_WNmu );
6514  ar & BOOST_SERIALIZATION_NVP( M_Aqm_pr );
6515  ar & BOOST_SERIALIZATION_NVP( M_Aqm_du );
6516  ar & BOOST_SERIALIZATION_NVP( M_Aqm_pr_du );
6517  ar & BOOST_SERIALIZATION_NVP( M_Fqm_pr );
6518  ar & BOOST_SERIALIZATION_NVP( M_Fqm_du );
6519  ar & BOOST_SERIALIZATION_NVP( M_Lqm_pr );
6520  ar & BOOST_SERIALIZATION_NVP( M_Lqm_du );
6521  ar & BOOST_SERIALIZATION_NVP( M_C0_pr );
6522  ar & BOOST_SERIALIZATION_NVP( M_C0_du );
6523  ar & BOOST_SERIALIZATION_NVP( M_Lambda_pr );
6524  ar & BOOST_SERIALIZATION_NVP( M_Lambda_du );
6525  ar & BOOST_SERIALIZATION_NVP( M_Gamma_pr );
6526  ar & BOOST_SERIALIZATION_NVP( M_Gamma_du );
6527 
6528  ar & BOOST_SERIALIZATION_NVP( M_Mqm_pr );
6529  ar & BOOST_SERIALIZATION_NVP( M_Mqm_du );
6530  ar & BOOST_SERIALIZATION_NVP( M_Mqm_pr_du );
6531 
6532  if ( model_type::is_time_dependent )
6533  {
6534  ar & BOOST_SERIALIZATION_NVP( M_coeff_pr_ini_online );
6535  ar & BOOST_SERIALIZATION_NVP( M_coeff_du_ini_online );
6536  ar & BOOST_SERIALIZATION_NVP( M_Cmf_pr );
6537  ar & BOOST_SERIALIZATION_NVP( M_Cma_pr );
6538  ar & BOOST_SERIALIZATION_NVP( M_Cmm_pr );
6539  ar & BOOST_SERIALIZATION_NVP( M_Cmf_du );
6540  ar & BOOST_SERIALIZATION_NVP( M_Cmf_du_ini );
6541  ar & BOOST_SERIALIZATION_NVP( M_Cma_du );
6542  ar & BOOST_SERIALIZATION_NVP( M_Cmm_du );
6543  }
6544 
6545  ar & BOOST_SERIALIZATION_NVP ( M_database_contains_variance_info );
6546  if( M_database_contains_variance_info )
6547  ar & BOOST_SERIALIZATION_NVP( M_variance_matrix_phi );
6548  ar & BOOST_SERIALIZATION_NVP( M_Fqm_pr );
6549  ar & BOOST_SERIALIZATION_NVP( M_InitialGuessV_pr );
6550 
6551  ar & BOOST_SERIALIZATION_NVP( M_current_mu );
6552  ar & BOOST_SERIALIZATION_NVP( M_no_residual_index );
6553 
6554  ar & BOOST_SERIALIZATION_NVP( M_maxerror );
6555  ar & BOOST_SERIALIZATION_NVP( M_use_newton );
6556  ar & BOOST_SERIALIZATION_NVP( M_Jqm_pr );
6557  ar & BOOST_SERIALIZATION_NVP( M_Rqm_pr );
6558 
6559  if( this->vm()["crb.use-newton"].template as<bool>() != M_use_newton )
6560  {
6561  if( M_use_newton )
6562  throw std::logic_error( "[CRB::loadDB] ERROR in the database used the option use-newton=true and it's not the case in your option" );
6563  else
6564  throw std::logic_error( "[CRB::loadDB] ERROR in the database used the option use-newton=false and it's not the case in your option" );
6565  }
6566 
6567 #if 0
6568  std::cout << "[loadDB] output index : " << M_output_index << "\n"
6569  << "[loadDB] N : " << M_N << "\n"
6570  << "[loadDB] error type : " << M_error_type << "\n";
6571 
6572  for ( auto it = M_rbconv.begin(), en = M_rbconv.end();it != en; ++it )
6573  std::cout << "[loadDB] convergence: (" << it->left << "," << it->right << ")\n";
6574 
6575  element_type temp = Xh->element();
6576 
6577  M_WN.resize( M_N );
6578  M_WNdu.resize( M_N );
6579 
6580  for( int i = 0 ; i < M_N ; i++ )
6581  {
6582  temp.setName( (boost::format( "fem-primal-%1%" ) % ( i ) ).str() );
6583  ar & BOOST_SERIALIZATION_NVP( temp );
6584  M_WN[i] = temp;
6585  }
6586 
6587  for( int i = 0 ; i < M_N ; i++ )
6588  {
6589  temp.setName( (boost::format( "fem-dual-%1%" ) % ( i ) ).str() );
6590  ar & BOOST_SERIALIZATION_NVP( temp );
6591  M_WNdu[i] = temp;
6592  }
6593 
6594 #endif
6595  LOG(INFO) << "[CRB::load] end of load function" << std::endl;
6596 }
6597 
6598 
6599 template<typename TruthModelType>
6600 bool
6602 {
6603  bool print = this->vm()["crb.print-error-during-rb-construction"].template as<bool>();
6604  return print;
6605 }
6606 
6607 template<typename TruthModelType>
6608 bool
6610 {
6611  bool rebuild = this->vm()["crb.rebuild-database"].template as<bool>();
6612  return rebuild;
6613 }
6614 
6615 template<typename TruthModelType>
6616 bool
6618 {
6619  bool show = this->vm()["crb.show-mu-selection"].template as<bool>();
6620  return show;
6621 }
6622 
6623 
6624 template<typename TruthModelType>
6625 void
6627 {
6628  fs::ofstream ofs( this->dbLocalPath() / this->dbFilename() );
6629 
6630  if ( ofs )
6631  {
6632  boost::archive::text_oarchive oa( ofs );
6633  // write class instance to archive
6634  oa << *this;
6635  // archive and stream closed when destructors are called
6636  }
6637 }
6638 
6639 template<typename TruthModelType>
6640 bool
6642 {
6643  if ( this->rebuildDB() )
6644  return false;
6645 
6646  if( this->isDBLoaded() )
6647  return true;
6648 
6649  fs::path db = this->lookForDB();
6650 
6651  if ( db.empty() )
6652  return false;
6653 
6654  if ( !fs::exists( db ) )
6655  return false;
6656 
6657  //std::cout << "Loading " << db << "...\n";
6658  fs::ifstream ifs( db );
6659 
6660  if ( ifs )
6661  {
6662  boost::archive::text_iarchive ia( ifs );
6663  // write class instance to archive
6664  ia >> *this;
6665  //std::cout << "Loading " << db << " done...\n";
6666  this->setIsLoaded( true );
6667  // archive and stream closed when destructors are called
6668  return true;
6669  }
6670 
6671  return false;
6672 }
6673 
6674 } // Feel
6675 
6676 namespace boost
6677 {
6678 namespace serialization
6679 {
6680 template< typename T>
6681 struct version< Feel::CRB<T> >
6682 {
6683  // at the moment the version of the CRB DB is 0. if any changes is done
6684  // to the format it is mandatory to increase the version number below
6685  // and use the new version number of identify the new entries in the DB
6686  typedef mpl::int_<0> type;
6687  typedef mpl::integral_c_tag tag;
6688  static const unsigned int value = version::type::value;
6689 };
6690 template<typename T> const unsigned int version<Feel::CRB<T> >::value;
6691 }
6692 }
6693 #endif /* __CRB_H */

Generated on Sun Oct 20 2013 08:24:55 for Feel++ by doxygen 1.8.4