mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-04 05:54:32 +00:00 
			
		
		
		
	Started a tidy up in the HMC sector. Now comfortable with the two level integrators;
to a little figure out what Guido had done & why -- but there is a neat saving of force evaluations across the nesting time boundary making use of linearity of the leapP in dt. I cleaned up the printing, reduced the volume of code, in the process sharing printing between all integrators. Placed an assert that the total integration time for all integrators must match at end of trajectory. Have now verified e-dH = 1 for nested integrators in Wilson/Wilson runs with both Omelyan and with Leapfrog so substantial confidence gained.
This commit is contained in:
		@@ -42,7 +42,6 @@ namespace Grid{
 | 
			
		||||
      Nexp(Nexp_),MDsteps(MDsteps_),trajL(trajL_),stepsize(trajL/MDsteps){};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    namespace MDutils{
 | 
			
		||||
      void generate_momenta(LatticeGaugeField&,GridParallelRNG&);
 | 
			
		||||
      void generate_momenta_su3(LatticeGaugeField&,GridParallelRNG&);
 | 
			
		||||
@@ -52,23 +51,34 @@ namespace Grid{
 | 
			
		||||
    template< class IntegratorAlgorithm >
 | 
			
		||||
    class Integrator{
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
      int levels;
 | 
			
		||||
      std::vector<double> t_P;
 | 
			
		||||
      double t_U;
 | 
			
		||||
 | 
			
		||||
      IntegratorParameters Params;
 | 
			
		||||
      const ActionSet as;
 | 
			
		||||
      std::unique_ptr<LatticeGaugeField> P;
 | 
			
		||||
      GridParallelRNG pRNG;
 | 
			
		||||
 | 
			
		||||
      //ObserverList observers; // not yet
 | 
			
		||||
     
 | 
			
		||||
      IntegratorAlgorithm TheIntegrator;
 | 
			
		||||
 | 
			
		||||
      void register_observers();
 | 
			
		||||
 | 
			
		||||
      void notify_observers();
 | 
			
		||||
 | 
			
		||||
      void update_P(LatticeGaugeField&U, int level,double ep){
 | 
			
		||||
	t_P[level]+=ep;
 | 
			
		||||
	for(int a=0; a<as[level].actions.size(); ++a){
 | 
			
		||||
	  LatticeGaugeField force(U._grid);
 | 
			
		||||
	  as[level].actions.at(a)->deriv(U,force);
 | 
			
		||||
	  *P -= force*ep;
 | 
			
		||||
	}
 | 
			
		||||
	std::cout<<GridLogMessage;
 | 
			
		||||
	for(int l=0; l<level;++l) std::cout<<"   ";	    
 | 
			
		||||
	std::cout<<"["<<level<<"] P " << " dt "<< ep <<" : t_P "<< t_P[level] <<std::endl;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void update_U(LatticeGaugeField&U, double ep){
 | 
			
		||||
@@ -81,18 +91,34 @@ namespace Grid{
 | 
			
		||||
	  Umu = expMat(Pmu, ep, Params.Nexp)*Umu;
 | 
			
		||||
	  PokeIndex<LorentzIndex>(U, Umu, mu);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t_U+=ep;
 | 
			
		||||
	int fl = levels-1;
 | 
			
		||||
	std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	for(int l=0; l<fl;++l) std::cout<<"   ";	    
 | 
			
		||||
	std::cout<<"["<<fl<<"] U " << " dt "<< ep <<" : t_U "<< t_U <<std::endl;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      
 | 
			
		||||
      friend void IntegratorAlgorithm::step (LatticeGaugeField& U, 
 | 
			
		||||
					     int level, std::vector<int>& clock,
 | 
			
		||||
					     Integrator<IntegratorAlgorithm>* Integ);
 | 
			
		||||
    public:
 | 
			
		||||
    Integrator(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
 | 
			
		||||
      Integrator(GridBase* grid, 
 | 
			
		||||
		 IntegratorParameters Par,
 | 
			
		||||
		 ActionSet& Aset):
 | 
			
		||||
      Params(Par),as(Aset),P(new LatticeGaugeField(grid)),pRNG(grid){
 | 
			
		||||
	pRNG.SeedRandomDevice();
 | 
			
		||||
          Params(Par),
 | 
			
		||||
    	  as(Aset),
 | 
			
		||||
	  P(new LatticeGaugeField(grid)),
 | 
			
		||||
	  pRNG(grid),
 | 
			
		||||
	  levels(Aset.size())
 | 
			
		||||
      {
 | 
			
		||||
	
 | 
			
		||||
	std::vector<int> seeds({1,2,3,4,5});
 | 
			
		||||
	pRNG.SeedFixedIntegers(seeds);
 | 
			
		||||
 | 
			
		||||
	t_P.resize(levels,0.0);
 | 
			
		||||
	t_U=0.0;
 | 
			
		||||
 | 
			
		||||
      };
 | 
			
		||||
      
 | 
			
		||||
      ~Integrator(){}
 | 
			
		||||
@@ -120,14 +146,17 @@ namespace Grid{
 | 
			
		||||
	Complex Hsum = sum(Hloc);
 | 
			
		||||
	
 | 
			
		||||
	RealD H = Hsum.real();
 | 
			
		||||
 | 
			
		||||
	RealD Hterm;
 | 
			
		||||
	std::cout<<GridLogMessage << "Momentum action H_p = "<< H << "\n";
 | 
			
		||||
 | 
			
		||||
	// Actions
 | 
			
		||||
	for(int level=0; level<as.size(); ++level)
 | 
			
		||||
	  for(int actionID=0; actionID<as[level].actions.size(); ++actionID)
 | 
			
		||||
	    H += as[level].actions.at(actionID)->S(U);
 | 
			
		||||
 | 
			
		||||
	for(int level=0; level<as.size(); ++level){
 | 
			
		||||
	  for(int actionID=0; actionID<as[level].actions.size(); ++actionID){
 | 
			
		||||
	    Hterm = as[level].actions.at(actionID)->S(U);
 | 
			
		||||
	    std::cout<<GridLogMessage << "Level "<<level<<" term "<<actionID<<" H = "<<Hterm<<std::endl;
 | 
			
		||||
	    H += Hterm;
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
	std::cout<<GridLogMessage << "Total action H = "<< H << "\n";
 | 
			
		||||
	
 | 
			
		||||
	return H;
 | 
			
		||||
@@ -136,17 +165,16 @@ namespace Grid{
 | 
			
		||||
      void integrate(LatticeGaugeField& U){
 | 
			
		||||
	std::vector<int> clock;
 | 
			
		||||
	clock.resize(as.size(),0);
 | 
			
		||||
	for(int step=0; step< Params.MDsteps; ++step)   // MD step
 | 
			
		||||
	for(int step=0; step< Params.MDsteps; ++step){   // MD step
 | 
			
		||||
	  TheIntegrator.step(U,0,clock, (this));
 | 
			
		||||
	}
 | 
			
		||||
	for(int level=0; level<as.size(); ++level){
 | 
			
		||||
	  assert(fabs(t_U - t_P[level])<1.0e-3);
 | 
			
		||||
	  std::cout<<GridLogMessage<<" times["<<level<<"]= "<<t_P[level]<< " " << t_U <<std::endl;
 | 
			
		||||
	}	
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif//INTEGRATOR_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -9,80 +9,158 @@
 | 
			
		||||
#ifndef INTEGRATOR_ALG_INCLUDED
 | 
			
		||||
#define INTEGRATOR_ALG_INCLUDED
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Grid{
 | 
			
		||||
  namespace QCD{
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
Chroma: Recursive min norm
 | 
			
		||||
00132     Real dtau = traj_length / Real(n_steps);
 | 
			
		||||
00133     Real lambda_dt = dtau*lambda;
 | 
			
		||||
00134     Real dtauby2 = dtau / Real(2);
 | 
			
		||||
00135     Real one_minus_2lambda_dt = (Real(1)-Real(2)*lambda)*dtau;
 | 
			
		||||
00136     Real two_lambda_dt = lambda_dt*Real(2);
 | 
			
		||||
00137 
 | 
			
		||||
00138     // Its sts so:
 | 
			
		||||
00139     expSdt(s, lambda_dt); 
 | 
			
		||||
00140     for(int i=0; i < n_steps-1; i++) {  // N-1 full steps
 | 
			
		||||
00141       // Roll the exp(lambda_dt T) here and start
 | 
			
		||||
00142       // Next iter into one
 | 
			
		||||
00143       subIntegrator(s, dtauby2);         <--- either leapU or next integrator
 | 
			
		||||
00144       expSdt(s, one_minus_2lambda_dt);  
 | 
			
		||||
00145       subIntegrator(s, dtauby2);         <--- either leapU or next integrator
 | 
			
		||||
00146       expSdt(s, two_lambda_dt); 
 | 
			
		||||
00147     }
 | 
			
		||||
00148     // Last step, can't roll the first and last exp(lambda_dt T) 
 | 
			
		||||
00149     // together.
 | 
			
		||||
00150     subIntegrator(s, dtauby2);
 | 
			
		||||
00151     expSdt(s, one_minus_2lambda_dt);
 | 
			
		||||
00152     subIntegrator(s, dtauby2);
 | 
			
		||||
00153     expSdt(s, lambda_dt);
 | 
			
		||||
 | 
			
		||||
    * 
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class MinimumNorm2{
 | 
			
		||||
      const double lambda = 0.1931833275037836;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      void step (LatticeLorentzColourMatrix& U, 
 | 
			
		||||
		 int level, std::vector<int>& clock,
 | 
			
		||||
		 Integrator<MinimumNorm2>* Integ){
 | 
			
		||||
 | 
			
		||||
	// level  : current level
 | 
			
		||||
	// fl     : final level
 | 
			
		||||
	// eps    : current step size
 | 
			
		||||
 | 
			
		||||
	int fl = Integ->as.size() -1;
 | 
			
		||||
 | 
			
		||||
	double eps = Integ->Params.stepsize;
 | 
			
		||||
	
 | 
			
		||||
	for(int l=0; l<=level; ++l) eps/= 2.0*Integ->as[l].multiplier;
 | 
			
		||||
	
 | 
			
		||||
	// which is final half step
 | 
			
		||||
	int fin = Integ->as[0].multiplier;
 | 
			
		||||
	for(int l=1; l<=level; ++l) fin*= 2.0*Integ->as[l].multiplier;
 | 
			
		||||
	fin = 3*Integ->Params.MDsteps*fin -1;
 | 
			
		||||
	
 | 
			
		||||
	for(int e=0; e<Integ->as[level].multiplier; ++e){
 | 
			
		||||
 | 
			
		||||
	int multiplier = Integ->as[level].multiplier;
 | 
			
		||||
	for(int e=0; e<multiplier; ++e){       // steps per step
 | 
			
		||||
 | 
			
		||||
	  if(clock[level] == 0){    // initial half step 
 | 
			
		||||
	    Integ->update_P(U,level,lambda*eps);
 | 
			
		||||
	    ++clock[level];
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"P "<< clock[level] <<std::endl;
 | 
			
		||||
	    Integ->update_P(U,level,lambda*eps);   ++clock[level];
 | 
			
		||||
	  }
 | 
			
		||||
	  
 | 
			
		||||
	  if(level == fl){          // lowest level 
 | 
			
		||||
	    Integ->update_U(U,0.5*eps);
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"U "<< (clock[level]+1) <<std::endl;
 | 
			
		||||
	  }else{                 // recursive function call 
 | 
			
		||||
	    step(U,level+1,clock, Integ);
 | 
			
		||||
	  }
 | 
			
		||||
	  
 | 
			
		||||
	  Integ->update_P(U,level,(1.0-2.0*lambda)*eps);
 | 
			
		||||
	  ++clock[level];
 | 
			
		||||
	  for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	  std::cout<<GridLogMessage<<"P "<< (clock[level]) <<std::endl;
 | 
			
		||||
	  Integ->update_P(U,level,(1.0-2.0*lambda)*eps); ++clock[level];
 | 
			
		||||
	  
 | 
			
		||||
	  if(level == fl){          // lowest level 
 | 
			
		||||
	    Integ->update_U(U,0.5*eps);
 | 
			
		||||
	    
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"U "<< (clock[level]+1) <<std::endl;
 | 
			
		||||
	  }else{                 // recursive function call 
 | 
			
		||||
	    step(U,level+1,clock, Integ);
 | 
			
		||||
	  }    
 | 
			
		||||
	  
 | 
			
		||||
	  
 | 
			
		||||
	  if(clock[level] == fin){  // final half step
 | 
			
		||||
	    Integ->update_P(U,level,lambda*eps);
 | 
			
		||||
	    
 | 
			
		||||
	    ++clock[level];
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"P "<< clock[level] <<std::endl;
 | 
			
		||||
	  }else{                  // bulk step
 | 
			
		||||
	    Integ->update_P(U,level,lambda*2.0*eps);
 | 
			
		||||
	    
 | 
			
		||||
	    clock[level]+=2;
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"P "<< clock[level] <<std::endl;
 | 
			
		||||
	  }
 | 
			
		||||
	  // Handle the final half step
 | 
			
		||||
	  std::cout << GridLogMessage << " P[" <<level<<"] clock = "<<clock[level]<<"/"<<fin<<std::endl;
 | 
			
		||||
	  int mm = (clock[level]==fin) ? 1 : 2;
 | 
			
		||||
	  Integ->update_P(U,level,lambda*eps*mm); clock[level]+=mm;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
 | 
			
		||||
Chroma: Recursive leapfrog
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
00124     Real dtau = traj_length / n_steps;
 | 
			
		||||
00125     Real dtauby2 = dtau/2;
 | 
			
		||||
00126 
 | 
			
		||||
00127     // Its sts so:
 | 
			
		||||
00128     expSdt(s, dtauby2);  // First half step
 | 
			
		||||
00129     for(int i=0; i < n_steps-1; i++) {  // N-1 full steps
 | 
			
		||||
00130       subIntegrator(s, dtau);  <--- either leapU or next integrator
 | 
			
		||||
00131       expSdt(s, dtau);
 | 
			
		||||
00132     }
 | 
			
		||||
00133     subIntegrator(s, dtau);     // Last Full Step
 | 
			
		||||
00134     expSdt(s, dtauby2);  // Last Half Step
 | 
			
		||||
 | 
			
		||||
    * Nested 1:4; units in dt for top level integrator
 | 
			
		||||
    * CHROMA                           GUIDO
 | 
			
		||||
    *   0        1                      0              
 | 
			
		||||
    *  P 1/2                           P 1/2
 | 
			
		||||
    *          P 1/16                                  P1/16
 | 
			
		||||
    *                 U 1/8                                   U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                   U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/16                                  P1/8
 | 
			
		||||
    *  P 1                             P 1
 | 
			
		||||
    *          P 1/16                    * skipped
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/16                                  P1/8
 | 
			
		||||
    *  P 1                             P 1
 | 
			
		||||
    *          P 1/16                    * skipped
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/16                    * skipped
 | 
			
		||||
    *  P 1                             P 1
 | 
			
		||||
    *          P 1/16                                  P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/8                                   P1/8
 | 
			
		||||
    *                 U 1/8                                 U1/8
 | 
			
		||||
    *          P 1/16                                  P1/16
 | 
			
		||||
    *  P 1/2                            P 1/2
 | 
			
		||||
    * Total
 | 
			
		||||
    */    
 | 
			
		||||
    class LeapFrog{
 | 
			
		||||
    public:
 | 
			
		||||
      void step (LatticeLorentzColourMatrix& U, 
 | 
			
		||||
@@ -94,46 +172,45 @@ namespace Grid{
 | 
			
		||||
	// eps    : current step size
 | 
			
		||||
	
 | 
			
		||||
	int fl = Integ->as.size() -1;
 | 
			
		||||
	double eps = Integ->Params.stepsize;
 | 
			
		||||
	
 | 
			
		||||
	// Get current level step size
 | 
			
		||||
	int fin = 2*Integ->Params.MDsteps;
 | 
			
		||||
	for(int l=0; l<=level; ++l) fin*= Integ->as[l].multiplier;
 | 
			
		||||
	fin = fin-1;
 | 
			
		||||
 | 
			
		||||
	double eps = Integ->Params.stepsize;
 | 
			
		||||
	for(int l=0; l<=level; ++l) eps/= Integ->as[l].multiplier;
 | 
			
		||||
	
 | 
			
		||||
	int fin = 1;
 | 
			
		||||
	for(int l=0; l<=level; ++l) fin*= Integ->as[l].multiplier;
 | 
			
		||||
	fin = 2*Integ->Params.MDsteps*fin - 1;
 | 
			
		||||
	
 | 
			
		||||
	for(int e=0; e<Integ->as[level].multiplier; ++e){
 | 
			
		||||
	  
 | 
			
		||||
	  if(clock[level] == 0){    // initial half step
 | 
			
		||||
	    Integ->update_P(U, level,eps/2.0);
 | 
			
		||||
	    ++clock[level];
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"P "<< 0.5*clock[level] <<std::endl;
 | 
			
		||||
	int multiplier = Integ->as[level].multiplier;
 | 
			
		||||
	for(int e=0; e<multiplier; ++e){
 | 
			
		||||
 | 
			
		||||
	  int first_step,last_step;
 | 
			
		||||
 | 
			
		||||
	  if ( level==0 ) {
 | 
			
		||||
	    first_step = (clock[level]==0);
 | 
			
		||||
	    last_step  = (clock[level]==fin);
 | 
			
		||||
	  } else {
 | 
			
		||||
	    first_step = (e==0);
 | 
			
		||||
	    last_step  = (e==multiplier-1);
 | 
			
		||||
	  }
 | 
			
		||||
 | 
			
		||||
	  if(first_step){    // initial half step
 | 
			
		||||
	    Integ->update_P(U, level,eps/2.0);	    ++clock[level];
 | 
			
		||||
	  }
 | 
			
		||||
 | 
			
		||||
	  if(level == fl){          // lowest level
 | 
			
		||||
	    Integ->update_U(U, eps);
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"U "<< 0.5*(clock[level]+1) <<std::endl;
 | 
			
		||||
	  }else{                 // recursive function call
 | 
			
		||||
	    step(U, level+1,clock, Integ);
 | 
			
		||||
	  }
 | 
			
		||||
 | 
			
		||||
	  if(clock[level] == fin){  // final half step
 | 
			
		||||
	    Integ->update_P(U, level,eps/2.0);
 | 
			
		||||
	    ++clock[level];
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"P "<< 0.5*clock[level] <<std::endl;
 | 
			
		||||
	  }else{                  // bulk step
 | 
			
		||||
	    Integ->update_P(U, level,eps);
 | 
			
		||||
	    clock[level]+=2;
 | 
			
		||||
	    for(int l=0; l<level;++l) std::cout<<GridLogMessage<<"   ";
 | 
			
		||||
	    std::cout<<GridLogMessage<<"P "<< 0.5*clock[level] <<std::endl;
 | 
			
		||||
	  }
 | 
			
		||||
	  // Handle the final half step
 | 
			
		||||
	  std::cout << GridLogMessage << " P[" <<level<<"] clock = "<<clock[level]<<"/"<<fin<<std::endl;
 | 
			
		||||
	  int mm = last_step ? 1 : 2;
 | 
			
		||||
	  Integ->update_P(U, level,mm*eps/2.0);	    
 | 
			
		||||
	  clock[level]+=mm;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -141,6 +218,4 @@ namespace Grid{
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif//INTEGRATOR_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user