//
// molfreq.h
//
// Copyright (C) 1996 Limit Point Systems, Inc.
//
// Author: Curtis Janssen <cljanss@limitpt.com>
// Maintainer: LPS
//
// This file is part of the SC Toolkit.
//
// The SC Toolkit is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// The SC Toolkit 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 Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
//
// The U.S. Government is granted a limited license as per AL 91-7.
//

#ifndef _chemistry_molecule_molfreq_h
#define _chemistry_molecule_molfreq_h

#include <iostream>
#include <math/scmat/matrix.h>
#include <util/render/animate.h>
#include <chemistry/molecule/energy.h>
#include <chemistry/molecule/molrender.h>
#include <chemistry/molecule/coor.h>

namespace sc {

class MolFreqAnimate;

/// @addtogroup ChemistryMolecule
/// @{

/** The MolecularFrequencies class is used to compute the molecular
frequencies and thermodynamic information. */
class MolecularFrequencies: public SavableState {
  private:
    Ref<Molecule> mol_;
    Ref<PointGroup> pg_;
    int debug_;
    int nirrep_;
    // the number of frequencies per irrep
    int *nfreq_;
    // the frequencies for each irrep
    double **freq_;

    Ref<SCMatrixKit> kit_;
    Ref<SCMatrixKit> symkit_;

    // the symmetry blocked dimension for internal motions
    RefSCDimension disym_;
    // the cartesian dimension
    RefSCDimension d3natom_;
    // the blocked cartesian dimension
    RefSCDimension bd3natom_;
    // the normal coordinates
    RefSCMatrix normco_;

    void do_freq_for_irrep(int irrep,
                           const RefDiagSCMatrix &m,
                           const RefSymmSCMatrix &dhessian,
                           const RefSCMatrix &dtranst);
  public:
    /** The KeyVal constructor.

        <dl>

        <dt><tt>molecule</tt><dd> A Molecule object. There is no default.

        <dt><tt>point_group</tt><dd> A PointGroup object.  This is the
        point group used to compute the finite displacements.  Since some
        MolecularEnergy objects cannot handle changes in the molecule's
        point group, the molecule must be given \f$C_1\f$ symmetry for
        frequency calculations.  In this case, the point_group keyword can
        be given to reduce number of the displacements needed to compute
        the frequencies.  If this is not given then the point group of the
        molecule is used.

        <dt><tt>debug</tt><dd> An integer which, if nonzero, will cause
        extra output.

        </dl> */
    MolecularFrequencies(const Ref<KeyVal> &);
    MolecularFrequencies(const Ref<Molecule>&);
    MolecularFrequencies(StateIn &);
    ~MolecularFrequencies();
    void save_data_state(StateOut&);

    /// Return the molecule.
    Ref<Molecule> molecule() const { return mol_; }

    /// Given a cartesian coordinate hessian, compute the frequencies.
    void compute_frequencies(const RefSymmSCMatrix &xhessian);

    /// Returns the number if irreps.
    int nirrep() const { return nirrep_; }

    /** Returns the number of modes in an irrep.  compute_frequencies
        must be called first. */
    int nfreq(int irrep) const { return nfreq_[irrep]; }

    /** Returns the frequency, given the irrep and the index.
        compute_frequencies must be called first. */
    double freq(int irrep, int i) const { return freq_[irrep][i]; }

    /** This returns the normal coordinates generated by
        compute_frequencies. */
    RefSCMatrix normal_coordinates() { return normco_; }

    /** Computes thermochemical information using information generated
        by calling compute_frequencies first. */
    void thermochemistry(int degeneracy, double temp=298.15, double pres=1.0);

    void animate(const Ref<Render>&, const Ref<MolFreqAnimate>&);

    Ref<SCMatrixKit> matrixkit() { return kit_; }
    Ref<SCMatrixKit> symmatrixkit() { return symkit_; }
};



class MolFreqAnimate: public AnimatedObject {
  private:
    Ref<RenderedMolecule> renmol_;
    Ref<MolecularFrequencies> molfreq_;
    Ref<MolecularEnergy> dependent_mole_;
    int irrep_;
    int mode_;
    int nframe_;
    double disp_;
  public:
    MolFreqAnimate(const Ref<KeyVal> &);
    virtual ~MolFreqAnimate();

    void set_mode(int i, int j) { irrep_ = i; mode_ = j; }
    int nobject();
    Ref<RenderedObject> object(int iobject);
};

/// @}
// end of addtogroup ChemistryMolecule

}

#endif

// Local Variables:
// mode: c++
// c-file-style: "CLJ"
// End:
