<commit_before>#ifndef DUNE_STUFF_FUNCTIONADAPTER_HH
#define DUNE_STUFF_FUNCTIONADAPTER_HH

#include <vector>
#include <boost/shared_ptr.hpp>
#include <dune/stuff/printing.hh>

namespace Stuff {

/** DiscreteFunction container \f$G\f$ that takes a \$f(dxd)\$f matrix valued function \f$f\f$ as input that splits itself into \$fd\$f
	DiscreteFunctions that are each \$fd\$f valued.
  * \f{eqnarray*}f\rightarrow (a_{ij})_{1<=i,j<=d}\\
  * G_k= \sum_K\int_K \sum_{l=1..d}a_{kl} \phi_{l} dx\f}
  **/
template < class DiscreteFunctionType, class DiscreteGradientFunctionType >
class GradientSplitterFunction : public std::vector< boost::shared_ptr< DiscreteFunctionType > >
{
	typedef std::vector< DiscreteFunctionType >
		BaseType;
	typedef GradientSplitterFunction< DiscreteFunctionType, DiscreteGradientFunctionType >
		ThisType;
	typedef typename boost::shared_ptr< DiscreteFunctionType >
		PointerType;

public:
	GradientSplitterFunction(	const typename DiscreteFunctionType::FunctionSpaceType& space,
								const DiscreteGradientFunctionType&  gradient )
	{
		typedef typename DiscreteFunctionType::FunctionSpaceType::DomainType
			DomainType;
		const size_t dim = DomainType::dimension;
		for ( size_t d = 0; d < dim; ++d ) {
			PointerType p( new DiscreteFunctionType( (boost::format("%s_%s") % gradient.name() % Stuff::dimToAxisName(d,true) ).str(),
			                                         space ) );//never use temporary smart pointers
			push_back( p );
		}

		typedef typename DiscreteFunctionType::FunctionSpaceType
			DiscreteFunctionSpaceType;
		typedef typename DiscreteGradientFunctionType::FunctionSpaceType
			DiscreteGradientFunctionSpaceType;
		typedef typename DiscreteFunctionType::LocalFunctionType
			LocalFunctionType;
		typedef std::vector< LocalFunctionType >
			LocalFunctionVectorType;
		typedef typename DiscreteGradientFunctionType::LocalFunctionType
			LocalGradientFunctionType;
		typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
			GridPartType;
		typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
			Iterator;
		typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
			BaseFunctionSetType ;
		typedef typename GridPartType::IntersectionIteratorType
			IntersectionIteratorType;

		const GridPartType& gridPart = space.gridPart();
		// type of quadrature
		typedef Dune::CachingQuadrature<GridPartType,0> VolumeQuadratureType;
		typedef Dune::CachingQuadrature<GridPartType,1> FaceQuadratureType;
		// type of local mass matrix
		typedef Dune::LocalDGMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType> LocalMassMatrixType;

		const int quadOrd =  (2 * space.order());

		// create local mass matrix object
		LocalMassMatrixType massMatrix( space, quadOrd );

		// check whether geometry mappings are affine or not
		const bool affineMapping = massMatrix.affine();

		const Iterator endit = space.end();
		for(Iterator it = space.begin(); it != endit ; ++it)
		{
			// get entity
			const typename GridType::template Codim<0>::Entity& entity = *it;
			// get geometry
			typedef  typename GridType::template Codim<0>::Geometry
				Geometry;
			const Geometry& geo = entity.geometry();

			// get quadrature
			VolumeQuadratureType quad(entity, quadOrd);

			// get local function of destination

			// get local function of argument
			const LocalGradientFunctionType gradient_local = gradient.localFunction(entity);

			for ( size_t d = 0; d < dim; ++d ) {
				LocalFunctionType local_function = this->at(d)->localFunction( entity );

				const BaseFunctionSetType & baseset = local_function.baseFunctionSet();

				const int quadNop = quad.nop();
				const int numDofs = local_function.numDofs();

				//volume part
				for(int qP = 0; qP < quadNop ; ++qP)
				{
					const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

					const double intel = (affineMapping) ?
						quad.weight(qP): // affine case
						quad.weight(qP)* geo.integrationElement( xLocal ); // general case

					typename DiscreteFunctionSpaceType::DomainType
						xWorld = geo.global( xLocal );

					// evaluate function
					typename DiscreteGradientFunctionType::RangeType
						gradient_eval;
					gradient_local.evaluate( quad[qP], gradient_eval );

					typename DiscreteFunctionSpaceType::RangeType
					        jacobian_row;
					for ( size_t e = 0; e < dim; ++e ) {
						jacobian_row[e] = gradient_eval(d,e);
					}
					// do projection
					for(int i=0; i<numDofs; ++i)
					{
						typename DiscreteFunctionType::RangeType phi (0.0);
						baseset.evaluate(i, quad[qP], phi);
						local_function[i] += intel * ( jacobian_row * phi );
					}
				}

				// in case of non-linear mapping apply inverse
				if ( ! affineMapping )
				{
					massMatrix.applyInverse( entity, local_function );
				}
			}
		}
	}
};

	template < int dim, class RangeType, class JacobianRangeType >
	struct GradientJacobianToLaplacian : public RangeType
	{
		GradientJacobianToLaplacian( const JacobianRangeType& jacobian )
		{
			Dune::CompileTimeChecker< ( dim == 1 || dim > 3 ) > NotImplemented;
		}
	};

	template < class RangeType, class JacobianRangeType >
	struct GradientJacobianToLaplacian< 2, RangeType, JacobianRangeType>  : public RangeType
	{
		GradientJacobianToLaplacian( const JacobianRangeType& jacobian )
		{
			(*this)[0] = jacobian[0][0];
			(*this)[1] = jacobian[3][1];
		}
	};

	template < class RangeType, class JacobianRangeType >
	struct GradientJacobianToLaplacian< 3, RangeType, JacobianRangeType>  : public RangeType
	{
		GradientJacobianToLaplacian( const JacobianRangeType& jacobian )
		{
			(*this)[0] = jacobian[0][0];
			(*this)[1] = jacobian[4][1];
			(*this)[2] = jacobian[8][2];
		}
	};

	struct ProductFunctorMatrices {
		template < class R1, class R2 >
		static double call (const R1& r1,const R2& r2 ) {
			return Stuff::colonProduct( r1, r2 );
		}
	};

	struct ProductFunctorMatrixVector {
		template < class R1, class R2 >
		static double call (const R1& r1,const R2& r2 ) {
			Dune::FieldVector< double, 1 > res;
			r1.mv( r2, res ) ;
			return res[0];
		}
	};

	template <	class DiscreteVelocityFunctionType,
				class SigmaFunctionType,
				class ProductFunctor >
	class GradientAdapterFunction :
			public SigmaFunctionType
	{
		protected:
			typedef GradientAdapterFunction <	DiscreteVelocityFunctionType,
												SigmaFunctionType,
												ProductFunctor>
				ThisType;
			typedef SigmaFunctionType
				BaseType;

		public:
			GradientAdapterFunction ( const DiscreteVelocityFunctionType& velocity,
								  SigmaFunctionType& dummy,
								  int polOrd = -1 )
				: BaseType( "grad" , dummy.space())
			{
				typedef SigmaFunctionType
					DiscreteFunctionType;
				typedef typename SigmaFunctionType::DiscreteFunctionSpaceType
					DiscreteFunctionSpaceType;
				typedef typename DiscreteFunctionType::LocalFunctionType
					LocalFuncType;
				typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
					GridPartType;
				typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
					Iterator;
				typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
					BaseFunctionSetType ;
				typedef typename GridPartType::IntersectionIteratorType
					IntersectionIteratorType;
				typedef typename DiscreteVelocityFunctionType::LocalFunctionType
					LocalFType;

				const DiscreteFunctionSpaceType space ( velocity.space().gridPart() );
				const GridPartType& gridPart = space.gridPart();
				// type of quadrature
				typedef Dune::CachingQuadrature<GridPartType,0> VolumeQuadratureType;
				typedef Dune::CachingQuadrature<GridPartType,1> FaceQuadratureType;
				// type of local mass matrix
				typedef Dune::LocalDGMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType> LocalMassMatrixType;

				const int quadOrd = (polOrd == -1) ? (2 * space.order()) : polOrd;

				// create local mass matrix object
				LocalMassMatrixType massMatrix( space, quadOrd );

				// check whether geometry mappings are affine or not
				const bool affineMapping = massMatrix.affine();

				// clear destination
				BaseType::clear();

				const Iterator endit = space.end();
				for(Iterator it = space.begin(); it != endit ; ++it)
				{
					// get entity
					const typename GridType::template Codim<0>::Entity& entity = *it;
					// get geometry
					typedef  typename GridType::template Codim<0>::Geometry
						Geometry;
					const Geometry& geo = entity.geometry();

					// get quadrature
					VolumeQuadratureType quad(entity, quadOrd);

					// get local function of destination
					LocalFuncType self_local = BaseType::localFunction(entity);
					// get local function of argument
					const LocalFType velocity_local = velocity.localFunction(entity);

					// get base function set
					const BaseFunctionSetType & baseset = self_local.baseFunctionSet();

					const int quadNop = quad.nop();
					const int numDofs = self_local.numDofs();

					//volume part
					for(int qP = 0; qP < quadNop ; ++qP)
					{
						const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

						const double intel = (affineMapping) ?
							quad.weight(qP): // affine case
							quad.weight(qP)* geo.integrationElement( xLocal ); // general case

						typename DiscreteFunctionSpaceType::DomainType
							xWorld = geo.global( xLocal );

						// evaluate function
						typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::RangeType
							velocity_eval;
						velocity_local.evaluate( quad[qP], velocity_eval );

						typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::JacobianRangeType
							velocity_jacobian_eval;
						velocity_local.jacobian( quad[qP], velocity_jacobian_eval );

						// do projection
						for(int i=0; i<numDofs; ++i)
						{
							typename DiscreteFunctionType::DiscreteFunctionSpaceType::RangeType phi (0.0);
							baseset.evaluate(i, quad[qP], phi);
							self_local[i] += intel * ProductFunctor::call( velocity_jacobian_eval, phi );
						}
					}

					// in case of non-linear mapping apply inverse
					if ( ! affineMapping )
					{
						massMatrix.applyInverse( entity, self_local );
					}
				}
			}

	};

