Commit 2af8a709 authored by Dmitry Bagaev's avatar Dmitry Bagaev

Merge branch 'INMOST-DEV/master' into fixfc2

parents 6b1fd49b 86e6d1f4
...@@ -15,4 +15,5 @@ if(USE_AUTODIFF AND USE_SOLVER AND USE_MESH) ...@@ -15,4 +15,5 @@ if(USE_AUTODIFF AND USE_SOLVER AND USE_MESH)
add_subdirectory(ADFVDiscr) add_subdirectory(ADFVDiscr)
add_subdirectory(ADMFD) add_subdirectory(ADMFD)
endif(USE_AUTODIFF AND USE_SOLVER AND USE_MESH) endif(USE_AUTODIFF AND USE_SOLVER AND USE_MESH)
#add_subdirectory(OctreeCutcell) #add_subdirectory(OctreeCutcell)
\ No newline at end of file add_subdirectory(Octree)
\ No newline at end of file
CXX=mpicxx
CC=mpicxx
#links for cluster
PETSC_DIR=/data4t/terekhov/Packages/petsc-3.3-p3
PETSC_ARCH=arch-linux2-c-opt
INCPATH = -I../../ #-I/data4t/terekhov/program/include -I${PETSC_DIR}/${PETSC_ARCH}/include -I${PETSC_DIR}/include
OPTFLAGS= -O0 -g -Wall
#OPTFLAGS= -O3
#MYLIBS=../../mspp.a
MYLIBS= ../../msppd.a
CXXFLAGS=$(OPTFLAGS) $(INCPATH)
LDFLAGS=$(OPTFLAGS)
PETSC = -L${PETSC_DIR}/${PETSC_ARCH}/lib/
#-lpetsc -L/usr/X11R6/lib -lX11 -ldmumps -lmumps_common -lmpi_f77 -lscalapack -lpord -lblacs -lparmetis -lmetis -lflapack -lfblas -lmpi -lHYPRE -lsuperlu_dist_2.4
#PETSC+=-lpetsc -L/usr/X11R6/lib64 -lX11 -lpthread -lmpigc4 -lstdc++ -ldmumps -lmumps_common -lscalapack -lpord -lblacs -lparmetis -lmetis -lmpi -lHYPRE -lflapack -lfblas -L/opt/intel/impi/3.2.2.006/lib64 -L/opt/intel/mpi-rt/3.2.2 -lmpigc4 -lmpigf -lmpi ../../ILU2/lib/libilu-2.3.a -lgfortran
PETSC =-lpetsc -L/usr/X11R6/lib -lX11 -lparmetis -lmetis -lmpi_f77 -lflapack -lfblas -lgfortran
ILU2 = ../../ILU2/lib/libilu-2.3.a -lgfortran
LDLIBS=$(MYLIBS) $(PETSC) $(ILU2)
targets=main
all: $(targets)
main: main.o
clean:
rm -f $(targets) *.o
project(Octree)
set(SOURCE main.cpp
rotate.cpp
rotate.h
octgrid.cpp
octgrid.h
my_glut.h)
add_executable(Octree ${SOURCE})
target_link_libraries(Octree inmost lapack blas)
if(USE_MPI)
message("linking with mpi")
target_link_libraries(Octree ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
message("adding link flags")
set_target_properties(Octree PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
find_package(OpenGL)
find_package(GLUT)
if(OPENGL_FOUND)
if(GLUT_FOUND)
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${GLUT_INCLUDE_DIR})
add_definitions(-D__GRAPHICS__)
target_link_libraries(Octree ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES})
else(GLUT_FOUND)
message("GLUT not found")
endif(GLUT_FOUND)
else(OPENGL_FOUND)
message("OpenGL not found")
endif(OPENGL_FOUND)
if(USE_PARTITIONER_ZOLTAN)
message("linking Octree with Zoltan")
target_link_libraries(Octree ${ZOLTAN_LIBRARIES})
endif()
if(USE_PARTITIONER_PARMETIS)
message("linking Octree with ParMETIS")
target_link_libraries(Octree ${PARMETIS_LIBRARIES})
endif()
This diff is collapsed.
#if defined(__GRAPHICS__)
#if defined (__APPLE__) || defined(MAXOSX)
#include <GLUT/glut.h>
#endif
#if defined(_WIN32)
//#include <GL/glut.h>
#include <windows.h>
#include <GL/glut.h>
//#include "glut.h"
#pragma comment(lib,"glut32.lib")
#endif
#if defined(__linux__)
#include <GL/glut.h>
#endif
#endif
This diff is collapsed.
#ifndef _OCTGRID_H
#define _OCTGRID_H
#include "inmost.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DIM 3
using namespace INMOST;
#define TSNH {printf("(%s:%d) this should not happen!\n",__FILE__,__LINE__); exit(-1);}
#define WAITNL {int ret; char c; printf("press Enter\n"); ret = scanf("%c",&c);}
#define VBUFFER 131072
#define CBUFFER 131072
/// Struct conatains tags for one cell
struct Cell_Tags
{
/// Center of cell (3 coordinates)
Tag center;
/// Sides of cell (3 doubles)
Tag side;
/// Number of cell in z dimension (up/down).
Tag floor;
/// Only for child cell. Octree division means 8 children. This tag contains id among other children.
/// Numeration: 1 2 above them 5 6
/// 0 3 4 7
Tag chld_num;
/// Child id for parent
Tag par_chld_nums;
/// Level of partition
Tag level;
/// Cell should be split
Tag to_split;
Tag busy;
Tag leaf;
Tag vertexes;
Tag children;
Tag parent;
Tag is_valid;
/// Number of processor before redistribute
Tag proc;
Tag i;
};
/// Main object, contains all information about mesh
struct grid
{
/// Inmost mesh
Mesh* mesh;
Cell_Tags c_tags;
void (*transformation)(double xyz[3]);
void (*rev_transformation)(double xyz[3]);
int (*cell_should_split)(struct grid * g, Cell cell, int level);
int (*cell_should_unite)(struct grid * g, Cell cell);
};
/// Often after redistribution brother cells splits to different processor
/// This function corrects this division. Puts all children to one processor
void correct_brothers(struct grid* g, int size, int rank, int type);
/// Debug. Print information about all cells
void print_all_about_cells(struct grid * g);
/// Initialize grid. Create tags and other data
void gridInit(struct grid * g, int n[3]);
/// Split cells using "cell_should_split" rule
void gridRefine(struct grid * g);
/// Unite cells using "cell_should_unite" rule
void gridCoarse(struct grid * g);
/// Unite and coarse cells
void gridAMR(struct grid * g, int action);
/// Default method of transformation
void default_transformation(double xyz[3]);
/// Default method of unite
int default_cell_should_unite(struct grid * g, int cell);
/// Default method of split
int default_cell_should_split(struct grid * g, int cell);
#endif
#if defined(__GRAPHICS__)
/*********************************
Implementation of quaternion-based
object rotation
Functions
clickmotion - call when holded mouse moved
click - call when user clicks
motion - call when mouse just moves
quatinit - flush rotation value
rotate - multiply GL matrix
Dependency: rotate.h,
Standard: math.h
Specific: glut.h
**********************************/
#include "my_glut.h"
#include "rotate.h"
#include "math.h"
#include <stdio.h>
struct quaternion
{
double x,y,z,w;
};
struct vector
{
double x,y,z;
};
// Rotation
struct quaternion q;
struct vector drag, onclick;
double rotate_mx,rotate_my;
extern int width, height;
//
void rotate_clickmotion(int nmx, int nmy) // Mouse
{
struct vector n;
double norm,length,t;
rotate_mx = 2.*(nmx/(double)width - 0.5);
rotate_my = 2.*(0.5 - nmy/(double)height);
norm = rotate_mx*rotate_mx + rotate_my*rotate_my;
if( norm > 1.0 )
{
length = sqrt(norm);
drag.x = rotate_mx/length;
drag.y = rotate_my/length;
drag.z = 0.0;
}
else
{
drag.x = rotate_mx;
drag.y = rotate_my;
drag.z = sqrt(1.0-norm);
}
n.x = drag.y*onclick.z - drag.z*onclick.y;
n.y = drag.z*onclick.x - drag.x*onclick.z;
n.z = drag.x*onclick.y - drag.y*onclick.x;
if ( n.x*n.x + n.y*n.y + n.z*n.z > 10e-7 )
{
t = drag.x*onclick.x + drag.y*onclick.y + drag.z*onclick.z;
q.x = + q.x*t + q.y*n.z - q.z*n.y + q.w*n.x;
q.y = - q.x*n.z + q.y*t + q.z*n.x + q.w*n.y;
q.z = + q.x*n.y - q.y*n.x + q.z*t + q.w*n.z;
q.w = - q.x*n.x - q.y*n.y - q.z*n.z + q.w*t;
onclick.x = drag.x;
onclick.y = drag.y;
onclick.z = drag.z;
}
glutPostRedisplay();
}
void rotate_motion(int nmx, int nmy) // Mouse
{
rotate_mx = 2.*(nmx/(double)width - 0.5);
rotate_my = 2.*(0.5 - nmy/(double)height);
}
void rotate_click(int b, int s, int nmx, int nmy) // Mouse
{
(void ) s;
double norm,length;
switch(b)
{
case GLUT_LEFT_BUTTON:
rotate_mx = 2.*(nmx/(double)width - 0.5);
rotate_my = 2.*(0.5 - nmy/(double)height);
norm = rotate_mx*rotate_mx + rotate_my*rotate_my;
if( norm > 1.0 )
{
length = sqrt(norm);
drag.x = rotate_mx/length;
drag.y = rotate_my/length;
drag.z = 0.0;
}
else
{
drag.x = rotate_mx;
drag.y = rotate_my;
drag.z = sqrt(1.0-norm);
}
onclick.x = drag.x;
onclick.y = drag.y;
onclick.z = drag.z;
break;
}
glutPostRedisplay();
}
void quatinit()
{
q.x = 0.0;
q.y = 0.0;
q.z = 0.0;
q.w = 1.0;
}
void rotate()
{
double rot[16];
rot[ 0] = (q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z);
rot[ 1] = 2.*(q.x*q.y - q.w*q.z);
rot[ 2] = 2.*(q.x*q.z + q.w*q.y);
rot[ 3] = 0.0;
rot[ 4] = 2.*(q.x*q.y + q.w*q.z);
rot[ 5] = (q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z);
rot[ 6] = 2.*(q.y*q.z - q.w*q.x);
rot[ 7] = 0.0;
rot[ 8] = 2.*(q.x*q.z - q.w*q.y);
rot[ 9] = 2.*(q.y*q.z + q.w*q.x);
rot[10] = (q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z);
rot[11] = 0.0;
rot[12] = 0.0;
rot[13] = 0.0;
rot[14] = 0.0;
rot[15] = (q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z);
glMultMatrixd(rot);
}
#endif
#if defined(__GRAPHICS__)
/*********************************
Implementation of quaternion-based
object rotation
Functions
clickmotion - call when holded mouse moved
click - call when user clicks
motion - call when mouse just moves
quatinit - flush rotation value
rotate - multiply GL matrix
Dependency: rotate.h,
Standard: math.h
Specific: glut.h
**********************************/
#ifndef _ROTATE_H
#define _ROTATE_H
void rotate_clickmotion(int nmx, int nmy);
void rotate_motion(int nmx, int nmy);
void rotate_click(int b, int s, int nmx, int nmy);
void quatinit();
void rotate();
#endif
#endif
...@@ -220,8 +220,10 @@ namespace INMOST ...@@ -220,8 +220,10 @@ namespace INMOST
friend class Storage; friend class Storage;
friend class Mesh; friend class Mesh;
}; };
class TagManager //implemented in tag.cpp class TagManager //implemented in tag.cpp
{ {
protected: protected:
TagManager(); TagManager();
...@@ -607,6 +609,123 @@ namespace INMOST ...@@ -607,6 +609,123 @@ namespace INMOST
__INLINE ElementSet getAsSet () const; __INLINE ElementSet getAsSet () const;
friend class Mesh; friend class Mesh;
}; };
//////////////////////////////////////////////////////////////////////
/// Helper classes for class Tag //
//////////////////////////////////////////////////////////////////////
class TagReal : public Tag
{
public:
TagReal() : Tag() {}
TagReal(const TagReal & b) : Tag(b) {}
TagReal(const Tag & b) : Tag(b) {}
TagReal & operator = (TagReal const & b) {Tag::operator =(b); return *this;}
TagReal & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::real & operator [](const Storage & arg) const {return arg.Real(*static_cast<const Tag*>(this));}
};
class TagInteger : public Tag
{
public:
TagInteger() : Tag() {}
TagInteger(const TagInteger & b) : Tag(b) {}
TagInteger(const Tag & b) : Tag(b) {}
TagInteger & operator = (TagInteger const & b) {Tag::operator =(b); return *this;}
TagInteger & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::integer & operator [](const Storage & arg) const {return arg.Integer(*static_cast<const Tag*>(this));}
};
class TagBulk : public Tag
{
public:
TagBulk() : Tag() {}
TagBulk(const TagBulk & b) : Tag(b) {}
TagBulk(const Tag & b) : Tag(b) {}
TagBulk & operator = (TagBulk const & b) {Tag::operator =(b); return *this;}
TagBulk & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::bulk & operator [](const Storage & arg) const {return arg.Bulk(*static_cast<const Tag*>(this));}
};
class TagReference : public Tag
{
public:
TagReference() : Tag() {}
TagReference(const TagReference & b) : Tag(b) {}
TagReference(const Tag & b) : Tag(b) {}
TagReference & operator = (TagReference const & b) {Tag::operator =(b); return *this;}
TagReference & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::reference & operator [](const Storage & arg) const {return arg.Reference(*static_cast<const Tag*>(this));}
};
class TagRealArray : public Tag
{
public:
TagRealArray() : Tag() {}
TagRealArray(const TagRealArray & b) : Tag(b) {}
TagRealArray(const Tag & b) : Tag(b) {}
TagRealArray & operator = (TagRealArray const & b) {Tag::operator =(b); return *this;}
TagRealArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::real_array operator [](const Storage & arg) const {return arg.RealArray(*static_cast<const Tag*>(this));}
};
class TagIntegerArray : public Tag
{
public:
TagIntegerArray() : Tag() {}
TagIntegerArray(const TagIntegerArray & b) : Tag(b) {}
TagIntegerArray(const Tag & b) : Tag(b) {}
TagIntegerArray & operator = (TagIntegerArray const & b) {Tag::operator =(b); return *this;}
TagIntegerArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::integer_array operator [](const Storage & arg) const {return arg.IntegerArray(*static_cast<const Tag*>(this));}
};
class TagBulkArray : public Tag
{
public:
TagBulkArray() : Tag() {}
TagBulkArray(const TagBulkArray & b) : Tag(b) {}
TagBulkArray(const Tag & b) : Tag(b) {}
TagBulkArray & operator = (TagBulkArray const & b) {Tag::operator =(b); return *this;}
TagBulkArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::bulk_array operator [](const Storage & arg) const {return arg.BulkArray(*static_cast<const Tag*>(this));}
};
class TagReferenceArray : public Tag
{
public:
TagReferenceArray() : Tag() {}
TagReferenceArray(const TagReferenceArray & b) : Tag(b) {}
TagReferenceArray(const Tag & b) : Tag(b) {}
TagReferenceArray & operator = (TagReferenceArray const & b) {Tag::operator =(b); return *this;}
TagReferenceArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::reference_array operator [](const Storage & arg) const {return arg.ReferenceArray(*static_cast<const Tag*>(this));}
};
#if defined(USE_AUTODIFF)
class TagVariable : public Tag
{
public:
TagVariable() : Tag() {}
TagVariable(const TagVariable & b) : Tag(b) {}
TagVariable(const Tag & b) : Tag(b) {}
TagVariable & operator = (TagVariable const & b) {Tag::operator =(b); return *this;}
TagVariable & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::var & operator [](const Storage & arg) const {return arg.Variable(*static_cast<const Tag*>(this));}
};
class TagVariableArray : public Tag
{
public:
TagVariableArray() : Tag() {}
TagVariableArray(const TagVariableArray & b) : Tag(b) {}
TagVariableArray(const Tag & b) : Tag(b) {}
TagVariableArray & operator = (TagVariableArray const & b) {Tag::operator =(b); return *this;}
TagVariableArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::var_array operator [](const Storage & arg) const {return arg.VariableArray(*static_cast<const Tag*>(this));}
};
#endif //USE_AUTODIFF
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
/// Inline functions for class Tag // /// Inline functions for class Tag //
......
This diff is collapsed.
...@@ -438,18 +438,28 @@ namespace INMOST ...@@ -438,18 +438,28 @@ namespace INMOST
void Centroid (real * cnt) const; void Centroid (real * cnt) const;
void Barycenter (real * cnt) const; void Barycenter (real * cnt) const;
Storage::real Mean (real (*func)(real* x,real t),real time) const; Storage::real Mean (real (*func)(real* x,real t),real time) const;
/// Determine that the element is on the boundary.
/// \warning This function does not involve communication
/// for distributed mesh and works only for local partition
/// of the mesh. It cannot correctly determine boundary elements
/// of the global mesh. For this purpose you should use
/// Mesh::MarkBoundaryFaces
/// @return True if the element is on the boundary, otherwise false.
/// @see Mesh::MarkBoundaryFaces
bool Boundary () const; bool Boundary () const;
bool Planarity () const; // check that all nodes lay on one plane bool Planarity () const; // check that all nodes lay on one plane
//implemented in modify.cpp //implemented in modify.cpp
/// If the function returns true then element was hidden, /// If the function returns true then element was hidden,
/// works only inside BeginModification and EndModification, /// works only inside BeginModification and EndModification,
/// on EndModification all Hidden elements are deleted. /// on EndModification all Hidden elements are deleted.
/// \todo Probably have to check normal orientation after hiding a back cell for a face. /// \todo Probably have to check normal orientation after
/// hiding a back cell for a face.
bool Hide () const; bool Hide () const;
/// If the function returns true then element was recovered /// If the function returns true then element was recovered
/// from hidden state, works only inside BeginModification /// from hidden state, works only inside BeginModification
/// and EndModification. /// and EndModification.
/// \todo Probably have to check normal orientation after recovering a back cell for a face. /// \todo Probably have to check normal orientation after
/// recovering a back cell for a face.
bool Show () const; // if true then element was recovered bool Show () const; // if true then element was recovered
/// Remove element from mesh. /// Remove element from mesh.
/// If you call this function inside modification phase, see Mesh::BeginModification and Mesh::EndModification, /// If you call this function inside modification phase, see Mesh::BeginModification and Mesh::EndModification,
......
...@@ -152,13 +152,18 @@ namespace INMOST ...@@ -152,13 +152,18 @@ namespace INMOST
case Element::MultiLine: case Element::MultiLine:
case Element::Polygon: case Element::Polygon:
case Element::Tet: case Element::Tet:
case Element::Hex:
case Element::Pyramid:
case Element::Prism:
{ {
ElementArray<Node> nodes = it->getNodes(); ElementArray<Node> nodes = it->getNodes();
if( nodes.size() != VtkElementNodes(it->GetGeometricType()) ) goto safe_output;
values.push_back(static_cast<integer>(nodes.size())); values.push_back(static_cast<integer>(nodes.size()));
for(ElementArray<Node>::iterator jt = nodes.begin(); jt != nodes.end(); jt++) for(ElementArray<Node>::iterator jt = nodes.begin(); jt != nodes.end(); jt++)
values.push_back(jt->IntegerDF(set_id)); values.push_back(jt->IntegerDF(set_id));
break; break;
} }
/*
case Element::Prism: case Element::Prism:
{ {
ElementArray<Node> nodes = it->getNodes(); ElementArray<Node> nodes = it->getNodes();
...@@ -172,6 +177,8 @@ namespace INMOST ...@@ -172,6 +177,8 @@ namespace INMOST
values.push_back(nodes[4].IntegerDF(set_id)); values.push_back(nodes[4].IntegerDF(set_id));
break; break;
} }
*/
/*
case Element::Hex: case Element::Hex:
{ {
ElementArray<Node> nodes = it->getNodes(); ElementArray<Node> nodes = it->getNodes();
...@@ -199,17 +206,17 @@ namespace INMOST ...@@ -199,17 +206,17 @@ namespace INMOST
values.push_back(nodes[4].IntegerDF(set_id)); values.push_back(nodes[4].IntegerDF(set_id));
break; break;
} }
*/
case Element::Polyhedron: case Element::Polyhedron:
case Element::MultiPolygon: case Element::MultiPolygon:
{ {
safe_output: safe_output:
//printf("polyhedron!!!\n"); //printf("polyhedron!!!\n");
ElementArray<Face> faces = it->getFaces(); ElementArray<Face> faces = it->getFaces();
integer totalNum = 1 + static_cast<integer>(faces.size()); integer totalNum = 1 + static_cast<integer>(faces.size());
for(ElementArray<Face>::iterator jt = faces.begin(); jt != faces.end(); jt++) for(ElementArray<Face>::iterator jt = faces.begin(); jt != faces.end(); jt++)
totalNum += jt->nbAdjElements(NODE); totalNum += jt->nbAdjElements(NODE);
values.push_back(totalNum);
values.push_back(totalNum);
values.push_back(static_cast<integer>(faces.size())); values.push_back(static_cast<integer>(faces.size()));
for(ElementArray<Face>::iterator jt = faces.begin(); jt != faces.end(); jt++) for(ElementArray<Face>::iterator jt = faces.begin(); jt != faces.end(); jt++)
{ {
......
...@@ -1134,11 +1134,8 @@ namespace INMOST ...@@ -1134,11 +1134,8 @@ namespace INMOST
switch(GetElementType()) switch(GetElementType())
{ {
case FACE: case FACE:
if( nbAdjElements(CELL) == 1 ) if( !getAsFace()->FrontCell().isValid() )
{ return true;
if( getAsFace()->BackCell()->GetStatus() != Element::Ghost )
return true;
}
return false; return false;
case CELL: case CELL:
case EDGE: case EDGE:
......
...@@ -1365,9 +1365,9 @@ namespace INMOST ...@@ -1365,9 +1365,9 @@ namespace INMOST
} }
ElementArray<Node> verts = face->getNodes(); ElementArray<Node> verts = face->getNodes();
if( face->BackCell() == c ) if( face->BackCell() == c )
ret.insert(ret.end(),verts.begin(),verts.end());
else
ret.insert(ret.end(),verts.rbegin(),verts.rend()); ret.insert(ret.end(),verts.rbegin(),verts.rend());
else
ret.insert(ret.end(),verts.begin(),verts.end());
ElementArray<Edge> c_edges = c->getEdges(); ElementArray<Edge> c_edges = c->getEdges();
ElementArray<Edge> f_edges = face->getEdges(); ElementArray<Edge> f_edges = face->getEdges();
c_edges.SetPrivateMarker(cemrk); c_edges.SetPrivateMarker(cemrk);
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <sstream> #include <sstream>
#include "inmost_sparse.h" #include "inmost_sparse.h"
#define SILENCE_SET_PARAMETER
namespace INMOST { namespace INMOST {
#if defined(USE_SOLVER) #if defined(USE_SOLVER)
......
...@@ -190,7 +190,7 @@ namespace INMOST { ...@@ -190,7 +190,7 @@ namespace INMOST {
input.open(xml_database); input.open(xml_database);
if (input.fail()) { if (input.fail()) {
std::cout << __FILE__ << ": XML database file not found " << std::endl; std::cout << __FILE__ << ":" << __LINE__ << ": XML database file " << xml_database << " not found." << std::endl;
return; <