Mentions légales du service

Skip to content
Snippets Groups Projects
FAdaptTools.hpp 10.52 KiB
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Brenger Bramas
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
#ifndef FADAPTTOOLS_HPP
#define FADAPTTOOLS_HPP

#include <fstream>

#include "Containers/FOctree.hpp"
//#include "Components/FSimpleLeaf.hpp"
#include "Components/FBasicParticleContainer.hpp"

#include "AdaptiveTree/FAdaptCell.hpp"

//!  \fn   adaptiveTreeBuilSminC(OctreeClass  & tree) {


//! \brief Build father and child lists

//! \param tree Octree
//! \param sminM Criteria to use P2M rather M2M
//! \param sminL ??
//!
template  <class OctreeClass >
void   adaptiveTreeBuilSminC(OctreeClass & tree,const int sminM, const int sminL) {
	//
	typename OctreeClass::Iterator octreeIterator(&tree) ;
	int NbLevels = tree.getHeight();

	int  nbPart ;
	//
	octreeIterator.gotoBottomLeft();
	// Set s on the cells at leave level
	//
	//  Build SMIN criteria
	//
	do{  // leaves level = NbLevels - 1
		nbPart = octreeIterator.getCurrentListTargets()->getNbParticles() ;
		octreeIterator.getCurrentCell()->addPart(nbPart);
		octreeIterator.getCurrentCell()->setCelladaptive();
		if(nbPart <= sminM){
			octreeIterator.getCurrentCell()->setSminMCriteria();
		}
	}while(octreeIterator.moveRight());
	//
	octreeIterator.moveUp();
	octreeIterator.gotoLeft();
	//
	for(int idxLevel = NbLevels - 2 ; idxLevel >= 1 ; --idxLevel){
		int nbChildForMyCell;
		//
		do{
			// Check number of
			nbChildForMyCell=0 ;
			auto ** child      = octreeIterator.getCurrentChild();
			auto  &  myCell = *(octreeIterator.getCurrentCell());
			nbPart = 0 ; nbChildForMyCell =0;
			//						std::cout << "NB: ";
			for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
				if(child[idxChild]) {
					++nbChildForMyCell;
					nbPart += child[idxChild]->getnbPart();
					//								std::cout << "  "<< child[idxChild]->getnbPart();
				}
			}
			//						std::cout << std::endl;
			myCell.addPart(nbPart);
			if(nbChildForMyCell>1) {
				myCell.setCelladaptive(); ;
			}
			if(nbPart <= sminM){
				myCell.setSminMCriteria();
			}
		} while(octreeIterator.moveRight());
		//
		//  Go to next level
		octreeIterator.moveUp();
		octreeIterator.gotoLeft();
	}

}
//!  \fn   adaptiveTreeBuildLists(OctreeClass & tree) {


//! \brief Build father and child lists