	template <	class DiscreteVelocityFunctionType,
				class SigmaFunctionType,
				class ProductFunctor >
	class LaplaceAdapterFunction :
			public DiscreteVelocityFunctionType
	{
		protected:
			typedef LaplaceAdapterFunction <	DiscreteVelocityFunctionType,
												SigmaFunctionType,
												ProductFunctor>
				ThisType;
			typedef DiscreteVelocityFunctionType
				BaseType;

		public:
			LaplaceAdapterFunction( const DiscreteVelocityFunctionType& velocity,
								  SigmaFunctionType& dummy,
								  int polOrd = -1 )
				: BaseType( "grad" , velocity.space())
			{
				GradientAdapterFunction<	DiscreteVelocityFunctionType,
											SigmaFunctionType,
											ProductFunctor>
				        gradient( velocity, dummy, polOrd );
				init( gradient, polOrd );
			}

//			LaplaceAdapterFunction( const SigmaFunctionType& gradient )
//				: BaseType( "grad" , velocity.space())
//			{
//				init( gradient, -1 );
//			}

			void init( const SigmaFunctionType& gradient, int polOrd )
			{
				typedef DiscreteVelocityFunctionType
					DiscreteFunctionType;
				typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType
					DiscreteFunctionSpaceType;
				typedef typename DiscreteFunctionType::LocalFunctionType
					LocalFuncType;
				typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
					GridPartType;
				typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
					Iterator;
				typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
					BaseFunctionSetType ;
				typedef typename GridPartType::IntersectionIteratorType
					IntersectionIteratorType;
				typedef typename SigmaFunctionType::LocalFunctionType
					LocalFType;

				const DiscreteFunctionSpaceType& space = BaseType::space();
				const GridPartType& gridPart = space.gridPart();
				// type of quadrature
				typedef Dune::CachingQuadrature<GridPartType,0> VolumeQuadratureType;
				typedef Dune::CachingQuadrature<GridPartType,1> FaceQuadratureType;
				// type of local mass matrix
				typedef Dune::LocalDGMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType> LocalMassMatrixType;

				const int quadOrd = (polOrd == -1) ? (2 * space.order()) : polOrd;

				// create local mass matrix object
				LocalMassMatrixType massMatrix( space, quadOrd );

				// check whether geometry mappings are affine or not
				const bool affineMapping = massMatrix.affine();

				// clear destination
				BaseType::clear();

				const Iterator endit = space.end();
				for(Iterator it = space.begin(); it != endit ; ++it)
				{
					// get entity
					const typename GridType::template Codim<0>::Entity& entity = *it;
					// get geometry
					typedef  typename GridType::template Codim<0>::Geometry
						Geometry;
					const Geometry& geo = entity.geometry();

					// get quadrature
					VolumeQuadratureType quad(entity, quadOrd);

					// get local function of destination
					LocalFuncType self_local = BaseType::localFunction(entity);
					// get local function of argument
					const LocalFType gradient_local = gradient.localFunction(entity);

					// get base function set
					const BaseFunctionSetType & baseset = self_local.baseFunctionSet();

					const int quadNop = quad.nop();
					const int numDofs = self_local.numDofs();

					//volume part
					for(int qP = 0; qP < quadNop ; ++qP)
					{
						const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

						const double intel = (affineMapping) ?
							quad.weight(qP): // affine case
							quad.weight(qP)* geo.integrationElement( xLocal ); // general case

						typename DiscreteFunctionSpaceType::DomainType
							xWorld = geo.global( xLocal );

						typename SigmaFunctionType::DiscreteFunctionSpaceType::JacobianRangeType
							gradient_jacobian_eval;
						gradient_local.jacobian( quad[qP], gradient_jacobian_eval );

						GradientJacobianToLaplacian<	DiscreteFunctionType::RangeType::size,
																typename DiscreteFunctionType::RangeType,
																typename SigmaFunctionType::JacobianRangeType >
								velocity_real_laplacian ( gradient_jacobian_eval );

						// do projection
						for(int i=0; i<numDofs; ++i)
						{
							typename DiscreteFunctionType::DiscreteFunctionSpaceType::RangeType phi (0.0);
							baseset.evaluate(i, quad[qP], phi);
							self_local[i] += intel * ( velocity_real_laplacian * phi );
						}
					}

					// in case of non-linear mapping apply inverse
					if ( ! affineMapping )
					{
						massMatrix.applyInverse( entity, self_local );
					}
				}
			}

	};

}

#endif // DUNE_STUFF_FUNCTIONADAPTER_HH
<commit_msg>magic number<commit_after>#ifndef DUNE_STUFF_FUNCTIONADAPTER_HH
#define DUNE_STUFF_FUNCTIONADAPTER_HH

#include <vector>
#include <boost/shared_ptr.hpp>
#include <dune/stuff/printing.hh>

namespace Stuff {

/** DiscreteFunction container \f$G\f$ that takes a \$f(dxd)\$f matrix valued function \f$f\f$ as input that splits itself into \$fd\$f
	DiscreteFunctions that are each \$fd\$f valued.
  * \f{eqnarray*}f\rightarrow (a_{ij})_{1<=i,j<=d}\\
  * G_k= \sum_K\int_K \sum_{l=1..d}a_{kl} \phi_{l} dx\f}
  **/
template < class DiscreteFunctionType, class DiscreteGradientFunctionType >
class GradientSplitterFunction : public std::vector< boost::shared_ptr< DiscreteFunctionType > >
{
	typedef std::vector< DiscreteFunctionType >
		BaseType;
	typedef GradientSplitterFunction< DiscreteFunctionType, DiscreteGradientFunctionType >
		ThisType;
	typedef typename boost::shared_ptr< DiscreteFunctionType >
		PointerType;

public:
	GradientSplitterFunction(	const typename DiscreteFunctionType::FunctionSpaceType& space,
								const DiscreteGradientFunctionType&  gradient )
	{
		typedef typename DiscreteFunctionType::FunctionSpaceType::DomainType
			DomainType;
		const size_t dim = DomainType::dimension;
		for ( size_t d = 0; d < dim; ++d ) {
			PointerType p( new DiscreteFunctionType( (boost::format("%s_%s") % gradient.name() % Stuff::dimToAxisName(d,true) ).str(),
			                                         space ) );//never use temporary smart pointers
			push_back( p );
		}

		typedef typename DiscreteFunctionType::FunctionSpaceType
			DiscreteFunctionSpaceType;
		typedef typename DiscreteGradientFunctionType::FunctionSpaceType
			DiscreteGradientFunctionSpaceType;
		typedef typename DiscreteFunctionType::LocalFunctionType
			LocalFunctionType;
		typedef std::vector< LocalFunctionType >
			LocalFunctionVectorType;
		typedef typename DiscreteGradientFunctionType::LocalFunctionType
			LocalGradientFunctionType;
		typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
			GridPartType;
		typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
			Iterator;
		typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
			BaseFunctionSetType ;
		typedef typename GridPartType::IntersectionIteratorType
			IntersectionIteratorType;

		const GridPartType& gridPart = space.gridPart();
		// type of quadrature
		typedef Dune::CachingQuadrature<GridPartType,0> VolumeQuadratureType;
		typedef Dune::CachingQuadrature<GridPartType,1> FaceQuadratureType;
		// type of local mass matrix
		typedef Dune::LocalDGMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType> LocalMassMatrixType;

		const int quadOrd =  (2 * space.order());

		// create local mass matrix object
		LocalMassMatrixType massMatrix( space, quadOrd );

		// check whether geometry mappings are affine or not
		const bool affineMapping = massMatrix.affine();

		const Iterator endit = space.end();
		for(Iterator it = space.begin(); it != endit ; ++it)
		{
			// get entity
			const typename GridType::template Codim<0>::Entity& entity = *it;
			// get geometry
			typedef  typename GridType::template Codim<0>::Geometry
				Geometry;
			const Geometry& geo = entity.geometry();

			// get quadrature
			VolumeQuadratureType quad(entity, quadOrd);

			// get local function of destination

			// get local function of argument
			const LocalGradientFunctionType gradient_local = gradient.localFunction(entity);

			for ( size_t d = 0; d < dim; ++d ) {
				LocalFunctionType local_function = this->at(d)->localFunction( entity );

				const BaseFunctionSetType & baseset = local_function.baseFunctionSet();

				const int quadNop = quad.nop();
				const int numDofs = local_function.numDofs();

				//volume part
				for(int qP = 0; qP < quadNop ; ++qP)
				{
					const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

					const double intel = (affineMapping) ?
						quad.weight(qP): // affine case
						quad.weight(qP)* geo.integrationElement( xLocal ); // general case

					typename DiscreteFunctionSpaceType::DomainType
						xWorld = geo.global( xLocal );

					// evaluate function
					typename DiscreteGradientFunctionType::RangeType
						gradient_eval;
					gradient_local.evaluate( quad[qP], gradient_eval );

					typename DiscreteFunctionSpaceType::RangeType
					        jacobian_row;
					for ( size_t e = 0; e < dim; ++e ) {
						jacobian_row[e] = gradient_eval(d,e);
					}
					// do projection
					for(int i=0; i<numDofs; ++i)
					{
						typename DiscreteFunctionType::RangeType phi (0.0);
						baseset.evaluate(i, quad[qP], phi);
						local_function[i] += intel * ( jacobian_row * phi );
					}
				}

				// in case of non-linear mapping apply inverse
				if ( ! affineMapping )
				{
					massMatrix.applyInverse( entity, local_function );
				}
			}
		}
	}
};

