Mise à jour terminée. Pour connaître les apports de la version 13.8.4 par rapport à notre ancienne version vous pouvez lire les "Release Notes" suivantes :
https://about.gitlab.com/releases/2021/02/11/security-release-gitlab-13-8-4-released/
https://about.gitlab.com/releases/2021/02/05/gitlab-13-8-3-released/

Commit 33701cb2 authored by PIACIBELLO Cyrille's avatar PIACIBELLO Cyrille

Change to kernel constructor prototype for Chebyshev and Uniform. Changes...

Change to kernel constructor prototype for Chebyshev and Uniform. Changes propagated to all Test and UTest files (I hope)
parent c8140c4b
...@@ -45,95 +45,95 @@ class FAbstractChebKernel : public FAbstractKernels< CellClass, ContainerClass> ...@@ -45,95 +45,95 @@ class FAbstractChebKernel : public FAbstractKernels< CellClass, ContainerClass>
{ {
protected: protected:
enum {nnodes = TensorTraits<ORDER>::nnodes}; enum {nnodes = TensorTraits<ORDER>::nnodes};
typedef FChebInterpolator<ORDER> InterpolatorClass; typedef FChebInterpolator<ORDER> InterpolatorClass;
/// Needed for P2M, M2M, L2L and L2P operators /// Needed for P2M, M2M, L2L and L2P operators
const FSmartPointer<InterpolatorClass,FSmartPointerMemory> Interpolator; const FSmartPointer<InterpolatorClass,FSmartPointerMemory> Interpolator;
/// Needed for P2P operator /// Needed for P2P operator
const FSmartPointer<MatrixKernelClass,FSmartPointerMemory> MatrixKernel; const FSmartPointer<MatrixKernelClass,FSmartPointerMemory> MatrixKernel;
/// Height of the entire oct-tree /// Height of the entire oct-tree
const unsigned int TreeHeight; const unsigned int TreeHeight;
/// Corner of oct-tree box /// Corner of oct-tree box
const FPoint BoxCorner; const FPoint BoxCorner;
/// Width of oct-tree box /// Width of oct-tree box
const FReal BoxWidth; const FReal BoxWidth;
/// Width of a leaf cell box /// Width of a leaf cell box
const FReal BoxWidthLeaf; const FReal BoxWidthLeaf;
/** /**
* Compute center of leaf cell from its tree coordinate. * Compute center of leaf cell from its tree coordinate.
* @param[in] Coordinate tree coordinate * @param[in] Coordinate tree coordinate
* @return center of leaf cell * @return center of leaf cell
*/ */
const FPoint getLeafCellCenter(const FTreeCoordinate& Coordinate) const const FPoint getLeafCellCenter(const FTreeCoordinate& Coordinate) const
{ {
return FPoint(BoxCorner.getX() + (FReal(Coordinate.getX()) + FReal(.5)) * BoxWidthLeaf, return FPoint(BoxCorner.getX() + (FReal(Coordinate.getX()) + FReal(.5)) * BoxWidthLeaf,
BoxCorner.getY() + (FReal(Coordinate.getY()) + FReal(.5)) * BoxWidthLeaf, BoxCorner.getY() + (FReal(Coordinate.getY()) + FReal(.5)) * BoxWidthLeaf,
BoxCorner.getZ() + (FReal(Coordinate.getZ()) + FReal(.5)) * BoxWidthLeaf); BoxCorner.getZ() + (FReal(Coordinate.getZ()) + FReal(.5)) * BoxWidthLeaf);
} }
public: public:
/** /**
* The constructor initializes all constant attributes and it reads the * The constructor initializes all constant attributes and it reads the
* precomputed and compressed M2L operators from a binary file (an * precomputed and compressed M2L operators from a binary file (an
* runtime_error is thrown if the required file is not valid). * runtime_error is thrown if the required file is not valid).
*/ */
FAbstractChebKernel(const int inTreeHeight, FAbstractChebKernel(const int inTreeHeight,
const FPoint& inBoxCenter, const FReal inBoxWidth,
const FReal inBoxWidth) const FPoint& inBoxCenter)
: Interpolator(new InterpolatorClass()), : Interpolator(new InterpolatorClass()),
MatrixKernel(new MatrixKernelClass()), MatrixKernel(new MatrixKernelClass()),
TreeHeight(inTreeHeight), TreeHeight(inTreeHeight),
BoxCorner(inBoxCenter - inBoxWidth / FReal(2.)), BoxCorner(inBoxCenter - inBoxWidth / FReal(2.)),
BoxWidth(inBoxWidth), BoxWidth(inBoxWidth),
BoxWidthLeaf(BoxWidth / FReal(FMath::pow(2, inTreeHeight - 1))) BoxWidthLeaf(BoxWidth / FReal(FMath::pow(2, inTreeHeight - 1)))
{ {
/* empty */ /* empty */
} }
virtual ~FAbstractChebKernel(){ virtual ~FAbstractChebKernel(){
// should not be used // should not be used
} }
const InterpolatorClass *const getPtrToInterpolator() const const InterpolatorClass *const getPtrToInterpolator() const
{ return Interpolator.getPtr(); } { return Interpolator.getPtr(); }
virtual void P2M(CellClass* const LeafCell, virtual void P2M(CellClass* const LeafCell,
const ContainerClass* const SourceParticles) = 0; const ContainerClass* const SourceParticles) = 0;
virtual void M2M(CellClass* const FRestrict ParentCell, virtual void M2M(CellClass* const FRestrict ParentCell,
const CellClass*const FRestrict *const FRestrict ChildCells, const CellClass*const FRestrict *const FRestrict ChildCells,
const int TreeLevel) = 0; const int TreeLevel) = 0;
virtual void M2L(CellClass* const FRestrict TargetCell, virtual void M2L(CellClass* const FRestrict TargetCell,
const CellClass* SourceCells[343], const CellClass* SourceCells[343],
const int NumSourceCells, const int NumSourceCells,
const int TreeLevel) = 0; const int TreeLevel) = 0;
virtual void L2L(const CellClass* const FRestrict ParentCell, virtual void L2L(const CellClass* const FRestrict ParentCell,
CellClass* FRestrict *const FRestrict ChildCells, CellClass* FRestrict *const FRestrict ChildCells,
const int TreeLevel) = 0; const int TreeLevel) = 0;
virtual void L2P(const CellClass* const LeafCell, virtual void L2P(const CellClass* const LeafCell,
ContainerClass* const TargetParticles) = 0; ContainerClass* const TargetParticles) = 0;
virtual void P2P(const FTreeCoordinate& /* LeafCellCoordinate */, // needed for periodic boundary conditions virtual void P2P(const FTreeCoordinate& /* LeafCellCoordinate */, // needed for periodic boundary conditions
ContainerClass* const FRestrict TargetParticles, ContainerClass* const FRestrict TargetParticles,
const ContainerClass* const FRestrict /*SourceParticles*/, const ContainerClass* const FRestrict /*SourceParticles*/,
ContainerClass* const NeighborSourceParticles[27], ContainerClass* const NeighborSourceParticles[27],
const int /* size */) = 0; const int /* size */) = 0;
virtual void P2PRemote(const FTreeCoordinate& /*inPosition*/, virtual void P2PRemote(const FTreeCoordinate& /*inPosition*/,
ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict /*inSources*/, ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict /*inSources*/,
ContainerClass* const inNeighbors[27], const int /*inSize*/) = 0; ContainerClass* const inNeighbors[27], const int /*inSize*/) = 0;
}; };
......
...@@ -105,9 +105,9 @@ public: ...@@ -105,9 +105,9 @@ public:
* runtime_error is thrown if the required file is not valid). * runtime_error is thrown if the required file is not valid).
*/ */
FChebFlopsSymKernel(const int _inTreeHeight, FChebFlopsSymKernel(const int _inTreeHeight,
const FPoint& inBoxCenter, const FReal inBoxWidth,
const FReal inBoxWidth, const FPoint& inBoxCenter,
const FReal Epsilon) const FReal Epsilon)
: MatrixKernel(new MatrixKernelClass()), : MatrixKernel(new MatrixKernelClass()),
SymHandler(new SymmetryHandler(MatrixKernel.getPtr(), Epsilon)), inTreeHeight(_inTreeHeight), SymHandler(new SymmetryHandler(MatrixKernel.getPtr(), Epsilon)), inTreeHeight(_inTreeHeight),
flopsP2M(0), flopsM2M(0), flopsM2L(0), flopsL2L(0), flopsL2P(0), flopsP2P(0), flopsP2M(0), flopsM2M(0), flopsM2L(0), flopsL2L(0), flopsL2P(0), flopsP2P(0),
......
...@@ -61,13 +61,13 @@ public: ...@@ -61,13 +61,13 @@ public:
* runtime_error is thrown if the required file is not valid). * runtime_error is thrown if the required file is not valid).
*/ */
FChebKernel(const int inTreeHeight, FChebKernel(const int inTreeHeight,
const FPoint& inBoxCenter, const FReal inBoxWidth,
const FReal inBoxWidth, const FPoint& inBoxCenter,
const FReal Epsilon) const FReal Epsilon)
: FAbstractChebKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER, NVALS>(inTreeHeight, : FAbstractChebKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER, NVALS>(inTreeHeight,
inBoxCenter, inBoxWidth,
inBoxWidth), inBoxCenter),
M2LHandler(new M2LHandlerClass(Epsilon)) M2LHandler(new M2LHandlerClass(Epsilon))
{ {
// read precomputed compressed m2l operators from binary file // read precomputed compressed m2l operators from binary file
//M2LHandler->ReadFromBinaryFileAndSet(); //M2LHandler->ReadFromBinaryFileAndSet();
......
...@@ -107,10 +107,10 @@ public: ...@@ -107,10 +107,10 @@ public:
* runtime_error is thrown if the required file is not valid). * runtime_error is thrown if the required file is not valid).
*/ */
FChebSymKernel(const int inTreeHeight, FChebSymKernel(const int inTreeHeight,
const FPoint& inBoxCenter, const FReal inBoxWidth,
const FReal inBoxWidth, const FPoint& inBoxCenter,
const FReal Epsilon) const FReal Epsilon)
: AbstractBaseClass(inTreeHeight, inBoxCenter, inBoxWidth), : AbstractBaseClass(inTreeHeight, inBoxWidth, inBoxCenter),
SymHandler(new SymmetryHandlerClass(AbstractBaseClass::MatrixKernel.getPtr(), Epsilon, inBoxWidth, inTreeHeight)), SymHandler(new SymmetryHandlerClass(AbstractBaseClass::MatrixKernel.getPtr(), Epsilon, inBoxWidth, inTreeHeight)),
Loc(NULL), Mul(NULL), countExp(NULL) Loc(NULL), Mul(NULL), countExp(NULL)
{ {
......
...@@ -79,8 +79,8 @@ public: ...@@ -79,8 +79,8 @@ public:
* runtime_error is thrown if the required file is not valid). * runtime_error is thrown if the required file is not valid).
*/ */
FAbstractUnifKernel(const int inTreeHeight, FAbstractUnifKernel(const int inTreeHeight,
const FPoint& inBoxCenter, const FReal inBoxWidth,
const FReal inBoxWidth) const FPoint& inBoxCenter)
: Interpolator(new InterpolatorClass()), : Interpolator(new InterpolatorClass()),
MatrixKernel(new MatrixKernelClass()), MatrixKernel(new MatrixKernelClass()),
TreeHeight(inTreeHeight), TreeHeight(inTreeHeight),
......
...@@ -61,11 +61,11 @@ public: ...@@ -61,11 +61,11 @@ public:
* runtime_error is thrown if the required file is not valid). * runtime_error is thrown if the required file is not valid).
*/ */
FUnifKernel(const int inTreeHeight, FUnifKernel(const int inTreeHeight,
const FPoint& inBoxCenter, const FReal inBoxWidth,
const FReal inBoxWidth) const FPoint& inBoxCenter)
: FAbstractUnifKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER, NVALS>(inTreeHeight, : FAbstractUnifKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER, NVALS>(inTreeHeight,
inBoxCenter, inBoxWidth,
inBoxWidth), inBoxCenter),
M2LHandler(new M2LHandlerClass()) M2LHandler(new M2LHandlerClass())
{ {
// read precomputed compressed m2l operators from binary file // read precomputed compressed m2l operators from binary file
......
...@@ -158,7 +158,7 @@ int main(int argc, char* argv[]) ...@@ -158,7 +158,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ",EPS="<< epsilon <<") ... " << std::endl; std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ",EPS="<< epsilon <<") ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
FmmClass algorithm(&tree, &kernels); FmmClass algorithm(&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
......
...@@ -134,7 +134,7 @@ int main(int argc, char* argv[]) ...@@ -134,7 +134,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ",EPS="<< epsilon <<") ... " << std::endl; std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ",EPS="<< epsilon <<") ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
FmmClass algorithm(app.global(),&tree, &kernels); FmmClass algorithm(app.global(),&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
......
...@@ -153,7 +153,7 @@ int main(int argc, char* argv[]) ...@@ -153,7 +153,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nChebyshev FMM ... " << std::endl; std::cout << "\nChebyshev FMM ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
FmmClass algorithm(&tree, &kernels); FmmClass algorithm(&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
......
...@@ -97,7 +97,7 @@ int main(int argc, char* argv[]) ...@@ -97,7 +97,7 @@ int main(int argc, char* argv[])
// ----------------------------------------------------- // -----------------------------------------------------
std::cout << "\nChebyshev FMM ... " << std::endl; std::cout << "\nChebyshev FMM ... " << std::endl;
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(TreeHeight, loader.getBoxWidth(),loader.getCenterOfBox(), epsilon);
FmmClass algorithm(&tree,&kernels); FmmClass algorithm(&tree,&kernels);
time.tic(); time.tic();
algorithm.execute(); algorithm.execute();
......
...@@ -152,7 +152,7 @@ int main(int argc, char* argv[]) ...@@ -152,7 +152,7 @@ int main(int argc, char* argv[])
typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass;
typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
// typedef FChebKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; // typedef FChebKernDel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass;
...@@ -178,7 +178,7 @@ int main(int argc, char* argv[]) ...@@ -178,7 +178,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nChebyshev FMM ... " << std::endl; std::cout << "\nChebyshev FMM ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
FmmClass algorithm(&tree, &kernels); FmmClass algorithm(&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
...@@ -333,7 +333,7 @@ int main(int argc, char* argv[]) ...@@ -333,7 +333,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nLagrange FMM ... " << std::endl; std::cout << "\nLagrange FMM ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth()); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox());
FmmClass algorithm(&tree, &kernels); FmmClass algorithm(&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
......
...@@ -158,7 +158,7 @@ int main(int argc, char ** argv){ ...@@ -158,7 +158,7 @@ int main(int argc, char ** argv){
#ifndef ScalFMM_USE_BLAS #ifndef ScalFMM_USE_BLAS
KernelClass kernels( DevP, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox()); KernelClass kernels( DevP, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox());
#else #else
KernelClass kernels( NbLevels, loader.getCenterOfBox(), loader.getBoxWidth(),epsilon); KernelClass kernels( NbLevels, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
#endif #endif
FmmClassNoPer algo(&tree,&kernels); FmmClassNoPer algo(&tree,&kernels);
algo.execute(); algo.execute();
...@@ -170,7 +170,7 @@ int main(int argc, char ** argv){ ...@@ -170,7 +170,7 @@ int main(int argc, char ** argv){
KernelClass kernels( DevP, algo.extendedTreeHeight(), algo.extendedBoxWidth(),algo.extendedBoxCenter()); KernelClass kernels( DevP, algo.extendedTreeHeight(), algo.extendedBoxWidth(),algo.extendedBoxCenter());
// KernelClass kernels( DevP, algo.extendedTreeHeight(), algo.extendedBoxWidth(),algo.extendedBoxCenter()); // KernelClass kernels( DevP, algo.extendedTreeHeight(), algo.extendedBoxWidth(),algo.extendedBoxCenter());
#else #else
KernelClass kernels(algo.extendedTreeHeight(), algo.extendedBoxCenter(), algo.extendedBoxWidth(),epsilon); KernelClass kernels(algo.extendedTreeHeight(), algo.extendedBoxWidth(),algo.extendedBoxCenter(), epsilon);
#endif #endif
algo.setKernel(&kernels); algo.setKernel(&kernels);
algo.execute(); algo.execute();
......
...@@ -156,7 +156,7 @@ int main(int argc, char* argv[]) ...@@ -156,7 +156,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nLagrange/Uniform grid FMM (ORDER="<< ORDER << ") ... " << std::endl; std::cout << "\nLagrange/Uniform grid FMM (ORDER="<< ORDER << ") ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth()); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox());
FmmClass algorithm(&tree, &kernels); FmmClass algorithm(&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
......
...@@ -133,7 +133,7 @@ int main(int argc, char* argv[]) ...@@ -133,7 +133,7 @@ int main(int argc, char* argv[])
{ // ----------------------------------------------------- { // -----------------------------------------------------
std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ",EPS="<< epsilon <<") ... " << std::endl; std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ",EPS="<< epsilon <<") ... " << std::endl;
time.tic(); time.tic();
KernelClass kernels(TreeHeight, loader.getCenterOfBox(), loader.getBoxWidth()); KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox());
FmmClass algorithm(app.global(),&tree, &kernels); FmmClass algorithm(app.global(),&tree, &kernels);
algorithm.execute(); algorithm.execute();
time.tac(); time.tac();
......
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include <stdlib.h> #include <stdlib.h>
// include for libfftw3 // include for libfftw3
//#include <fftw3.h> #include <fftw3.h>
// include for mkl_fftw3 // include for mkl_fftw3
#include <fftw/fftw3.h> //#include <fftw/fftw3.h>
#include "../../Src/Utils/FGlobal.hpp" #include "../../Src/Utils/FGlobal.hpp"
#include "../../Src/Utils/FComplexe.hpp" #include "../../Src/Utils/FComplexe.hpp"
......
...@@ -105,7 +105,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { ...@@ -105,7 +105,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> {
// Run FMM // Run FMM
Print("Fmm..."); Print("Fmm...");
KernelClass kernels(NbLevels, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
FmmClass algo(&tree,&kernels); FmmClass algo(&tree,&kernels);
algo.execute(); algo.execute();
......
...@@ -96,8 +96,8 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { ...@@ -96,8 +96,8 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> {
// Run FMM // Run FMM
Print("Fmm..."); Print("Fmm...");
FmmClass algo(&tree,PeriodicDeep ); FmmClass algo(&tree,PeriodicDeep );
KernelClass kernels(algo.extendedTreeHeight(), algo.extendedBoxCenter(), KernelClass kernels(algo.extendedTreeHeight(), algo.extendedBoxWidth(),
algo.extendedBoxWidth(), epsilon); algo.extendedBoxCenter(), epsilon);
algo.setKernel(&kernels); algo.setKernel(&kernels);
algo.execute(); algo.execute();
......
...@@ -105,7 +105,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { ...@@ -105,7 +105,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> {
// Run FMM // Run FMM
Print("Fmm..."); Print("Fmm...");
KernelClass kernels(NbLevels, loader.getCenterOfBox(), loader.getBoxWidth(), epsilon); KernelClass kernels(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox(), epsilon);
FmmClass algo(&tree,&kernels); FmmClass algo(&tree,&kernels);
algo.execute(); algo.execute();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment