mirror of
https://github.com/paboyle/Grid.git
synced 2026-10-11 10:18:06 +01:00
88 lines
4.5 KiB
C++
88 lines
4.5 KiB
C++
/*************************************************************************************
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
Source file: ./Grid/algorithms/iterative/GCRCoefficients.h
|
|
|
|
Copyright (C) 2026
|
|
|
|
Author: Peter Boyle <pboyle@bnl.gov>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
See the full license in the file "LICENSE" in the top level distribution
|
|
directory
|
|
*************************************************************************************/
|
|
/* END LEGAL */
|
|
#pragma once
|
|
|
|
NAMESPACE_BEGIN(Grid);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Recorded GCR coefficients: per-step means over calls of the step length
|
|
// a_k and the orthogonalisation coefficients b_kj (already scaled and
|
|
// signed as applied: p_{k+1} = r + sum_j b_kj p_{k-j}).
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
struct GCRCoefficients {
|
|
int mmax = 0;
|
|
// Every recorded call is kept: calls[c] = list of (a_k, [b_kj]) per step.
|
|
// A(k)/B(k,j) return the coefficients of the SELECTED call: by default the
|
|
// last complete one. Selection "mean" averages coefficients over calls --
|
|
// kept for comparison only: the mean of the coefficients of a nonlinear
|
|
// recurrence is not the mean of the polynomials, and in practice (Frontier
|
|
// M3, 2026-08-26) it was worse than every individual call.
|
|
enum Select { Last=0, First=1, Index=2, Mean=3 };
|
|
Select select = Last;
|
|
int index = 0;
|
|
typedef std::vector<std::pair<ComplexD,std::vector<ComplexD> > > Call;
|
|
std::vector<Call> calls;
|
|
Call current;
|
|
void RecordA(int k, ComplexD a){
|
|
if ( k==0 && current.size() ) { calls.push_back(current); current.clear(); }
|
|
if ( (int)current.size() <= k ) current.resize(k+1);
|
|
current[k].first = a;
|
|
}
|
|
void RecordB(int k, const std::vector<ComplexD> &b){
|
|
if ( (int)current.size() <= k ) current.resize(k+1);
|
|
current[k].second = b;
|
|
}
|
|
void Flush(void){ if ( current.size() ) { calls.push_back(current); current.clear(); } }
|
|
int Calls(void) const { return calls.size() + (current.size() ? 1 : 0); }
|
|
const Call & Chosen(void) const {
|
|
GRID_ASSERT( calls.size() || current.size() );
|
|
if ( calls.empty() ) return current;
|
|
if ( select==First ) return calls.front();
|
|
if ( select==Index ) { GRID_ASSERT(index>=0 && index<(int)calls.size()); return calls[index]; }
|
|
return calls.back();
|
|
}
|
|
int Steps(void) const { return select==Mean ? MeanSteps() : Chosen().size(); }
|
|
int NB(int k) const { return select==Mean ? MeanNB(k) : Chosen()[k].second.size(); }
|
|
ComplexD A(int k) const { return select==Mean ? MeanA(k) : Chosen()[k].first; }
|
|
ComplexD B(int k,int j) const { return select==Mean ? MeanB(k,j) : Chosen()[k].second[j]; }
|
|
// mean over calls (comparison only)
|
|
int MeanSteps(void) const { int m=0; for(auto &c:calls) m = std::max(m,(int)c.size()); return m; }
|
|
int MeanNB(int k) const { int m=0; for(auto &c:calls) if(k<(int)c.size()) m = std::max(m,(int)c[k].second.size()); return m; }
|
|
ComplexD MeanA(int k) const { ComplexD s(0.0); int n=0; for(auto &c:calls) if(k<(int)c.size()){ s+=c[k].first; n++; } return s/(double)n; }
|
|
ComplexD MeanB(int k,int j) const { ComplexD s(0.0); int n=0; for(auto &c:calls) if(k<(int)c.size() && j<(int)c[k].second.size()){ s+=c[k].second[j]; n++; } return s/(double)n; }
|
|
void Report(const std::string &name) const {
|
|
const char *sel[4]={"last","first","index","mean"};
|
|
std::cout << GridLogMessage << "GCRCoefficients " << name << ": " << Calls() << " calls, " << Steps() << " steps, mmax " << mmax
|
|
<< ", selection " << sel[select] << std::endl;
|
|
for(int k=0;k<Steps();k++){
|
|
std::cout << GridLogMessage << " step " << k << " a=(" << real(A(k)) << "," << imag(A(k)) << ")";
|
|
for(int j=0;j<NB(k);j++) std::cout << " b[" << j << "]=(" << real(B(k,j)) << "," << imag(B(k,j)) << ")";
|
|
// spread of a_k across calls: how different the individual polynomials are
|
|
if ( calls.size()>1 ) {
|
|
RealD lo=1e300, hi=0; for(auto &c:calls) if(k<(int)c.size()){ RealD x=real(c[k].first), y=imag(c[k].first); RealD m=std::sqrt(x*x+y*y); lo=std::min(lo,m); hi=std::max(hi,m); }
|
|
std::cout << " |a| over calls [" << lo << "," << hi << "]";
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
}
|
|
};
|
|
|
|
NAMESPACE_END(Grid);
|