	template < int dim, class RangeType, class JacobianRangeType >
	struct GradientJacobianToLaplacian : public RangeType
	{
		GradientJacobianToLaplacian( const JacobianRangeType& jacobian )
		{
			Dune::CompileTimeChecker< ( dim == 1 || dim > 3 ) > NotImplemented;
		}
	};

	template < class RangeType, class JacobianRangeType >
	struct GradientJacobianToLaplacian< 2, RangeType, JacobianRangeType>  : public RangeType
	{
		GradientJacobianToLaplacian( const JacobianRangeType& jacobian )
		{
			(*this)[0] = jacobian[0][0];
			(*this)[1] = jacobian[3][1];
		}
	};

	template < class RangeType, class JacobianRangeType >
	struct GradientJacobianToLaplacian< 3, RangeType, JacobianRangeType>  : public RangeType
	{
		GradientJacobianToLaplacian( const JacobianRangeType& jacobian )
		{
			(*this)[0] = jacobian[0][0];
			(*this)[1] = jacobian[4][1];
			(*this)[2] = jacobian[8][2];
		}
	};

	struct ProductFunctorMatrices {
		template < class R1, class R2 >
		static double call (const R1& r1,const R2& r2 ) {
			return Stuff::colonProduct( r1, r2 );
		}
	};

	struct ProductFunctorMatrixVector {
		template < class R1, class R2 >
		static double call (const R1& r1,const R2& r2 ) {
			Dune::FieldVector< double, 1 > res;
			r1.mv( r2, res ) ;
			return res[0];
		}
	};

	template <	class DiscreteVelocityFunctionType,
				class SigmaFunctionType,
				class ProductFunctor >
	class GradientAdapterFunction :
			public SigmaFunctionType
	{
		protected:
			typedef GradientAdapterFunction <	DiscreteVelocityFunctionType,
												SigmaFunctionType,
												ProductFunctor>
				ThisType;
			typedef SigmaFunctionType
				BaseType;

		public:
			GradientAdapterFunction ( const DiscreteVelocityFunctionType& velocity,
								  SigmaFunctionType& dummy,
								  int polOrd = -1 )
				: BaseType( "grad" , dummy.space())
			{
				typedef SigmaFunctionType
					DiscreteFunctionType;
				typedef typename SigmaFunctionType::DiscreteFunctionSpaceType
					DiscreteFunctionSpaceType;
				typedef typename DiscreteFunctionType::LocalFunctionType
					LocalFuncType;
				typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
					GridPartType;
				typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
					Iterator;
				typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
					BaseFunctionSetType ;
				typedef typename GridPartType::IntersectionIteratorType
					IntersectionIteratorType;
				typedef typename DiscreteVelocityFunctionType::LocalFunctionType
					LocalFType;

				const DiscreteFunctionSpaceType space ( velocity.space().gridPart() );
				const GridPartType& gridPart = space.gridPart();
				// type of quadrature
				typedef Dune::CachingQuadrature<GridPartType,0> VolumeQuadratureType;
				typedef Dune::CachingQuadrature<GridPartType,1> FaceQuadratureType;
				// type of local mass matrix
				typedef Dune::LocalDGMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType> LocalMassMatrixType;

				const int quadOrd = (polOrd == -1) ? (2 * space.order()) : polOrd;

				// create local mass matrix object
				LocalMassMatrixType massMatrix( space, quadOrd );

				// check whether geometry mappings are affine or not
				const bool affineMapping = massMatrix.affine();

				// clear destination
				BaseType::clear();

				const Iterator endit = space.end();
				for(Iterator it = space.begin(); it != endit ; ++it)
				{
					// get entity
					const typename GridType::template Codim<0>::Entity& entity = *it;
					// get geometry
					typedef  typename GridType::template Codim<0>::Geometry
						Geometry;
					const Geometry& geo = entity.geometry();

					// get quadrature
					VolumeQuadratureType quad(entity, quadOrd);

					// get local function of destination
					LocalFuncType self_local = BaseType::localFunction(entity);
					// get local function of argument
					const LocalFType velocity_local = velocity.localFunction(entity);

					// get base function set
					const BaseFunctionSetType & baseset = self_local.baseFunctionSet();

					const int quadNop = quad.nop();
					const int numDofs = self_local.numDofs();

					//volume part
					for(int qP = 0; qP < quadNop ; ++qP)
					{
						const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

						const double intel = (affineMapping) ?
							quad.weight(qP): // affine case
							quad.weight(qP)* geo.integrationElement( xLocal ); // general case

						typename DiscreteFunctionSpaceType::DomainType
							xWorld = geo.global( xLocal );

						// evaluate function
						typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::RangeType
							velocity_eval;
						velocity_local.evaluate( quad[qP], velocity_eval );

						typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::JacobianRangeType
							velocity_jacobian_eval;
						velocity_local.jacobian( quad[qP], velocity_jacobian_eval );

						// do projection
						for(int i=0; i<numDofs; ++i)
						{
							typename DiscreteFunctionType::DiscreteFunctionSpaceType::RangeType phi (0.0);
							baseset.evaluate(i, quad[qP], phi);
							self_local[i] += intel * ProductFunctor::call( velocity_jacobian_eval, phi );
						}
					}

					// in case of non-linear mapping apply inverse
					if ( ! affineMapping )
					{
						massMatrix.applyInverse( entity, self_local );
					}
				}
			}

	};

