//#####################################################################
// Copyright 2012.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#include <Core/Viewer/VIEWER_OUTPUT.h>
#include <Core/Arrays/FACE_ARRAYS.h>
#include <Core/Geometry_Particles/DEBUG_PARTICLES.h>
#include <Core/Geometry_Particles/GEOMETRY_PARTICLES.h>
#include <Core/Grids/FACE_INDEX.h>
#include <Core/Grids/GRID.h>
#include <Core/Log/LOG.h>
#include <Core/Meshes/MESH_OBJECT.h>
#include <Core/Read_Write/FILE_UTILITIES.h>
#include <fstream>
namespace PhysBAM{
//#####################################################################
// Constructor
//#####################################################################
VIEWER_OUTPUT::
VIEWER_OUTPUT(STREAM_TYPE stream_type,VIEWER_DIR& viewer_dir)
    :viewer_dir(viewer_dir),stream_type(stream_type)
{
    Singleton(this);
}
//#####################################################################
// Destructor
//#####################################################################
VIEWER_OUTPUT::
~VIEWER_OUTPUT()
{
    Singleton(0);
}
//#####################################################################
// Function Singleton
//#####################################################################
VIEWER_OUTPUT* VIEWER_OUTPUT::
Singleton(VIEWER_OUTPUT* viewer_output_)
{
    static VIEWER_OUTPUT* viewer_output=0;
    VIEWER_OUTPUT* tmp=viewer_output;
    if(viewer_output_) viewer_output=viewer_output_;
    return tmp;
}
//#####################################################################
// Function Flush_Frame
//#####################################################################
void VIEWER_OUTPUT::
Flush_Frame(const std::string& title,int substep_level)
{
    viewer_dir.Start_Directory(substep_level,title);
    Dump_Stored();
    viewer_dir.Finish_Directory();
}
//#####################################################################
// Function Dump_Stored
//#####################################################################
void VIEWER_OUTPUT::
Dump_Stored()
{
    if(viewer_dir.First_Frame())
        for(const auto& f:entries[1]) f();
    for(const auto& f:entries[0]) f();
}

//#####################################################################
// Function Add_Helper
//#####################################################################
template<class T,int m,int d,class OPT> void
Add_Helper(VIEWER_OUTPUT& viewer_output,const OPT& opt,
    const std::string& s1="",const std::string& s2="")
{
    if(!viewer_output.started_manifest)
    {
        viewer_output.started_manifest=true;
        viewer_output.viewer_dir.Make_Common_Directory();
        std::ofstream fout(viewer_output.viewer_dir.Common_File("manifest.txt"));
    }

    std::ofstream fout(viewer_output.viewer_dir.Common_File("manifest.txt"),std::ios::app);
    fout<<opt.st_type_prefix;
    if(m>0) fout<<"."<<m;
    if(d>0) fout<<"."<<d;
    if constexpr(is_same<T,bool>::value) fout<<".b";
    if constexpr(is_same<T,int>::value) fout<<".i";
    if constexpr(is_same<T,float>::value) fout<<".f";
    if constexpr(is_same<T,double>::value) fout<<".d";
    if(m>0 && s2.size()>0) fout<<".sp";
    std::string s0=s1;
    if(opt.name.Valid()) s0=opt.name;
    fout<<" "<<std::quoted(s0);
    if(s1.size()) fout<<" "<<std::quoted(s1);
    if(s2.size()) fout<<" "<<std::quoted(s2);
    fout<<"\n";
    if(opt.name.Valid())
    {
        auto opt2(opt);
        opt2.name.Invalidate();
        opt2.Write(fout,s0);
    }
    else opt.Write(fout,s0);
}
//#####################################################################
// Function Add_Global
//#####################################################################
void VIEWER_OUTPUT::
Add_Global(const GLOBAL_OPTIONS& opt)
{
    if(!started_manifest)
    {
        started_manifest=true;
        viewer_dir.Make_Common_Directory();
        std::ofstream fout(viewer_dir.Common_File("manifest.txt"));
    }

    std::ofstream fout(viewer_dir.Common_File("manifest.txt"),std::ios::app);
    opt.Write(fout,"global");
}
//#####################################################################
// Function Add_Vector_Field
//#####################################################################
template<class TV> void VIEWER_OUTPUT::
Add_Vector_Field(const std::string& file,const std::string& grid_name,
    const VECTOR_FIELD_OPTIONS& opt)
{
    Add_Helper<typename TV::SCALAR,0,TV::m>(*this,opt,file,grid_name);
}
//#####################################################################
// Function Add_Grid
//#####################################################################
template<class TV> void VIEWER_OUTPUT::
Add_Grid(const std::string& file,const GRID_OPTIONS& opt)
{
    Add_Helper<typename TV::SCALAR,0,TV::m>(*this,opt,file);
}
//#####################################################################
// Function Add_Axes
//#####################################################################
template<int d> void VIEWER_OUTPUT::
Add_Axes(const std::string& name,const AXES_OPTIONS& opt)
{
    auto opt2(opt);
    opt2.name=name;
    Add_Helper<void,0,d>(*this,opt2);
}
//#####################################################################
// Function Add_Debug_Particles
//#####################################################################
template<class TV> void VIEWER_OUTPUT::
Add_Debug_Particles(const std::string& file,
    const DEBUG_PARTICLES_OPTIONS& opt)
{
    Add_Helper<typename TV::SCALAR,0,TV::m>(*this,opt,file);
}
//#####################################################################
// Function Add_Face_Field
//#####################################################################
template<class TV,class T2> void VIEWER_OUTPUT::
Add_Face_Field(const std::string& file,const std::string& grid_name,
    const FACE_FIELD_OPTIONS<F<T2>>& opt)
{
    Add_Helper<T2,0,TV::m>(*this,opt,file,grid_name);
}
//#####################################################################
// Function Add_Scalar_Field
//#####################################################################
template<class TV,class T2> void VIEWER_OUTPUT::
Add_Scalar_Field(const std::string& file,const std::string& grid_name,
    const SCALAR_FIELD_OPTIONS<F<T2>>& opt)
{
    Add_Helper<T2,0,TV::m>(*this,opt,file,grid_name);
}
//#####################################################################
// Function Add_Group
//#####################################################################
void VIEWER_OUTPUT::
Add_Group(const std::string& name,const GROUP_OPTIONS& opt)
{
    auto opt2(opt);
    opt2.name=name;
    Add_Helper<void,0,0>(*this,opt2);
}
//#####################################################################
// Function Add_Particles
//#####################################################################
template<class TV> void VIEWER_OUTPUT::
Add_Particles(const std::string& file,
    const PARTICLES_OPTIONS& opt)
{
    Add_Helper<typename TV::SCALAR,0,TV::m>(*this,opt,file);
}
//#####################################################################
// Function Add_Mesh
//#####################################################################
template<class TV,int d> void VIEWER_OUTPUT::
Add_Mesh(const std::string& file,const MESH_OPTIONS<d+0>& opt)
{
    Add_Helper<typename TV::SCALAR,d,TV::m>(*this,opt,file);
}
//#####################################################################
// Function Add
//#####################################################################
template<class T,int d> void VIEWER_OUTPUT::
Add(const std::string& file,const std::string& grid_name,
    const ARRAY_VIEW<VECTOR<T,d>,VECTOR<int,d>>& obj,
    bool is_common,const VECTOR_FIELD_OPTIONS& opt)
{
    Write(file,obj,is_common);
    Add_Vector_Field<VECTOR<T,d>>(file,grid_name,opt);
}
//#####################################################################
// Function Add
//#####################################################################
template<class T,int d> void VIEWER_OUTPUT::
Add(const std::string& file,const std::string& grid_name,
    const ARRAY<VECTOR<T,d>,VECTOR<int,d>>& obj,
    bool is_common,const VECTOR_FIELD_OPTIONS& opt)
{
    Write(file,obj,is_common);
    Add_Vector_Field<VECTOR<T,d>>(file,grid_name,opt);
}
//#####################################################################
// Function Add_Grid
//#####################################################################
template<class TV> void VIEWER_OUTPUT::Add(const std::string& file,const GRID<TV>& obj,
    bool is_common,const GRID_OPTIONS& opt)
{
    Write(file,obj,is_common);
    Add_Grid<TV>(file,opt);
}
//#####################################################################
// Function Add
//#####################################################################
template<class TV> void VIEWER_OUTPUT::
Add(const std::string& file,DEBUG_PARTICLES<TV>& obj,
    bool is_common,const DEBUG_PARTICLES_OPTIONS& opt)
{
    entries[is_common].Append([this,file,&obj]()
    {
        Write_To_File(stream_type,viewer_dir.Frame_File(file),obj);
        obj.Clear_Debug_Particles();
    });
    Add_Debug_Particles<TV>(file,opt);
}
//#####################################################################
// Function Add
//#####################################################################
template<class T2,int d> void VIEWER_OUTPUT::
Add(const std::string& file,const std::string& grid_name,const ARRAY<T2,FACE_INDEX<d> >& obj,
    bool is_common,const FACE_FIELD_OPTIONS<F<T2>>& opt)
{
    Write(file,obj,is_common);
    Add_Face_Field<VECTOR<T2,d>,T2>(file,grid_name,opt);
}
//#####################################################################
// Function Add_Scalar
//#####################################################################
template<class T2,int d> void VIEWER_OUTPUT::
Add_Scalar(const std::string& file,const std::string& grid_name,const ARRAY<T2,FACE_INDEX<d> >& obj,
    bool is_common,const FACE_FIELD_OPTIONS<F<T2>>& opt)
{
    if((opt.draw_points.Valid() && opt.draw_points.Value()) || (opt.draw_diamonds.Valid() && opt.draw_diamonds.Value()))
        return Add(file,grid_name,obj,is_common,opt);
    auto opt2=opt;
    opt2.draw_points=true;
    if constexpr(!is_same<T2,bool>::value && !is_same<T2,int>::value)
        opt2.use_fixed_color=false;
    Add(file,grid_name,obj,is_common,opt2);
}
//#####################################################################
// Function Add
//#####################################################################
template<class T,int d> auto VIEWER_OUTPUT::
Add(const std::string& file,const std::string& grid_name,const ARRAY<T,VECTOR<int,d>>& obj,
    bool is_common,const SCALAR_FIELD_OPTIONS<F<T>>& opt) -> SV<T>
{
    Write(file,obj,is_common);
    Add_Scalar_Field<VECTOR<T,d>,T>(file,grid_name,opt);
}
//#####################################################################
// Function Add
//#####################################################################
template<class T,int d> auto VIEWER_OUTPUT::
Add(const std::string& file,const std::string& grid_name,const ARRAY_VIEW<T,VECTOR<int,d>>& obj,
    bool is_common,const SCALAR_FIELD_OPTIONS<F<T>>& opt) -> SV<T>
{
    Write(file,obj,is_common);
    Add_Scalar_Field<VECTOR<T,d>,T>(file,grid_name,opt);
}
//#####################################################################
// Function Add
//#####################################################################
template<class TV> void VIEWER_OUTPUT::
Add(const std::string& file,const PARTICLES<TV>& obj,
    bool is_common,const PARTICLES_OPTIONS& opt)
{
    Write(file,obj,is_common);
    Add_Particles<TV>(file,opt);
}
//#####################################################################
// Function Add
//#####################################################################
template<class TV,int d> void VIEWER_OUTPUT::
Add(const std::string& file,const MESH_OBJECT<TV,d>& obj,
    bool is_common,const MESH_OPTIONS<d+0>& opt)
{
    Write(file,obj,is_common);
    Add_Mesh<TV,d>(file,opt);
}
//#####################################################################
// Function Add_Split_Mesh
//#####################################################################
template<class TV,int d> void VIEWER_OUTPUT::
Add_Split_Mesh(const std::string& name,const std::string& mesh_file,
    const std::string& particle_file,const MESH_OPTIONS<d+0>& opt)
{
    auto opt2(opt);
    opt2.name=name;
    Add_Helper<typename TV::SCALAR,d,TV::m>(*this,opt2,mesh_file,particle_file);
}
//#####################################################################
// Function Add_Levelset
//#####################################################################
template<class T,int d> void VIEWER_OUTPUT::
Add_Levelset(const std::string& file,const std::string& grid_name,
    const ARRAY<T,VECTOR<int,d>>& obj,bool is_common,
    const SCALAR_FIELD_OPTIONS<F<T>>& opt,const VECTOR<T,3>& color)
{
    auto o=opt;
    o.color_map.Set({});
    o.color_map.Value().colors.Add_Control_Point(0,VECTOR<float,3>(color));
    o.min=-1;
    o.max=1;
    o.draw_cell_colors=false;
    o.draw_contours=true;
    Add(file,grid_name,obj,is_common,o);
}
//#####################################################################
// Function Add_Div
//#####################################################################
template<class T,int d> void VIEWER_OUTPUT::
Add_Div(const std::string& name,const std::string& data_name,const SCALAR_FIELD_OPTIONS<float>& opt)
{
    std::ofstream fout(viewer_dir.Common_File("manifest.txt"),std::ios::app);
    fout<<"div";
    if(d>0) fout<<"."<<d;
    if constexpr(is_same<T,float>::value) fout<<".f";
    if constexpr(is_same<T,double>::value) fout<<".d";
    fout<<" "<<std::quoted(name);
    fout<<" "<<std::quoted(data_name)<<"\n";

    auto opt2(opt);
    opt2.name.Invalidate();
    opt2.cell_centered=true;
    opt2.Write(fout,name);
}
//#####################################################################
// Function Add
//#####################################################################
void VIEWER_OUTPUT::
Add(std::function<void()> f,bool is_common)
{
    entries[is_common].Append(f);
}
//#####################################################################
// Function Write_Substep
//#####################################################################
void VIEWER_OUTPUT::
Write_Substep(const std::string& title,int level)
{
    Flush_Frame(title,level);
    LOG::printf("Writing substep %P: %P\n",viewer_dir.Frame_As_String(),title);
}
template void VIEWER_OUTPUT::Add<VECTOR<float,2> >(std::string const&,DEBUG_PARTICLES<VECTOR<float,2> >&,bool,DEBUG_PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,2> >(std::string const&,GRID<VECTOR<float,2> > const&,bool,GRID_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,3> >(std::string const&,DEBUG_PARTICLES<VECTOR<float,3> >&,bool,DEBUG_PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,3> >(std::string const&,GRID<VECTOR<float,3> > const&,bool,GRID_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,2> >(std::string const&,DEBUG_PARTICLES<VECTOR<double,2> >&,bool,DEBUG_PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,2> >(std::string const&,PARTICLES<VECTOR<double,2> > const&,bool,PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,3> >(std::string const&,DEBUG_PARTICLES<VECTOR<double,3> >&,bool,DEBUG_PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,3> >(std::string const&,PARTICLES<VECTOR<double,3> > const&,bool,PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,2> >(std::string const&,PARTICLES<VECTOR<float,2> > const&,bool,PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,3> >(std::string const&,PARTICLES<VECTOR<float,3> > const&,bool,PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,2> >(std::string const&,GRID<VECTOR<double,2> > const&,bool,GRID_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,3> >(std::string const&,GRID<VECTOR<double,3> > const&,bool,GRID_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,1> >(std::string const&,DEBUG_PARTICLES<VECTOR<double,1> >&,bool,DEBUG_PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,1> >(std::string const&,DEBUG_PARTICLES<VECTOR<float,1> >&,bool,DEBUG_PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,1> >(std::string const&,GRID<VECTOR<double,1> > const&,bool,GRID_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,1> >(std::string const&,PARTICLES<VECTOR<double,1> > const&,bool,PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,1> >(std::string const&,GRID<VECTOR<float,1> > const&,bool,GRID_OPTIONS const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,1> >(std::string const&,PARTICLES<VECTOR<float,1> > const&,bool,PARTICLES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<bool,2>(std::string const&,std::string const&,ARRAY<bool,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add<bool,3>(std::string const&,std::string const&,ARRAY<bool,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add<double,2>(std::string const&,std::string const&,ARRAY<double,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<double,2>(std::string const&,std::string const&,ARRAY_VIEW<double,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<double,3>(std::string const&,std::string const&,ARRAY<double,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<double,3>(std::string const&,std::string const&,ARRAY_VIEW<double,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,2>(std::string const&,std::string const&,ARRAY<float,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,2>(std::string const&,std::string const&,ARRAY_VIEW<float,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,3>(std::string const&,std::string const&,ARRAY<float,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,3>(std::string const&,std::string const&,ARRAY_VIEW<float,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<double,2>(std::string const&,std::string const&,ARRAY<VECTOR<double,2>,VECTOR<int,2> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<double,2>(std::string const&,std::string const&,ARRAY_VIEW<VECTOR<double,2>,VECTOR<int,2> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<double,3>(std::string const&,std::string const&,ARRAY_VIEW<VECTOR<double,3>,VECTOR<int,3> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<float,3>(std::string const&,std::string const&,ARRAY_VIEW<VECTOR<float,3>,VECTOR<int,3> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<bool,2>(std::string const&,std::string const&,ARRAY<bool,FACE_INDEX<2> > const&,bool,FACE_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add<bool,3>(std::string const&,std::string const&,ARRAY<bool,FACE_INDEX<3> > const&,bool,FACE_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Scalar<bool,2>(std::string const&,std::string const&,ARRAY<bool,FACE_INDEX<2> > const&,bool,FACE_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Scalar<bool,3>(std::string const&,std::string const&,ARRAY<bool,FACE_INDEX<3> > const&,bool,FACE_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add<bool,1>(std::string const&,std::string const&,ARRAY<bool,VECTOR<int,1> > const&,bool,SCALAR_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add<double,1>(std::string const&,std::string const&,ARRAY<double,VECTOR<int,1> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,1>(std::string const&,std::string const&,ARRAY<float,VECTOR<int,1> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<int,1>(std::string const&,std::string const&,ARRAY<int,VECTOR<int,1> > const&,bool,SCALAR_FIELD_OPTIONS<int> const&);
template void VIEWER_OUTPUT::Add<int,2>(std::string const&,std::string const&,ARRAY<int,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<int> const&);
template void VIEWER_OUTPUT::Add<int,3>(std::string const&,std::string const&,ARRAY<int,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<int> const&);
template void VIEWER_OUTPUT::Add<double,3>(std::string const&,std::string const&,ARRAY<VECTOR<double,3>,VECTOR<int,3> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<float,2>(std::string const&,std::string const&,ARRAY_VIEW<VECTOR<float,2>,VECTOR<int,2> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<float,3>(std::string const&,std::string const&,ARRAY<VECTOR<float,3>,VECTOR<int,3> > const&,bool,VECTOR_FIELD_OPTIONS const&);
template void VIEWER_OUTPUT::Add<bool,1>(std::string const&,std::string const&,ARRAY<bool,FACE_INDEX<1> > const&,bool,FACE_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Scalar<bool,1>(std::string const&,std::string const&,ARRAY<bool,FACE_INDEX<1> > const&,bool,FACE_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Face_Field<VECTOR<double,1>,double>(std::string const&,std::string const&,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Face_Field<VECTOR<double,2>,double>(std::string const&,std::string const&,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Face_Field<VECTOR<double,3>,double>(std::string const&,std::string const&,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Face_Field<VECTOR<float,1>,float>(std::string const&,std::string const&,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Face_Field<VECTOR<float,2>,float>(std::string const&,std::string const&,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Face_Field<VECTOR<float,3>,float>(std::string const&,std::string const&,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Levelset<double,1>(std::string const&,std::string const&,ARRAY<double,VECTOR<int,1> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&,VECTOR<double,3> const&);
template void VIEWER_OUTPUT::Add_Levelset<double,2>(std::string const&,std::string const&,ARRAY<double,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&,VECTOR<double,3> const&);
template void VIEWER_OUTPUT::Add_Levelset<double,3>(std::string const&,std::string const&,ARRAY<double,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&,VECTOR<double,3> const&);
template void VIEWER_OUTPUT::Add_Levelset<float,1>(std::string const&,std::string const&,ARRAY<float,VECTOR<int,1> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&,VECTOR<float,3> const&);
template void VIEWER_OUTPUT::Add_Levelset<float,2>(std::string const&,std::string const&,ARRAY<float,VECTOR<int,2> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&,VECTOR<float,3> const&);
template void VIEWER_OUTPUT::Add_Levelset<float,3>(std::string const&,std::string const&,ARRAY<float,VECTOR<int,3> > const&,bool,SCALAR_FIELD_OPTIONS<float> const&,VECTOR<float,3> const&);
template void VIEWER_OUTPUT::Add_Axes<1>(std::string const&,AXES_OPTIONS const&);
template void VIEWER_OUTPUT::Add_Axes<2>(std::string const&,AXES_OPTIONS const&);
template void VIEWER_OUTPUT::Add_Axes<3>(std::string const&,AXES_OPTIONS const&);
template void VIEWER_OUTPUT::Add<double,2>(std::string const&,std::string const&,ARRAY<double,FACE_INDEX<2> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<double,3>(std::string const&,std::string const&,ARRAY<double,FACE_INDEX<3> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,2>(std::string const&,std::string const&,ARRAY<float,FACE_INDEX<2> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,3>(std::string const&,std::string const&,ARRAY<float,FACE_INDEX<3> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar<double,2>(std::string const&,std::string const&,ARRAY<double,FACE_INDEX<2> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar<double,3>(std::string const&,std::string const&,ARRAY<double,FACE_INDEX<3> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar<float,2>(std::string const&,std::string const&,ARRAY<float,FACE_INDEX<2> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar<float,3>(std::string const&,std::string const&,ARRAY<float,FACE_INDEX<3> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<bool,1>,bool>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<bool,2>,bool>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<bool,3>,bool>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<bool> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<double,1>,double>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<double,2>,double>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<double,3>,double>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<float,1>,float>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<float,2>,float>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<float,3>,float>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<int,1>,int>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<int> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<int,2>,int>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<int> const&);
template void VIEWER_OUTPUT::Add_Scalar_Field<VECTOR<int,3>,int>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<int> const&);
template void VIEWER_OUTPUT::Add<double,1>(std::string const&,std::string const&,ARRAY<double,FACE_INDEX<1> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<float,1>(std::string const&,std::string const&,ARRAY<float,FACE_INDEX<1> > const&,bool,FACE_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,2> >(std::string const&,MESH_OBJECT<VECTOR<double,2>,1> const&,bool,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,3> >(std::string const&,MESH_OBJECT<VECTOR<double,3>,2> const&,bool,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add<VECTOR<double,3> >(std::string const&,MESH_OBJECT<VECTOR<double,3>,1> const&,bool,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,2> >(std::string const&,MESH_OBJECT<VECTOR<float,2>,1> const&,bool,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,3> >(std::string const&,MESH_OBJECT<VECTOR<float,3>,2> const&,bool,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add<VECTOR<float,3> >(std::string const&,MESH_OBJECT<VECTOR<float,3>,1> const&,bool,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,1>,1>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,2>,1>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,3>,1>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,1>,1>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,2>,1>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,3>,1>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<1> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,1>,3>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<3> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,2>,3>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<3> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,3>,3>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<3> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,1>,3>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<3> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,2>,3>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<3> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,3>,3>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<3> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,1>,2>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,2>,2>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<double,3>,2>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,1>,2>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,2>,2>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add_Split_Mesh<VECTOR<float,3>,2>(std::string const&,std::string const&,std::string const&,MESH_OPTIONS<2> const&);
template void VIEWER_OUTPUT::Add_Div<double,2>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Div<double,3>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Div<float,2>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
template void VIEWER_OUTPUT::Add_Div<float,3>(std::string const&,std::string const&,SCALAR_FIELD_OPTIONS<float> const&);
}