//! \param tree Octree
//!
template  <class OctreeClass >
void   adaptiveTreeBuildLists(OctreeClass & tree) {
	//
	typename OctreeClass::Iterator octreeIterator(&tree) ;
	//
	int NbLevels = tree.getHeight();
	//
	octreeIterator.gotoBottomLeft();
	//
	// Add leaf pointer on cells at the leaves level
	do {
		octreeIterator.getCurrentCell()->addLeafptr(octreeIterator.getCurrentLeaf ()   ) ;
	}while(octreeIterator.moveRight());
	octreeIterator.gotoLeft();
	//
	for(int idxLevel = NbLevels ; idxLevel > 1 ; --idxLevel){
		//		std::cout << "idxLevel "<< idxLevel <<std::endl;
		do {
			//		FAdaptCell  &  myCell = *(octreeIterator.getCurrentCell());
			auto  &  myCell = *(octreeIterator.getCurrentCell());
			//			std::cout  << "     My ID "<< myCell.getGlobalId()
			//							<< "  isAdapt ? " << std::boolalpha<<myCell.isadaptive()<<  std::endl ;
			//
			typename OctreeClass::Iterator findParent(octreeIterator);
			// std::cout <<  "      Same cell  parent iterator "<< findParent.getCurrentCell()->getGlobalId() <<  std::endl ;
			while(findParent.moveUp() ) {
				// std::cout << "           Level " <<octreeIterator.level() <<std::endl;
				// std::cout << "              Check  cell (id, level, isAdap)  " <<  findParent.getCurrentCell()->getGlobalId()
				//				<< "    " <<findParent.level()  <<   "   "<< std::boolalpha<< findParent.getCurrentCell()->isadaptive()  <<  std::endl ;
				if ( findParent.getCurrentCell()->isadaptive() ){
					//
					//							std::cout << "                         I found " <<std::endl;
					myCell.addadaptiveParent(findParent.getCurrentCell(), findParent.level()) ;
					//					std::cout <<  "       FA      "  << findParent.getCurrentCell()->getGlobalId() << "  Level " << findParent.level()<< std::endl;

					if(myCell.isadaptive()){
						findParent.getCurrentCell()->addadaptiveChild(&myCell,idxLevel) ;
						//						std::cout <<  "       CA       "  << myCell <<std::endl;
					}
					break ;
				}
			}

		}while(octreeIterator.moveRight());
		//
		// Add links to leaves if needed
		//
		if (idxLevel != NbLevels) {
			octreeIterator.gotoLeft();
			do {
				if(octreeIterator.getCurrentCell()->isSminMCriteria() ){
					auto** child = octreeIterator.getCurrentChild();
					for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
						if(child[idxChild] ) {
							for(int i = 0 ; i < child[idxChild]->getLeavesSize()  ; ++i){
								octreeIterator.getCurrentCell()->addLeafptr(child[idxChild]->getLeaf(i)   ) ;
							}
						}
					}
				}
			}while(octreeIterator.moveRight());

		}
		//
		//  Go to next level
		octreeIterator.moveUp();
		octreeIterator.gotoLeft();
	}
};
/////////////////////////////////////////////////////////////////////////////////////////
//!  \fn   setGlobalID(FOctree< FAdaptCell,  FBasicParticleContainer<0> ,  FSimpleLeaf< FBasicParticleContainer<0>> >  & tree) {
/////////////////////////////////////////////////////////////////////////////////////////


//! \brief Set a unique global Id to all cells into the octree

//! \param tree Octree
//! \return Return the total number of cells in the octree (including the leaves level.)
//template  <class Container, class Leaf >
template  <class OctreeClass >
long int  setGlobalID(OctreeClass  & tree) {
	//
	typename OctreeClass::Iterator octreeIterator(&tree) ;
	//
	//  Set Global id
	//
	int NbLevels = tree.getHeight();
	//
	octreeIterator.gotoTop() ;
	long int idCell =1 ;
	for(int idxLevel = 1 ; idxLevel < NbLevels ;  ++idxLevel){
		do{
			++idCell ;
			octreeIterator.getCurrentCell()->setGlobalId(idCell);
		} while(octreeIterator.moveRight());
		octreeIterator.moveDown() ;
		octreeIterator.gotoLeft();
	}
	octreeIterator.gotoLeft();
	do{
		long int id = octreeIterator.getCurrentCell()->getGlobalId();
		octreeIterator.getCurrentLeaf()->setIndex(id) ;
	} while(octreeIterator.moveRight());

	return idCell;
} ;
//! \brief export octree in Tulip format

