//                                               -*- C++ -*-
/**
 *  @file  FunctionalChaosResult.cxx
 *  @brief The result of a chaos expansion
 *
 *  (C) Copyright 2005-2012 EDF-EADS-Phimeca
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 *  @author dutka
 *  @date   2008-05-21 11:21:38 +0200 (Wed, 21 May 2008)
 */
#include "FunctionalChaosResult.hxx"
#include "Os.hxx"
#include "OSS.hxx"
#include "NumericalSample.hxx"
#include "PersistentObjectFactory.hxx"

BEGIN_NAMESPACE_OPENTURNS

static Factory<PersistentCollection<UnsignedLong> > RegisteredFactory2("PersistentCollection<UnsignedLong>");



CLASSNAMEINIT(FunctionalChaosResult);
static Factory<FunctionalChaosResult> RegisteredFactory("FunctionalChaosResult");


/* Default constructor */
FunctionalChaosResult::FunctionalChaosResult()
  : MetaModelResult(),
    distribution_(),
    transformation_(),
    inverseTransformation_(),
    composedModel_(),
    orthogonalBasis_(),
    I_(0),
    alpha_k_(0, 0),
    Psi_k_(0)
{
  // Nothing to do
}


/* Default constructor */
FunctionalChaosResult::FunctionalChaosResult(const NumericalMathFunction & model,
    const Distribution & distribution,
    const NumericalMathFunction & transformation,
    const NumericalMathFunction & inverseTransformation,
    const NumericalMathFunction & composedModel,
    const OrthogonalBasis & orthogonalBasis,
    const Indices & I,
    const NumericalSample & alpha_k,
    const NumericalMathFunctionCollection & Psi_k,
    const NumericalPoint & residuals,
    const NumericalPoint & relativeErrors)
  : MetaModelResult(model, NumericalMathFunction(), residuals, relativeErrors),
    distribution_(distribution),
    transformation_(transformation),
    inverseTransformation_(inverseTransformation),
    composedModel_(composedModel),
    orthogonalBasis_(orthogonalBasis),
    I_(I),
    alpha_k_(alpha_k),
    Psi_k_(Psi_k),
    composedMetaModel_()
{
  // The composed meta model will be a dual linear combination
  composedMetaModel_ = NumericalMathFunction(Psi_k, alpha_k);
  metaModel_ = NumericalMathFunction(composedMetaModel_, transformation);
}


/* Virtual constructor */
FunctionalChaosResult * FunctionalChaosResult::clone() const
{
  return new FunctionalChaosResult(*this);
}


/* String converter */
String FunctionalChaosResult::__repr__() const
{
  return OSS() << "class=" << getClassName()
         << " derived from " << MetaModelResult::__repr__()
         << " distribution=" << distribution_
         << " transformation=" << transformation_
         << " inverseTransformation=" << inverseTransformation_
         << " composedModel=" << composedModel_
         << " orthogonalBasis=" << orthogonalBasis_
         << " indices=" << I_
         << " coefficients=" << alpha_k_
         << " reduced basis=" << Psi_k_
         << " residuals=" << residuals_
         << " relativeErrors=" << relativeErrors_
         << " composedMetaModel=" << composedMetaModel_
         << " metaModel=" << metaModel_;
}

String FunctionalChaosResult::__str__(const String & offset) const
{
  OSS oss(false);
  oss << offset << "meta model=" << metaModel_ << Os::GetEndOfLine();
  oss << offset << "orthogonal basis=" << orthogonalBasis_;
  return oss;
}

/* Distribution accessor */
Distribution FunctionalChaosResult::getDistribution() const
{
  return distribution_;
}

/* IsoProbabilisticTransformation accessor */
NumericalMathFunction FunctionalChaosResult::getTransformation() const
{
  return transformation_;
}

/* InverseIsoProbabilisticTransformation accessor */
NumericalMathFunction FunctionalChaosResult::getInverseTransformation() const
{
  return inverseTransformation_;
}

/* Composed model accessor */
NumericalMathFunction FunctionalChaosResult::getComposedModel() const
{
  return composedModel_;
}

/* Orthogonal basis accessor */
OrthogonalBasis FunctionalChaosResult::getOrthogonalBasis() const
{
  return orthogonalBasis_;
}

/* Indices accessor */
Indices FunctionalChaosResult::getIndices() const
{
  return I_;
}

/* Coefficients accessor */
NumericalSample FunctionalChaosResult::getCoefficients() const
{
  return alpha_k_;
}

/* Reduced basis accessor */
FunctionalChaosResult::NumericalMathFunctionCollection FunctionalChaosResult::getReducedBasis() const
{
  return Psi_k_;
}

/* Composed meta model accessor */
NumericalMathFunction FunctionalChaosResult::getComposedMetaModel() const
{
  return composedMetaModel_;
}

/* Method save() stores the object through the StorageManager */
void FunctionalChaosResult::save(Advocate & adv) const
{
  MetaModelResult::save(adv);
  adv.saveAttribute( "distribution_", distribution_ );
  adv.saveAttribute( "transformation_", transformation_ );
  adv.saveAttribute( "inverseTransformation_", inverseTransformation_ );
  adv.saveAttribute( "composedModel_", composedModel_ );
  adv.saveAttribute( "orthogonalBasis_", orthogonalBasis_ );
  adv.saveAttribute( "I_", I_ );
  adv.saveAttribute( "alpha_k_", alpha_k_ );
  adv.saveAttribute( "Psi_k_", Psi_k_ );
  adv.saveAttribute( "composedMetaModel_", composedMetaModel_ );
}


/* Method load() reloads the object from the StorageManager */
void FunctionalChaosResult::load(Advocate & adv)
{
  MetaModelResult::load(adv);
  adv.loadAttribute( "distribution_", distribution_ );
  adv.loadAttribute( "transformation_", transformation_ );
  adv.loadAttribute( "inverseTransformation_", inverseTransformation_ );
  adv.loadAttribute( "composedModel_", composedModel_ );
  adv.loadAttribute( "orthogonalBasis_", orthogonalBasis_ );
  adv.loadAttribute( "I_", I_ );
  adv.loadAttribute( "alpha_k_", alpha_k_ );
  adv.loadAttribute( "Psi_k_", Psi_k_ );
  adv.loadAttribute( "composedMetaModel_", composedMetaModel_ );
}



END_NAMESPACE_OPENTURNS