	template <	class DiscreteVelocityFunctionType,
				class SigmaFunctionType,
				class ProductFunctor >
	class LaplaceAdapterFunction :
			public DiscreteVelocityFunctionType
	{
		protected:
			typedef LaplaceAdapterFunction <	DiscreteVelocityFunctionType,
												SigmaFunctionType,
												ProductFunctor>
				ThisType;
			typedef DiscreteVelocityFunctionType
				BaseType;

		public:
			LaplaceAdapterFunction( const DiscreteVelocityFunctionType& velocity,
								  SigmaFunctionType& dummy,
								  int polOrd = -1 )
				: BaseType( "grad" , velocity.space())
			{
				GradientAdapterFunction<	DiscreteVelocityFunctionType,
											SigmaFunctionType,
											ProductFunctor>
				        gradient( velocity, dummy, polOrd );
				init( gradient, polOrd );
			}

//			LaplaceAdapterFunction( const SigmaFunctionType& gradient )
//				: BaseType( "grad" , velocity.space())
//			{
//				init( gradient, -1 );
//			}

			void init( const SigmaFunctionType& gradient, int polOrd )
			{
				typedef DiscreteVelocityFunctionType
					DiscreteFunctionType;
				typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType
					DiscreteFunctionSpaceType;
				typedef typename DiscreteFunctionType::LocalFunctionType
					LocalFuncType;
				typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
					GridPartType;
				typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
					Iterator;
				typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
					BaseFunctionSetType ;
				typedef typename GridPartType::IntersectionIteratorType
					IntersectionIteratorType;
				typedef typename SigmaFunctionType::LocalFunctionType
					LocalFType;

				const DiscreteFunctionSpaceType& space = BaseType::space();
				const GridPartType& gridPart = space.gridPart();
				// type of quadrature
				typedef Dune::CachingQuadrature<GridPartType,0> VolumeQuadratureType;
				typedef Dune::CachingQuadrature<GridPartType,1> FaceQuadratureType;
				// type of local mass matrix
				typedef Dune::LocalDGMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType> LocalMassMatrixType;

				const int quadOrd = (polOrd == -1) ? (2 * space.order()) : polOrd;

				// create local mass matrix object
				LocalMassMatrixType massMatrix( space, quadOrd );

				// check whether geometry mappings are affine or not
				const bool affineMapping = massMatrix.affine();

				// clear destination
				BaseType::clear();

				const Iterator endit = space.end();
				for(Iterator it = space.begin(); it != endit ; ++it)
				{
					// get entity
					const typename GridType::template Codim<0>::Entity& entity = *it;
					// get geometry
					typedef  typename GridType::template Codim<0>::Geometry
						Geometry;
					const Geometry& geo = entity.geometry();

					// get quadrature
					VolumeQuadratureType quad(entity, quadOrd);

					// get local function of destination
					LocalFuncType self_local = BaseType::localFunction(entity);
					// get local function of argument
					const LocalFType gradient_local = gradient.localFunction(entity);

					// get base function set
					const BaseFunctionSetType & baseset = self_local.baseFunctionSet();

					const int quadNop = quad.nop();
					const int numDofs = self_local.numDofs();

					//volume part
					for(int qP = 0; qP < quadNop ; ++qP)
					{
						const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

						const double intel = (affineMapping) ?
							quad.weight(qP): // affine case
							quad.weight(qP)* geo.integrationElement( xLocal ); // general case

						typename DiscreteFunctionSpaceType::DomainType
							xWorld = geo.global( xLocal );

						typename SigmaFunctionType::DiscreteFunctionSpaceType::JacobianRangeType
							gradient_jacobian_eval;
						gradient_local.jacobian( quad[qP], gradient_jacobian_eval );

						GradientJacobianToLaplacian<	DiscreteFunctionType::RangeType::size,
																typename DiscreteFunctionType::RangeType,
																typename SigmaFunctionType::JacobianRangeType >
								velocity_real_laplacian ( gradient_jacobian_eval );

						// do projection
						for(int i=0; i<numDofs; ++i)
						{
							typename DiscreteFunctionType::DiscreteFunctionSpaceType::RangeType phi (0.0);
							baseset.evaluate(i, quad[qP], phi);
							self_local[i] += 2 * intel * ( velocity_real_laplacian * phi );
						}
					}

					// in case of non-linear mapping apply inverse
					if ( ! affineMapping )
					{
						massMatrix.applyInverse( entity, self_local );
					}
				}
			}

	};

}

#endif // DUNE_STUFF_FUNCTIONADAPTER_HH
<|endoftext|>


<commit_before>#include <QtWidgets>

#include "GeometryWidget.hpp"

#include <Spirit/Geometry.h>

GeometryWidget::GeometryWidget(std::shared_ptr<State> state, SpinWidget * spinWidget)
{
	this->state = state;
	this->spinWidget = spinWidget;

	// Setup User Interface
    this->setupUi(this);
	// We use a regular expression (regex) to filter the input into the lineEdits
	QRegularExpression re("[+|-]?[\\d]*[\\.]?[\\d]*");
	this->number_validator = new QRegularExpressionValidator(re);
	QRegularExpression re2("[\\d]*[\\.]?[\\d]*");
	this->number_validator_unsigned = new QRegularExpressionValidator(re2);
	QRegularExpression re3("[+|-]?[\\d]*");
	this->number_validator_int = new QRegularExpressionValidator(re3);
	QRegularExpression re4("[\\d]*");
	this->number_validator_int_unsigned = new QRegularExpressionValidator(re4);
	// Setup the validators for the various input fields
	 this->Setup_Input_Validators();

	// Load variables from SpinWidget and State
	this->updateData();

	// Connect signals and slots
	 this->Setup_Slots();
}

void GeometryWidget::updateData()
{
	int n_cells[3];
	Geometry_Get_N_Cells(this->state.get(), n_cells);
	this->lineEdit_n_cells_a->setText(QString::number(n_cells[0]));
	this->lineEdit_n_cells_b->setText(QString::number(n_cells[1]));
	this->lineEdit_n_cells_c->setText(QString::number(n_cells[2]));
}

void GeometryWidget::setNCells()
{
	// Get some reference values for the position filter of SpinWidget
	auto x_range = this->spinWidget->xRangePosition();
	auto y_range = this->spinWidget->yRangePosition();
	auto z_range = this->spinWidget->zRangePosition();
	float b_min[3], b_max[3], b_range[3];
	Geometry_Get_Bounds(state.get(), b_min, b_max);
	float pc_x = x_range.y;
	float pc_y = y_range.y;
	float pc_z = z_range.y;
	if (std::abs(b_max[0]) > 0) pc_x /= b_max[0];
	if (std::abs(b_max[1]) > 0) pc_y /= b_max[1];
	if (std::abs(b_max[2]) > 0) pc_z /= b_max[2];

	// Update the geometry in the core
	int n_cells[3]{ this->lineEdit_n_cells_a->text().toInt(), this->lineEdit_n_cells_b->text().toInt(), this->lineEdit_n_cells_c->text().toInt() };
	Geometry_Set_N_Cells(this->state.get(), n_cells);

	// Update geometry and arrays in SpinWidget
	this->spinWidget->initializeGL();
	this->spinWidget->updateData();

	// Update the position filter of SpinWidget
	float b_min_new[3], b_max_new[3], b_range_new[3];
	Geometry_Get_Bounds(state.get(), b_min_new, b_max_new);
	x_range.y = pc_x * b_max_new[0];
	y_range.y = pc_y * b_max_new[1];
	z_range.y = pc_z * b_max_new[2];
	this->spinWidget->setOverallPositionRange(x_range, y_range, z_range);

	// Update all widgets
	emit updateNeeded();
}

void GeometryWidget::Setup_Input_Validators()
{
	this->lineEdit_n_cells_a->setValidator(this->number_validator_unsigned);
	this->lineEdit_n_cells_b->setValidator(this->number_validator_unsigned);
	this->lineEdit_n_cells_c->setValidator(this->number_validator_unsigned);
}

void GeometryWidget::Setup_Slots()
{
	connect(this->lineEdit_n_cells_a, SIGNAL(returnPressed()), this, SLOT(setNCells()));
	connect(this->lineEdit_n_cells_b, SIGNAL(returnPressed()), this, SLOT(setNCells()));
	connect(this->lineEdit_n_cells_c, SIGNAL(returnPressed()), this, SLOT(setNCells()));
}
<commit_msg>UI-QT: fixed a bug with geometry updates and position filter. The position filter is now correctly updated when the geometry is changed, independent of bounds being negative.<commit_after>#include <QtWidgets>

#include "GeometryWidget.hpp"

#include <Spirit/Geometry.h>

GeometryWidget::GeometryWidget(std::shared_ptr<State> state, SpinWidget * spinWidget)
{
	this->state = state;
	this->spinWidget = spinWidget;

	// Setup User Interface
    this->setupUi(this);
	// We use a regular expression (regex) to filter the input into the lineEdits
	QRegularExpression re("[+|-]?[\\d]*[\\.]?[\\d]*");
	this->number_validator = new QRegularExpressionValidator(re);
	QRegularExpression re2("[\\d]*[\\.]?[\\d]*");
	this->number_validator_unsigned = new QRegularExpressionValidator(re2);
	QRegularExpression re3("[+|-]?[\\d]*");
	this->number_validator_int = new QRegularExpressionValidator(re3);
	QRegularExpression re4("[\\d]*");
	this->number_validator_int_unsigned = new QRegularExpressionValidator(re4);
	// Setup the validators for the various input fields
	 this->Setup_Input_Validators();

	// Load variables from SpinWidget and State
	this->updateData();

	// Connect signals and slots
	 this->Setup_Slots();
}

void GeometryWidget::updateData()
{
	int n_cells[3];
	Geometry_Get_N_Cells(this->state.get(), n_cells);
	this->lineEdit_n_cells_a->setText(QString::number(n_cells[0]));
	this->lineEdit_n_cells_b->setText(QString::number(n_cells[1]));
	this->lineEdit_n_cells_c->setText(QString::number(n_cells[2]));
}

