/****************************************************************************
*
*                                 M U E S L I   v 1.8
*
*
*     Copyright 2020 IMDEA Materials Institute, Getafe, Madrid, Spain
*     Contact: muesli.materials@imdea.org
*     Author: Ignacio Romero (ignacio.romero@imdea.org)
*
*     This file is part of MUESLI.
*
*     MUESLI is free software: you can redistribute it and/or modify
*     it under the terms of the GNU General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     MUESLI 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 General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with MUESLI.  If not, see <http://www.gnu.org/licenses/>.
*
****************************************************************************/



#include <iostream>
#include <ctime>
#include <cstdlib>
#include <unistd.h>

#include "muesli/muesli.h"

int main(int argc, char **argv)
{
    std::ofstream os("testmuesli.log");
    
    // header
    os << "            M U E S L I    T E S T S\n\n";
    time_t walltime = time(NULL);
    os << " Test done on : " << ctime(&walltime);
    os << " Username     : " << getlogin();
    
    char host[256];
    if (gethostname( host, 256) == 0)
    {
        os << "\n Hostname     : " << host;
    }
    else
    {
        os << "\n Hostname     : unknown";
    }
    
    static char noOS[] = "UNKNOWN OS";
    char *op = getenv("OSTYPE");
    if (op == NULL) op = getenv("OS");
    if (op == NULL) op = noOS;
    os << "\n OS           : " << op;

    bool isok = true;

    std::string st_redMethod = "nr";
    //std::string st_redMethod = "";
    {
        // testing small strian beams (elastic and plastic)
        muesli::materialProperties mp;
        std::string name = "smalstrain reduced material";
        //muesli::splasticMaterial* m = new muesli::splasticMaterial(name, mp);
        muesli::elasticIsotropicMaterial* m = new muesli::elasticIsotropicMaterial(name, mp);

        m->setRandom();

        muesli::smallStrainMP* p = m->createMaterialPoint();
        muesli::sbeamMP* sp = new muesli::sbeamMP(p, st_redMethod);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain reduced beam plastic material";
        os << "\n----------------------------------------------------";
        bool mok = sp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "smallstrain reduced material";
        //muesli::splasticMaterial* m = new muesli::splasticMaterial(name, mp);
        muesli::elasticIsotropicMaterial* m = new muesli::elasticIsotropicMaterial(name, mp);

        m->setRandom();

        muesli::smallStrainMP* p = m->createMaterialPoint();
        muesli::sshellMP* sp = new muesli::sshellMP(p, st_redMethod);

        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain reduced shell plastic material";
        os << "\n----------------------------------------------------";
        bool mok = sp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "smallstrain reduced material";
        //muesli::splasticMaterial* m = new muesli::splasticMaterial(name, mp);
        muesli::elasticIsotropicMaterial* m = new muesli::elasticIsotropicMaterial(name, mp);

        m->setRandom();

        muesli::smallStrainMP* p = m->createMaterialPoint();
        muesli::splaneMP* sp = new muesli::splaneMP(p, st_redMethod);

        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain reduced plane plastic material";
        os << "\n----------------------------------------------------";
        bool mok = sp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }

    {
        // testing small strian beams (elastic and plastic)
        muesli::materialProperties mp;
        std::string name = "smalstrain reduced material";
        muesli::splasticMaterial* m = new muesli::splasticMaterial(name, mp);
        //muesli::elasticIsotropicMaterial* m = new muesli::elasticIsotropicMaterial(name, mp);

        m->setRandom();
        
        muesli::smallStrainMP* p = m->createMaterialPoint();
        muesli::sbarMP* sp = new muesli::sbarMP(p, st_redMethod);

        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain reduced bar plastic material";
        os << "\n----------------------------------------------------";
        bool mok = sp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "finitestrain elastic material";
        muesli::neohookeanMaterial* m = new muesli::neohookeanMaterial(name, mp);
        //muesli::fplasticMaterial* m = new muesli::fplasticMaterial(name, mp);

        m->setRandom();

        muesli::finiteStrainMP* p = m->createMaterialPoint();
        muesli::fbeamMP* fp = new muesli::fbeamMP(p, st_redMethod);

        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finitestrain reduced beam plastic material";
        os << "\n----------------------------------------------------";
        bool mok = fp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "finitestrain elastic material";
        muesli::neohookeanMaterial* m = new muesli::neohookeanMaterial(name, mp);
        //muesli::fplasticMaterial* m = new muesli::fplasticMaterial(name, mp);

        m->setRandom();

        muesli::finiteStrainMP* p = m->createMaterialPoint();
        muesli::fshellMP* fp = new muesli::fshellMP(p, st_redMethod);

        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finitestrain reduced shell plastic material";
        os << "\n----------------------------------------------------";
        bool mok = fp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }
    
    {
        muesli::materialProperties mp;
        std::string name = "finitestrain elastic material";
        //muesli::neohookeanMaterial* m = new muesli::neohookeanMaterial(name, mp);
        muesli::fplasticMaterial* m = new muesli::fplasticMaterial(name, mp);

        m->setRandom();

        muesli::finiteStrainMP* p = m->createMaterialPoint();
        muesli::fbarMP* fp = new muesli::fbarMP(p, st_redMethod);

        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finitestrain reduced bar plastic material";
        os << "\n----------------------------------------------------";
        bool mok = fp->testImplementation(os);
        isok = isok && mok;
        delete m;
    }
    /*

     {
     muesli::materialProperties mp;
     std::string name = "finitestrain elastic material";
     //muesli::neohookeanMaterial* m = new muesli::neohookeanMaterial(name, mp);
     muesli::fplasticMaterial* m = new muesli::fplasticMaterial(name, mp);

     m->setRandom();

     muesli::finiteStrainMP* p = m->createMaterialPoint();
     muesli::fplaneMP* fp = new muesli::fplaneMP(p, st_redMethod);

     os << "\n";
     os << "\n----------------------------------------------------";
     os << "\n Testing finitestrain reduced plane plastic material";
     os << "\n----------------------------------------------------";
     bool mok = fp->testImplementation(os);
     isok = isok && mok;
     delete m;
     }

     */
    {
        muesli::materialProperties mp;
        std::string name = "elastic material";
        muesli::elasticIsotropicMaterial* m = new muesli::elasticIsotropicMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain isotropic elastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "anisotropic material";
        muesli::elasticAnisotropicMaterial* m = new muesli::elasticAnisotropicMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain anisotropic elastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "orthotropic material";
        muesli::elasticOrthotropicMaterial* m = new muesli::elasticOrthotropicMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain orthotropic elastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "visco elastic material";
        muesli::viscoelasticMaterial* m = new muesli::viscoelasticMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain visco elastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "a plastic material";
        muesli::splasticMaterial* m = new muesli::splasticMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain elasto plastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a viscoplastic material";
        muesli::materialProperties mp;
        muesli::viscoplasticMaterial* m = new muesli::viscoplasticMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain elasto visco plastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        muesli::materialProperties mp;
        std::string name = "damage material";
        muesli::sdamageMaterial* m = new muesli::sdamageMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing smallstrain damage material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a small strain thermomechanical material";
        muesli::materialProperties mp;
        muesli::sThermoMechMaterial* m = new muesli::sThermoMechMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing small strain thermomechanical material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a SV-K material";
        muesli::materialProperties mp;
        muesli::svkMaterial* m = new muesli::svkMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Saint Venant - Kirchhoff material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a neohookean material";
        muesli::materialProperties mp;
        muesli::neohookeanMaterial* m = new muesli::neohookeanMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Neohookean material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a mooney rivlin material";
        muesli::materialProperties mp;
        muesli::mooneyMaterial* m = new muesli::mooneyMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Mooney - Rivlin material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "an arruda boyce material";
        muesli::materialProperties mp;
        muesli::arrudaboyceMaterial* m = new muesli::arrudaboyceMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Arruda - Boyce material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a Yeoh material";
        muesli::materialProperties mp;
        muesli::yeohMaterial* m = new muesli::yeohMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Yeoh material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a fs elastoplastic material";
        muesli::materialProperties mp;
        muesli::fplasticMaterial* m = new muesli::fplasticMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finite strain elastoplastic material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }


    {
        std::string name = "a fourier material";
        muesli::fourierMaterial* m = new muesli::fourierMaterial(name);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing conductor material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "an anisotropic material";
        muesli::anisotropicConductorMaterial* m = new muesli::anisotropicConductorMaterial(name);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing anisotropic conductor material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a nonlinear conductor material";
        muesli::nonlinearConductorMaterial* m = new muesli::nonlinearConductorMaterial(name);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing nonlinear conductor material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a newtonian fluid material";
        muesli::newtonianMaterial* m = new muesli::newtonianMaterial(name);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing newtonian material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a finite strain thermomechanical material";
        muesli::materialProperties mp;
        muesli::thermofiniteStrainMaterial* m = new muesli::thermofiniteStrainMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finite strain, thermomechanical material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a thermomechanical Johnson-Cook model material";
        muesli::materialProperties mp;
        muesli::thermoJCMaterial* m = new muesli::thermoJCMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Johnson-Cook, thermomechanical material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a thermomechanical Zerilli-Armstrong model material";
        muesli::materialProperties mp;
        muesli::thermoZAMaterial* m = new muesli::thermoZAMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Zerilli-Armstrong, thermomechanical material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a finite strain coupled stress/diffusion material";
        muesli::materialProperties mp;
        muesli::fMechMassMaterial* m = new muesli::fMechMassMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finite strain, stress/diffusion material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a Johnson-Cook finite strain material";
        muesli::materialProperties mp;
        muesli::johnsonCookMaterial* m = new muesli::johnsonCookMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Johnson-Cook finite strain material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a Zerilli-Armstrong finite strain material";
        muesli::materialProperties mp;
        muesli::zerilliArmstrongMaterial* m = new muesli::zerilliArmstrongMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Zerilli-Armstrong finite strain material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "an Arrhenius-type finite strain material";
        muesli::materialProperties mp;
        muesli::arrheniusTypeMaterial* m = new muesli::arrheniusTypeMaterial(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing Arrhenius-type finite strain material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    {
        std::string name = "a finite strain, thermo-chemo-mechanical material (Anand 2011 IJSS)";
        muesli::materialProperties mp;
        muesli::AnandIJSS2011Material* m = new muesli::AnandIJSS2011Material(name, mp);
        os << "\n";
        os << "\n----------------------------------------------------";
        os << "\n Testing finite strain, thermo-chemo-mech material";
        os << "\n----------------------------------------------------";
        bool mok = m->test(os);
        isok = isok && mok;
        delete m;
    }

    return 0;
}