//! \param nbCell number of cells (including the leaves level)
//!
template  <class OctreeClass >
void  TulipExport( std::ofstream& tlp, long int nbCell, OctreeClass & tree) {
	//
	tlp << "(tlp \"2.0\" "<< std::endl
			<< "(date \"04-11-2014\") "<< std::endl
			<< "(comments \"Octree \")"<< std::endl
			<<"(nodes ";

	int NbLevels = tree.getHeight();
	typename OctreeClass::Iterator octreeIterator(&tree) ;

	//
	for(int i = 1 ; i <= nbCell ;  ++i){
		tlp << "  " << i ;
	}
	tlp << " )" << std::endl
			<< ";(edge <edge_id> <source_id> <target_id>)" <<std ::endl;
	int edge = 0 ;
	// edge with the root
	octreeIterator.gotoTop() ;
	bool isadaptiveRoot = false;
	// Build edges between root and its child.
	do{
		++edge ;
		tlp <<"(edge " << edge << " 1 " <<octreeIterator.getCurrentCell()->getGlobalId() << " )" <<std::endl;
	} while(octreeIterator.moveRight());
	if (edge > 1) {isadaptiveRoot=true;}
	// End  for level 0
	//
	// Level 1 return to write
	octreeIterator.gotoLeft();
	for(int idxLevel = 1 ; idxLevel < NbLevels-1 ;  ++idxLevel){
		do{
			long int  myId= octreeIterator.getCurrentCell()->getGlobalId();

			auto** child = octreeIterator.getCurrentChild();
			//						std::cout << "NB: ";
			for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
				if(child[idxChild]) {
					++edge  ;
					tlp <<"(edge " << edge << "  " << myId << "  "  << child[idxChild]->getGlobalId() << " )" <<std::endl;
				}
			}
		} while(octreeIterator.moveRight());
		octreeIterator.moveDown() ;
		octreeIterator.gotoLeft();
	}
	//
	// Set adaptive property
	//
	std::string rootColor("  \"(255,0,0,255)\" ") ;      // Bleu
	std::string adaptiveColor("  \"(0,0,255,255)\" ") ;      // Bleu
	std::string defaultEdgeColor("  \"(255,191,0,255)\" ") ;
	std::string defaultNodeColor("  \"(0,0,0,255)\" ") ;    // Black
	std::string leafColor("  \"( 0,255,0,255)\" ") ;
	tlp << "(property  0 color \"viewColor\" " <<std::endl
			<< "(default " << defaultNodeColor <<defaultEdgeColor << "  ) " << std::endl ;
	octreeIterator.gotoTop() ;
	if (isadaptiveRoot) {
		tlp << "  (node 1 "  <<rootColor<<"  )" << std::endl ;
	}
	for(int idxLevel = 1 ; idxLevel < NbLevels-1 ;  ++idxLevel){
		do{
			if(octreeIterator.getCurrentCell()->isadaptive()){
				tlp << "  (node " <<  octreeIterator.getCurrentCell()->getGlobalId()   <<adaptiveColor<<"  )" << std::endl ;;
			}
		} while(octreeIterator.moveRight());
		octreeIterator.moveDown() ;
		octreeIterator.gotoLeft();
	}
	//	Set leaf color
	std::cout  << "  Iterator Level    " << octreeIterator.level()<<  "  is leaves level: " << octreeIterator.isAtLeafLevel()	<<std::endl;

	do{
		tlp << "  (node " <<  octreeIterator.getCurrentCell()->getGlobalId()   <<leafColor<<"  )" << std::endl ;;
	} while(octreeIterator.moveRight());
	tlp << ")" << std::endl;

	//
	// Set P2M property
	//
	std::cout <<std::endl<< "   TULIP OUTPUT PROPERTY P2M "<<std::endl<<std::endl;
	tlp << "(property  0 bool \"P2M\" " <<std::endl
			<< "(default \"false\" \"false\"  ) " << std::endl ;
	octreeIterator.gotoBottomLeft();		octreeIterator.moveUp() ;
	bool endProp = true;
	int elt =0;
	for(int idxLevel =  NbLevels-2 ; idxLevel >=1 ;  --idxLevel){
		endProp = true ;
		std::cout << " TLP " << idxLevel << "   " << octreeIterator.level() << "  "  << elt << std::endl;
		do{
			auto ** child      = octreeIterator.getCurrentChild();
			for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
				if(child[idxChild]) {
					if(child[idxChild]->isSminMCriteria()){
						endProp = false ; ++elt;
						tlp << "  (node " <<  child[idxChild]->getGlobalId()   <<"  \"" <<std::boolalpha <<child[idxChild]->isSminMCriteria()<<"\"  )" << std::endl ;;
					}
				}
			}
		} while(octreeIterator.moveRight());
		if(endProp){
			break ; // all upper levels are with smin > sminM
		}
		octreeIterator.gotoLeft();
		octreeIterator.moveUp() ;
	}
	if(elt != 0)
	{tlp << ")" << std::endl;}


	// END TLP FILE
	tlp << ")" << std::endl;
};
#endif