void GeometryWidget::setNCells()
{
	// Get some reference values for the position filter of SpinWidget
	auto x_range = this->spinWidget->xRangePosition();
	auto y_range = this->spinWidget->yRangePosition();
	auto z_range = this->spinWidget->zRangePosition();
	float pc_x = x_range.y - x_range.x;
	float pc_y = y_range.y - y_range.x;
	float pc_z = z_range.y - z_range.x;
	float b_min[3], b_max[3], b_range[3];
	Geometry_Get_Bounds(state.get(), b_min, b_max);
	if (std::abs(b_max[0]-b_min[0]) > 0) pc_x /= std::abs(b_max[0]-b_min[0]);
	if (std::abs(b_max[1]-b_min[1]) > 0) pc_y /= std::abs(b_max[1]-b_min[1]);
	if (std::abs(b_max[2]-b_min[2]) > 0) pc_z /= std::abs(b_max[2]-b_min[2]);

	// Update the geometry in the core
	int n_cells[3]{ this->lineEdit_n_cells_a->text().toInt(), this->lineEdit_n_cells_b->text().toInt(), this->lineEdit_n_cells_c->text().toInt() };
	Geometry_Set_N_Cells(this->state.get(), n_cells);

	// Update geometry and arrays in SpinWidget
	this->spinWidget->initializeGL();
	this->spinWidget->updateData();

	// Update the position filter of SpinWidget
	float b_min_new[3], b_max_new[3], b_range_new[3];
	Geometry_Get_Bounds(state.get(), b_min_new, b_max_new);
	x_range.x = pc_x * b_min_new[0];
	x_range.y = pc_x * b_max_new[0];
	y_range.x = pc_y * b_min_new[1];
	y_range.y = pc_y * b_max_new[1];
	z_range.x = pc_z * b_min_new[2];
	z_range.y = pc_z * b_max_new[2];
	this->spinWidget->setOverallPositionRange(x_range, y_range, z_range);

	// Update all widgets
	emit updateNeeded();
}

void GeometryWidget::Setup_Input_Validators()
{
	this->lineEdit_n_cells_a->setValidator(this->number_validator_unsigned);
	this->lineEdit_n_cells_b->setValidator(this->number_validator_unsigned);
	this->lineEdit_n_cells_c->setValidator(this->number_validator_unsigned);
}

void GeometryWidget::Setup_Slots()
{
	connect(this->lineEdit_n_cells_a, SIGNAL(returnPressed()), this, SLOT(setNCells()));
	connect(this->lineEdit_n_cells_b, SIGNAL(returnPressed()), this, SLOT(setNCells()));
	connect(this->lineEdit_n_cells_c, SIGNAL(returnPressed()), this, SLOT(setNCells()));
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../Execution/Thread.h"

#include "Sanitizer.h"
#include "Trace.h"

#include "AssertExternallySynchronizedMutex.h"

using namespace Stroika;
using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Debug;

#if qDebug
/*
 ********************************************************************************
 ****************** Debug::AssertExternallySynchronizedMutex ********************
 ********************************************************************************
 */
void AssertExternallySynchronizedMutex::lock_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        if (sharedContext->fLocks_++ == 0) {
            // If first time in, save thread-id
            sharedContext->fCurLockThread_ = this_thread::get_id ();
            if (not sharedContext->GetSharedLockEmpty_ ()) {
                // If first already shared locks - OK - so long as same thread
                Require (sharedContext->CountOfIInSharedLockThreads_ (sharedContext->fCurLockThread_) == sharedContext->GetSharedLockThreadsCount_ ());
            }
        }
        else {
            // If first already locked - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO modify (lock for write) an object which is already in use (debuglocked) in another thread");
                DbgTrace ("Original thread holding lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
        }
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_ () const noexcept
{
    SharedContext* sharedContext = _fSharedContext.get ();
    Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
    Require (sharedContext->fLocks_ > 0); // else unbalanced
    --sharedContext->fLocks_;
}

void AssertExternallySynchronizedMutex::lock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        // OK to shared lock from various threads
        // But if already locked, NOT OK (would have blocked in real impl) - if you try to shared lock from another thread while locked
        if (sharedContext->fLocks_ != 0) {
            // If first already locks - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO sharked_lock (lock for READ) an object which is already in use (debuglocked for WRITE) in another thread");
                DbgTrace ("Original thread holding (write) lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
        }
        sharedContext->AddSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        sharedContext->RemoveSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

mutex& AssertExternallySynchronizedMutex::GetSharedLockMutexThreads_ ()
{
    static mutex sMutex_; // must be out-of-line so we can have just one mutex object. Could use static member, but then trouble using
                          // AssertExternallySynchronizedMutex before main
    return sMutex_;
}
#endif
<commit_msg>cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../Execution/Thread.h"

#include "Sanitizer.h"
#include "Trace.h"

#include "AssertExternallySynchronizedMutex.h"

using namespace Stroika;
using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Debug;

#if qDebug
/*
 ********************************************************************************
 ****************** Debug::AssertExternallySynchronizedMutex ********************
 ********************************************************************************
 */
void AssertExternallySynchronizedMutex::lock_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        if (sharedContext->fLocks_++ == 0) {
            // If first time in, save thread-id
            sharedContext->fCurLockThread_ = this_thread::get_id ();
            if (not sharedContext->GetSharedLockEmpty_ ()) {
                // If first already shared locks - OK - so long as same thread
                Require (sharedContext->CountOfIInSharedLockThreads_ (sharedContext->fCurLockThread_) == sharedContext->GetSharedLockThreadsCount_ ());
            }
        }
        else {
            // If first already locked - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO modify (lock for write) an object which is already in use (debuglocked) in another thread");
                DbgTrace ("Original thread holding lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
        }
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_ () const noexcept
{
    SharedContext* sharedContext = _fSharedContext.get ();
    Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
    Require (sharedContext->fLocks_ > 0); // else unbalanced
    --sharedContext->fLocks_;
}

void AssertExternallySynchronizedMutex::lock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        // OK to shared lock from various threads
        // But if already locked, NOT OK (would have blocked in real impl) - if you try to shared lock from another thread while locked
        if (sharedContext->fLocks_ != 0) {
            // If first already locks - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO shared_lock (lock for READ) an object which is already in use (debuglocked for WRITE) in another thread");
                DbgTrace ("Original thread holding (write) lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
        }
        sharedContext->AddSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        sharedContext->RemoveSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

mutex& AssertExternallySynchronizedMutex::GetSharedLockMutexThreads_ ()
{
    static mutex sMutex_; // must be out-of-line so we can have just one mutex object. Could use static member, but then trouble using
                          // AssertExternallySynchronizedMutex before main
    return sMutex_;
}
#endif
<|endoftext|>


<commit_before>#pragma once
#include <Grappa.hpp>
#include <graph/Graph.hpp>
#include <Reducer.hpp>

GRAPPA_DECLARE_METRIC(SummarizingMetric<double>, iteration_time);
DECLARE_int32(max_iterations);

using namespace Grappa;
using delegate::call;

using Empty = struct {};

template< typename T >
struct GraphlabVertex {
  static Reducer<int64_t,ReducerType::Add> total_active;

  bool active;
  T cache;
  GraphlabVertex(): active(false), cache() {}
  void activate() {
    if (!active) {
      total_active++;
      active = true;
    }
  }
  void post_delta(T d){ cache += d; }
};
template<typename T> Reducer<int64_t,ReducerType::Add> GraphlabVertex<T>::total_active;

template< typename V, typename E >
void activate_all(GlobalAddress<Graph<V,E>> g) {
  forall(g, [](typename Graph<V,E>::Vertex& v){ v->activate(); });
}

template< typename V >
void activate(GlobalAddress<V> v) {
  delegate::call(v, [](V& v){ v->activate(); });
}

////////////////////////////////////////////////////////
/// Synchronous GraphLab engine, assumes:
/// - Delta caching enabled
/// - (currently) gather_edges:IN_EDGES, scatter_edges:(OUT_EDGES || NONE)
template< typename VertexProg, typename V, typename E >
void run_synchronous(GlobalAddress<Graph<V,E>> g) {
#define GVertex typename Graph<V,E>::Vertex
#define GEdge typename Graph<V,E>::Edge
  // using G = Graph<V,E>;
  // using GVertex = typename G::Vertex;
  // using GEdge = typename G::Edge;

  // // tack the VertexProg data onto the existing vertex data
  // struct VPlus : public V {
  //   VertexProg prog;
  //   VPlus(typename Graph<V,E>::Vertex& v): V(v.data), prog(v) {}
  // };
  // auto g = g->template transform<VPlus>([](typename Graph<V,E>::Vertex& v, VPlus& d){
  //   new (&d) VPlus(v);
  // });
  // using GPVertex = typename Graph<VPlus,E>::Vertex;
  // using GPEdge = typename Graph<VPlus,E>::Edge;

  // "gather" once to initialize cache (doing with a scatter)

  // TODO: find efficient way to skip 'gather' if 'gather_edges' is always false

  forall(g, [=](GVertex& v){
    forall<async>(adj(g,v), [&v](GEdge& e){

      VertexProg prog;

      // gather
      auto delta = prog.gather(v, e);

      call<async>(e.ga, [=](GVertex& ve){
        ve->post_delta(delta);
      });
    });
  });

  int iteration = 0;

  while ( V::total_active > 0 ) GRAPPA_TIME_REGION(iteration_time) {

    VLOG(1) << "iteration " << std::setw(3) << iteration
            << " -- active:" << V::total_active;

    V::total_active = 0; // 'apply' deactivates all vertices

    if (iteration > FLAGS_max_iterations) break;

    forall(g, [=](GVertex& v){
      if (!v->active) return;

      VertexProg prog;

      // apply
      prog.apply(v, v->cache);
      v->active = false;

      if (prog.scatter_edges(v)) {
        // scatter
        forall<async>(adj(g,v), [g,prog](GEdge& e){
          auto e_id = e.id;
          auto e_data = e.data;
          call<async>(e.ga, [g,e_id,e_data,prog](GVertex& ve){
            auto local_e_data = e_data;
            GEdge e = { e_id, g->vs+e_id, local_e_data };
            prog.scatter(e, ve);
          });
        });
      }
    });

    iteration++;
  }
}
<commit_msg>fix max_iteration loop, print time for each iteration<commit_after>#pragma once
#include <Grappa.hpp>
#include <graph/Graph.hpp>
#include <Reducer.hpp>

GRAPPA_DECLARE_METRIC(SummarizingMetric<double>, iteration_time);
DECLARE_int32(max_iterations);

using namespace Grappa;
using delegate::call;

using Empty = struct {};

template< typename T >
struct GraphlabVertex {
  static Reducer<int64_t,ReducerType::Add> total_active;

  bool active;
  T cache;
  GraphlabVertex(): active(false), cache() {}
  void activate() {
    if (!active) {
      total_active++;
      active = true;
    }
  }
  void post_delta(T d){ cache += d; }
};
template<typename T> Reducer<int64_t,ReducerType::Add> GraphlabVertex<T>::total_active;

template< typename V, typename E >
void activate_all(GlobalAddress<Graph<V,E>> g) {
  forall(g, [](typename Graph<V,E>::Vertex& v){ v->activate(); });
}

template< typename V >
void activate(GlobalAddress<V> v) {
  delegate::call(v, [](V& v){ v->activate(); });
}

////////////////////////////////////////////////////////
/// Synchronous GraphLab engine, assumes:
/// - Delta caching enabled
/// - (currently) gather_edges:IN_EDGES, scatter_edges:(OUT_EDGES || NONE)
template< typename VertexProg, typename V, typename E >
void run_synchronous(GlobalAddress<Graph<V,E>> g) {
#define GVertex typename Graph<V,E>::Vertex
#define GEdge typename Graph<V,E>::Edge
  // using G = Graph<V,E>;
  // using GVertex = typename G::Vertex;
  // using GEdge = typename G::Edge;

  // // tack the VertexProg data onto the existing vertex data
  // struct VPlus : public V {
  //   VertexProg prog;
  //   VPlus(typename Graph<V,E>::Vertex& v): V(v.data), prog(v) {}
  // };
  // auto g = g->template transform<VPlus>([](typename Graph<V,E>::Vertex& v, VPlus& d){
  //   new (&d) VPlus(v);
  // });
  // using GPVertex = typename Graph<VPlus,E>::Vertex;
  // using GPEdge = typename Graph<VPlus,E>::Edge;

  // "gather" once to initialize cache (doing with a scatter)

  // TODO: find efficient way to skip 'gather' if 'gather_edges' is always false

  forall(g, [=](GVertex& v){
    forall<async>(adj(g,v), [&v](GEdge& e){

      VertexProg prog;

      // gather
      auto delta = prog.gather(v, e);

      call<async>(e.ga, [=](GVertex& ve){
        ve->post_delta(delta);
      });
    });
  });

  int iteration = 0;

  while ( V::total_active > 0 && iteration < FLAGS_max_iterations )
      GRAPPA_TIME_REGION(iteration_time) {

    VLOG(1) << "iteration " << std::setw(3) << iteration
            << " -- active:" << V::total_active;
    double t = walltime();

    V::total_active = 0; // 'apply' deactivates all vertices

    forall(g, [=](GVertex& v){
      if (!v->active) return;

      VertexProg prog;

      // apply
      prog.apply(v, v->cache);
      v->active = false;

      if (prog.scatter_edges(v)) {
        // scatter
        forall<async>(adj(g,v), [g,prog](GEdge& e){
          auto e_id = e.id;
          auto e_data = e.data;
          call<async>(e.ga, [g,e_id,e_data,prog](GVertex& ve){
            auto local_e_data = e_data;
            GEdge e = { e_id, g->vs+e_id, local_e_data };
            prog.scatter(e, ve);
          });
        });
      }
    });

    iteration++;
    VLOG(1) << "> time: " << walltime()-t;
  }
}
<|endoftext|>


<commit_before>/// \file RNTuple.cxx
/// \ingroup NTuple ROOT7
/// \author Jakob Blomer <jblomer@cern.ch>
/// \date 2018-10-04
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <ROOT/RNTuple.hxx>

#include <ROOT/RFieldVisitor.hxx>
#include <ROOT/RNTupleModel.hxx>
#include <ROOT/RPageStorage.hxx>
#include "ROOT/RPageStorageFile.hxx"
#ifdef R__USE_IMT
#include <ROOT/TTaskGroup.hxx>
#endif

#include <TError.h>
#include <TROOT.h> // for IsImplicitMTEnabled()

#include <algorithm>
#include <exception>
#include <functional>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>

void ROOT::Experimental::RNTupleReader::ConnectModel(const RNTupleModel &model) {
   std::unordered_map<const Detail::RFieldBase *, DescriptorId_t> fieldPtr2Id;
   fieldPtr2Id[model.GetFieldZero()] = fSource->GetDescriptor().GetFieldZeroId();
   for (auto &field : *model.GetFieldZero()) {
      auto parentId = fieldPtr2Id[field.GetParent()];
      auto fieldId = fSource->GetDescriptor().FindFieldId(field.GetName(), parentId);
      R__ASSERT(fieldId != kInvalidDescriptorId);
      fieldPtr2Id[&field] = fieldId;
      Detail::RFieldFuse::Connect(fieldId, *fSource, field);
   }
}

void ROOT::Experimental::RNTupleReader::InitPageSource()
{
#ifdef R__USE_IMT
   if (IsImplicitMTEnabled()) {
      fUnzipTasks = std::make_unique<TTaskGroup>();
      fSource->SetTaskScheduleFunc([this](const std::function<void()> &task) { fUnzipTasks->Run(task); });
   }
#endif
   fSource->Attach();
   fMetrics.ObserveMetrics(fSource->GetMetrics());
}

ROOT::Experimental::RNTupleReader::RNTupleReader(
   std::unique_ptr<ROOT::Experimental::RNTupleModel> model,
   std::unique_ptr<ROOT::Experimental::Detail::RPageSource> source)
   : fSource(std::move(source))
   , fModel(std::move(model))
   , fMetrics("RNTupleReader")
{
   InitPageSource();
   ConnectModel(*fModel);
}

ROOT::Experimental::RNTupleReader::RNTupleReader(std::unique_ptr<ROOT::Experimental::Detail::RPageSource> source)
   : fSource(std::move(source))
   , fModel(nullptr)
   , fMetrics("RNTupleReader")
{
   InitPageSource();
}

ROOT::Experimental::RNTupleReader::~RNTupleReader()
{
   fSource->SetTaskScheduleFunc(Detail::RPageSource::TaskScheduleFunc_t());
}

std::unique_ptr<ROOT::Experimental::RNTupleReader> ROOT::Experimental::RNTupleReader::Open(
   std::unique_ptr<RNTupleModel> model,
   std::string_view ntupleName,
   std::string_view storage,
   const RNTupleReadOptions &options)
{
   return std::make_unique<RNTupleReader>(std::move(model), Detail::RPageSource::Create(ntupleName, storage, options));
}

std::unique_ptr<ROOT::Experimental::RNTupleReader> ROOT::Experimental::RNTupleReader::Open(
   std::string_view ntupleName,
   std::string_view storage,
   const RNTupleReadOptions &options)
{
   return std::make_unique<RNTupleReader>(Detail::RPageSource::Create(ntupleName, storage, options));
}

ROOT::Experimental::RNTupleModel *ROOT::Experimental::RNTupleReader::GetModel()
{
   if (!fModel) {
      fModel = fSource->GetDescriptor().GenerateModel();
      ConnectModel(*fModel);
   }
   return fModel.get();
}

void ROOT::Experimental::RNTupleReader::PrintInfo(const ENTupleInfo what, std::ostream &output)
{
   // TODO(lesimon): In a later version, these variables may be defined by the user or the ideal width may be read out from the terminal.
   char frameSymbol = '*';
   int width = 80;
   /*
   if (width < 30) {
      output << "The width is too small! Should be at least 30." << std::endl;
      return;
   }
   */
   std::string name = fSource->GetDescriptor().GetName();
   switch (what) {
   case ENTupleInfo::kSummary: {
      for (int i = 0; i < (width/2 + width%2 - 4); ++i)
            output << frameSymbol;
      output << " NTUPLE ";
      for (int i = 0; i < (width/2 - 4); ++i)
         output << frameSymbol;
      output << std::endl;
      // FitString defined in RFieldVisitor.cxx
      output << frameSymbol << " N-Tuple : " << RNTupleFormatter::FitString(name, width-13) << frameSymbol << std::endl; // prints line with name of ntuple
      output << frameSymbol << " Entries : " << RNTupleFormatter::FitString(std::to_string(GetNEntries()), width - 13) << frameSymbol << std::endl;  // prints line with number of entries

      // Traverses through all fields to gather information needed for printing.
      RPrepareVisitor prepVisitor;
      // Traverses through all fields to do the actual printing.
      RPrintSchemaVisitor printVisitor(output);

      // Note that we do not need to connect the model, we are only looking at its tree of fields
      auto fullModel = fSource->GetDescriptor().GenerateModel();
      fullModel->GetFieldZero()->AcceptVisitor(prepVisitor);

      printVisitor.SetFrameSymbol(frameSymbol);
      printVisitor.SetWidth(width);
      printVisitor.SetDeepestLevel(prepVisitor.GetDeepestLevel());
      printVisitor.SetNumFields(prepVisitor.GetNumFields());

      for (int i = 0; i < width; ++i)
         output << frameSymbol;
      output << std::endl;
      fullModel->GetFieldZero()->AcceptVisitor(printVisitor);
      for (int i = 0; i < width; ++i)
         output << frameSymbol;
      output << std::endl;
      break;
   }
   case ENTupleInfo::kStorageDetails:
      fSource->GetDescriptor().PrintInfo(output);
      break;
   case ENTupleInfo::kMetrics:
      fMetrics.Print(output);
      break;
   default:
      // Unhandled case, internal error
      R__ASSERT(false);
   }
}

ROOT::Experimental::RNTupleReader *ROOT::Experimental::RNTupleReader::GetDisplayReader()
{
   if (!fDisplayReader)
      fDisplayReader = Clone();
   return fDisplayReader.get();
}

void ROOT::Experimental::RNTupleReader::Show(NTupleSize_t index, const ENTupleShowFormat format, std::ostream &output)
{
   RNTupleReader *reader = this;
   REntry *entry = nullptr;
   // Don't accidentally trigger loading of the entire model
   if (fModel)
      entry = fModel->GetDefaultEntry();

   switch(format) {
   case ENTupleShowFormat::kCompleteJSON:
      reader = GetDisplayReader();
      entry = reader->GetModel()->GetDefaultEntry();
      // Fall through
   case ENTupleShowFormat::kCurrentModelJSON:
      if (!entry) {
         output << "{}" << std::endl;
         break;
      }

      reader->LoadEntry(index);
      output << "{";
      for (auto iValue = entry->begin(); iValue != entry->end(); ) {
         output << std::endl;
         RPrintValueVisitor visitor(*iValue, output, 1 /* level */);
         iValue->GetField()->AcceptVisitor(visitor);

         if (++iValue == entry->end()) {
            output << std::endl;
            break;
         } else {
            output << ",";
         }
      }
      output << "}" << std::endl;
      break;
   default:
      // Unhandled case, internal error
      R__ASSERT(false);
   }
}

//------------------------------------------------------------------------------

ROOT::Experimental::RNTupleWriter::RNTupleWriter(
   std::unique_ptr<ROOT::Experimental::RNTupleModel> model,
   std::unique_ptr<ROOT::Experimental::Detail::RPageSink> sink)
   : fSink(std::move(sink))
   , fModel(std::move(model))
   , fClusterSizeEntries(kDefaultClusterSizeEntries)
   , fLastCommitted(0)
   , fNEntries(0)
{
   fSink->Create(*fModel.get());
}

ROOT::Experimental::RNTupleWriter::~RNTupleWriter()
{
   CommitCluster();
   fSink->CommitDataset();
}

std::unique_ptr<ROOT::Experimental::RNTupleWriter> ROOT::Experimental::RNTupleWriter::Recreate(
   std::unique_ptr<RNTupleModel> model,
   std::string_view ntupleName,
   std::string_view storage,
   const RNTupleWriteOptions &options)
{
   return std::make_unique<RNTupleWriter>(std::move(model), Detail::RPageSink::Create(ntupleName, storage, options));
}

std::unique_ptr<ROOT::Experimental::RNTupleWriter> ROOT::Experimental::RNTupleWriter::Append(
   std::unique_ptr<RNTupleModel> model,
   std::string_view ntupleName,
   TFile &file,
   const RNTupleWriteOptions &options)
{
   auto sink = std::make_unique<Detail::RPageSinkFile>(ntupleName, file, options);
   return std::make_unique<RNTupleWriter>(std::move(model), std::move(sink));
}

void ROOT::Experimental::RNTupleWriter::CommitCluster()
{
   if (fNEntries == fLastCommitted) return;
   for (auto& field : *fModel->GetFieldZero()) {
      field.Flush();
      field.CommitCluster();
   }
   fSink->CommitCluster(fNEntries);
   fLastCommitted = fNEntries;
}

//------------------------------------------------------------------------------

ROOT::Experimental::RCollectionNTuple::RCollectionNTuple(std::unique_ptr<REntry> defaultEntry)
   : fOffset(0), fDefaultEntry(std::move(defaultEntry))
{
}
<commit_msg>[ntuple] Properly shut down unzip task group in RNTuple<commit_after>/// \file RNTuple.cxx
/// \ingroup NTuple ROOT7
/// \author Jakob Blomer <jblomer@cern.ch>
/// \date 2018-10-04
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <ROOT/RNTuple.hxx>

#include <ROOT/RFieldVisitor.hxx>
#include <ROOT/RNTupleModel.hxx>
#include <ROOT/RPageStorage.hxx>
#include "ROOT/RPageStorageFile.hxx"
#ifdef R__USE_IMT
#include <ROOT/TTaskGroup.hxx>
#endif

#include <TError.h>
#include <TROOT.h> // for IsImplicitMTEnabled()

#include <algorithm>
#include <exception>
#include <functional>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>

void ROOT::Experimental::RNTupleReader::ConnectModel(const RNTupleModel &model) {
   std::unordered_map<const Detail::RFieldBase *, DescriptorId_t> fieldPtr2Id;
   fieldPtr2Id[model.GetFieldZero()] = fSource->GetDescriptor().GetFieldZeroId();
   for (auto &field : *model.GetFieldZero()) {
      auto parentId = fieldPtr2Id[field.GetParent()];
      auto fieldId = fSource->GetDescriptor().FindFieldId(field.GetName(), parentId);
      R__ASSERT(fieldId != kInvalidDescriptorId);
      fieldPtr2Id[&field] = fieldId;
      Detail::RFieldFuse::Connect(fieldId, *fSource, field);
   }
}

void ROOT::Experimental::RNTupleReader::InitPageSource()
{
#ifdef R__USE_IMT
   if (IsImplicitMTEnabled()) {
      fUnzipTasks = std::make_unique<TTaskGroup>();
      fSource->SetTaskScheduleFunc([this](const std::function<void()> &task) { fUnzipTasks->Run(task); });
   }
#endif
   fSource->Attach();
   fMetrics.ObserveMetrics(fSource->GetMetrics());
}

ROOT::Experimental::RNTupleReader::RNTupleReader(
   std::unique_ptr<ROOT::Experimental::RNTupleModel> model,
   std::unique_ptr<ROOT::Experimental::Detail::RPageSource> source)
   : fSource(std::move(source))
   , fModel(std::move(model))
   , fMetrics("RNTupleReader")
{
   InitPageSource();
   ConnectModel(*fModel);
}

ROOT::Experimental::RNTupleReader::RNTupleReader(std::unique_ptr<ROOT::Experimental::Detail::RPageSource> source)
   : fSource(std::move(source))
   , fModel(nullptr)
   , fMetrics("RNTupleReader")
{
   InitPageSource();
}

ROOT::Experimental::RNTupleReader::~RNTupleReader()
{
#ifdef R__USE_IMT
   if (fUnzipTasks) {
      fUnzipTasks->Wait();
      fSource->SetTaskScheduleFunc(Detail::RPageSource::TaskScheduleFunc_t());
   }
#endif
}

std::unique_ptr<ROOT::Experimental::RNTupleReader> ROOT::Experimental::RNTupleReader::Open(
   std::unique_ptr<RNTupleModel> model,
   std::string_view ntupleName,
   std::string_view storage,
   const RNTupleReadOptions &options)
{
   return std::make_unique<RNTupleReader>(std::move(model), Detail::RPageSource::Create(ntupleName, storage, options));
}

std::unique_ptr<ROOT::Experimental::RNTupleReader> ROOT::Experimental::RNTupleReader::Open(
   std::string_view ntupleName,
   std::string_view storage,
   const RNTupleReadOptions &options)
{
   return std::make_unique<RNTupleReader>(Detail::RPageSource::Create(ntupleName, storage, options));
}

ROOT::Experimental::RNTupleModel *ROOT::Experimental::RNTupleReader::GetModel()
{
   if (!fModel) {
      fModel = fSource->GetDescriptor().GenerateModel();
      ConnectModel(*fModel);
   }
   return fModel.get();
}

void ROOT::Experimental::RNTupleReader::PrintInfo(const ENTupleInfo what, std::ostream &output)
{
   // TODO(lesimon): In a later version, these variables may be defined by the user or the ideal width may be read out from the terminal.
   char frameSymbol = '*';
   int width = 80;
   /*
   if (width < 30) {
      output << "The width is too small! Should be at least 30." << std::endl;
      return;
   }
   */
   std::string name = fSource->GetDescriptor().GetName();
   switch (what) {
   case ENTupleInfo::kSummary: {
      for (int i = 0; i < (width/2 + width%2 - 4); ++i)
            output << frameSymbol;
      output << " NTUPLE ";
      for (int i = 0; i < (width/2 - 4); ++i)
         output << frameSymbol;
      output << std::endl;
      // FitString defined in RFieldVisitor.cxx
      output << frameSymbol << " N-Tuple : " << RNTupleFormatter::FitString(name, width-13) << frameSymbol << std::endl; // prints line with name of ntuple
      output << frameSymbol << " Entries : " << RNTupleFormatter::FitString(std::to_string(GetNEntries()), width - 13) << frameSymbol << std::endl;  // prints line with number of entries

      // Traverses through all fields to gather information needed for printing.
      RPrepareVisitor prepVisitor;
      // Traverses through all fields to do the actual printing.
      RPrintSchemaVisitor printVisitor(output);

      // Note that we do not need to connect the model, we are only looking at its tree of fields
      auto fullModel = fSource->GetDescriptor().GenerateModel();
      fullModel->GetFieldZero()->AcceptVisitor(prepVisitor);

      printVisitor.SetFrameSymbol(frameSymbol);
      printVisitor.SetWidth(width);
      printVisitor.SetDeepestLevel(prepVisitor.GetDeepestLevel());
      printVisitor.SetNumFields(prepVisitor.GetNumFields());

      for (int i = 0; i < width; ++i)
         output << frameSymbol;
      output << std::endl;
      fullModel->GetFieldZero()->AcceptVisitor(printVisitor);
      for (int i = 0; i < width; ++i)
         output << frameSymbol;
      output << std::endl;
      break;
   }
   case ENTupleInfo::kStorageDetails:
      fSource->GetDescriptor().PrintInfo(output);
      break;
   case ENTupleInfo::kMetrics:
      fMetrics.Print(output);
      break;
   default:
      // Unhandled case, internal error
      R__ASSERT(false);
   }
}

ROOT::Experimental::RNTupleReader *ROOT::Experimental::RNTupleReader::GetDisplayReader()
{
   if (!fDisplayReader)
      fDisplayReader = Clone();
   return fDisplayReader.get();
}

void ROOT::Experimental::RNTupleReader::Show(NTupleSize_t index, const ENTupleShowFormat format, std::ostream &output)
{
   RNTupleReader *reader = this;
   REntry *entry = nullptr;
   // Don't accidentally trigger loading of the entire model
   if (fModel)
      entry = fModel->GetDefaultEntry();

   switch(format) {
   case ENTupleShowFormat::kCompleteJSON:
      reader = GetDisplayReader();
      entry = reader->GetModel()->GetDefaultEntry();
      // Fall through
   case ENTupleShowFormat::kCurrentModelJSON:
      if (!entry) {
         output << "{}" << std::endl;
         break;
      }

      reader->LoadEntry(index);
      output << "{";
      for (auto iValue = entry->begin(); iValue != entry->end(); ) {
         output << std::endl;
         RPrintValueVisitor visitor(*iValue, output, 1 /* level */);
         iValue->GetField()->AcceptVisitor(visitor);

         if (++iValue == entry->end()) {
            output << std::endl;
            break;
         } else {
            output << ",";
         }
      }
      output << "}" << std::endl;
      break;
   default:
      // Unhandled case, internal error
      R__ASSERT(false);
   }
}

//------------------------------------------------------------------------------

ROOT::Experimental::RNTupleWriter::RNTupleWriter(
   std::unique_ptr<ROOT::Experimental::RNTupleModel> model,
   std::unique_ptr<ROOT::Experimental::Detail::RPageSink> sink)
   : fSink(std::move(sink))
   , fModel(std::move(model))
   , fClusterSizeEntries(kDefaultClusterSizeEntries)
   , fLastCommitted(0)
   , fNEntries(0)
{
   fSink->Create(*fModel.get());
}

ROOT::Experimental::RNTupleWriter::~RNTupleWriter()
{
   CommitCluster();
   fSink->CommitDataset();
}

std::unique_ptr<ROOT::Experimental::RNTupleWriter> ROOT::Experimental::RNTupleWriter::Recreate(
   std::unique_ptr<RNTupleModel> model,
   std::string_view ntupleName,
   std::string_view storage,
   const RNTupleWriteOptions &options)
{
   return std::make_unique<RNTupleWriter>(std::move(model), Detail::RPageSink::Create(ntupleName, storage, options));
}

std::unique_ptr<ROOT::Experimental::RNTupleWriter> ROOT::Experimental::RNTupleWriter::Append(
   std::unique_ptr<RNTupleModel> model,
   std::string_view ntupleName,
   TFile &file,
   const RNTupleWriteOptions &options)
{
   auto sink = std::make_unique<Detail::RPageSinkFile>(ntupleName, file, options);
   return std::make_unique<RNTupleWriter>(std::move(model), std::move(sink));
}

void ROOT::Experimental::RNTupleWriter::CommitCluster()
{
   if (fNEntries == fLastCommitted) return;
   for (auto& field : *fModel->GetFieldZero()) {
      field.Flush();
      field.CommitCluster();
   }
   fSink->CommitCluster(fNEntries);
   fLastCommitted = fNEntries;
}

//------------------------------------------------------------------------------

ROOT::Experimental::RCollectionNTuple::RCollectionNTuple(std::unique_ptr<REntry> defaultEntry)
   : fOffset(0), fDefaultEntry(std::move(defaultEntry))
{
}
<|endoftext|>


<commit_before><commit_msg>Skip METADATA sections in VTK files<commit_after><|endoftext|>


<commit_before>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "OneDEnergyWallHeating.h"

#include "edge_edge2.h"
#include "fe_type.h"

// physics
#include "Diffusion.h"

const std::string PipeBase::_type("pipe");

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");

  std::vector<Real> zr(LIBMESH_DIM, 0.);
  params.addParam<std::vector<Real> >("offset", zr, "Offset of the origin for mesh generation");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");

  //Input parameters default values could be given.
  params.addParam<Real>("aw", 0.0, "Heating surface density");
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _offset(toPoint(getParam<std::vector<Real> >("offset"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _aw(getParam<Real>("aw")),
    _f(getParam<Real>("f")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw"))
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  p += _offset;
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);
}

std::vector<unsigned int>
PipeBase::getIDs(std::string /*piece*/)
{
  mooseError("Not implemented yet");
  return std::vector<unsigned int>();
}

std::string
PipeBase::variableName(std::string /*piece*/)
{
  mooseError("Not implemented yet");
  return std::string();
}
<commit_msg>Closes idaholab/relap-7#993<commit_after>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "OneDEnergyWallHeating.h"

#include "edge_edge2.h"
#include "fe_type.h"

// physics
#include "Diffusion.h"

const std::string PipeBase::_type("pipe");

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");

  std::vector<Real> zr(LIBMESH_DIM, 0.);
  params.addParam<std::vector<Real> >("offset", zr, "Offset of the origin for mesh generation");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");

  //Input parameters default values could be given.
  params.addParam<Real>("aw", 0.0, "Heating surface density");
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _offset(toPoint(getParam<std::vector<Real> >("offset"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _aw(getParam<Real>("aw")),
    _f(getParam<Real>("f")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw"))
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  p += _offset;
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);
}

std::vector<unsigned int>
PipeBase::getIDs(std::string part)
{
  std::vector<unsigned int> ids;

  if(part == "PIPE")
    ids.push_back(_subdomain_id);
  else
    mooseError(part + " is not a valid part of PipeBase!");

  return ids;
}

std::string
PipeBase::variableName(std::string part)
{
  if(part == "FLUID_TEMP")
    return Model::TEMPERATURE;
  else
    mooseError(part + " is not a valid part of PipeBase!");
}
<|endoftext|>