Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebased splice potential #127

Open
wants to merge 58 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
5ce24ca
Allow to splice the potential
cphyc Jul 21, 2021
68a3347
Allow to set CG accuracy for splicing
cphyc Oct 28, 2021
78a2383
Fix orthograph
cphyc Oct 29, 2021
4824edf
Log change in precision
cphyc Oct 29, 2021
b10d3d7
Set the fundamental *after* applying **k
cphyc Oct 29, 2021
c9dcb78
Add test for potential splicing
cphyc Oct 29, 2021
6387e59
Update pot
cphyc Feb 20, 2023
58b4df5
First working version
cphyc Feb 22, 2023
883626f
added splicing now using fourier parallel seeding
AnatoleStorck Mar 16, 2023
3cdb76a
new compiled genetIC file
AnatoleStorck Mar 16, 2023
18e209d
reverted back to zeldovich gradient
AnatoleStorck Apr 3, 2023
f2c3d6c
testing splicing potential - added P/k**2
AnatoleStorck Apr 20, 2023
58e26ec
Exploring different field minimization criteria
AnatoleStorck May 11, 2023
abda4d5
Testing maximum vs norm tolerance
AnatoleStorck May 12, 2023
f308076
Add minres minimization method for splicing
AnatoleStorck May 14, 2023
574d9b8
small changes to CG and minres methods
AnatoleStorck May 15, 2023
b9df9b3
added break condition for elapsed time in splicing
AnatoleStorck Jun 3, 2023
01329be
cleaned up some of the code
AnatoleStorck May 19, 2023
9c9b834
added restart functionality to splicing
AnatoleStorck Aug 4, 2023
b2a9209
making minres its own file
AnatoleStorck Aug 10, 2023
97e491f
minor changes to structure
AnatoleStorck Aug 28, 2023
04199e5
minor changes to parameters
AnatoleStorck Sep 21, 2023
fb04a17
Cleaned up code a bit.
AnatoleStorck Oct 4, 2023
9031bf3
Allow compilation with 32bit precision
cphyc Oct 13, 2023
ccda41e
Untrack genetIC
cphyc Oct 13, 2023
c1a079e
Making tolerance criteria to be
AnatoleStorck Oct 15, 2023
f680093
Cleaned up command names, splicing no longer
AnatoleStorck Oct 18, 2023
132635a
Used a colon instead of semicolon.
AnatoleStorck Oct 18, 2023
705d1fb
Added a few deprecated commands
AnatoleStorck Oct 18, 2023
2004db5
Fixed deprecated class route bug.
AnatoleStorck Oct 18, 2023
e206125
Added possibility to control stopping
AnatoleStorck Oct 18, 2023
04a3424
Add ability to set min-method for splicing.
AnatoleStorck Oct 19, 2023
6426d78
Fixed bug causing splicing to output incorrectly.
AnatoleStorck Oct 19, 2023
fbca771
Removed MINRES as default minimizer for pot_splice
AnatoleStorck Oct 19, 2023
084b945
Remove deprecated potential splicing test. New one to be made soon.
AnatoleStorck Oct 19, 2023
36b72d3
Custom Makefile for project (with COSMOS support)
AnatoleStorck Nov 8, 2023
899b7e8
Fixed library paths for my mac
AnatoleStorck Nov 8, 2023
32814d2
set defaults for pot splicing
AnatoleStorck Nov 16, 2023
de53fa6
added fourier series seed drawing for splicing
AnatoleStorck Nov 16, 2023
23e3ef6
Merged usefull functionality from minimizationComparison
AnatoleStorck Aug 5, 2024
32a0146
updated Mafile for testing machine
AnatoleStorck Sep 30, 2024
4943030
cleaned up code and reverted splicing defaults to density splicing
AnatoleStorck Sep 30, 2024
f958852
resolving more differences from rebase
AnatoleStorck Sep 30, 2024
631541e
fixed Makefile
AnatoleStorck Sep 30, 2024
f0da1b8
fixed typo while rebasing
AnatoleStorck Sep 30, 2024
09252f8
fixed tracking of test
AnatoleStorck Sep 30, 2024
fe53aab
fixed tracking of tools
AnatoleStorck Sep 30, 2024
2b814ac
fixed more tracking of tools
AnatoleStorck Sep 30, 2024
7c6047d
further cleanup
AnatoleStorck Sep 30, 2024
510ea83
Addressed pull request comments
AnatoleStorck Sep 30, 2024
de798dc
added testing for potential splicing (needs to be single core as MINR…
AnatoleStorck Oct 3, 2024
71a9030
Made the result more deterministic (splicing smaller sphere needs les…
AnatoleStorck Oct 3, 2024
af48786
fixed test file
AnatoleStorck Oct 3, 2024
a174415
changed methods to camel-case and slightly adjusted some comments and…
AnatoleStorck Oct 6, 2024
3ec60ca
Merge remote-tracking branch 'upstream/master' into rebased_splicePot…
AnatoleStorck Oct 6, 2024
c796fd6
added warning for potential splicing with the 'ZELDOVICH_GRADIENT_FOU…
AnatoleStorck Oct 6, 2024
54716f9
updated warning message about potential splicing
AnatoleStorck Oct 7, 2024
2d84db4
fixed splice accuracy logging message
AnatoleStorck Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion genetIC/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CFLAGS ?= -Wall -g -lpthread -O3 -fopenmp -std=c++17 -fdiagnostics-color=auto -I
# -DVELOCITY_MODIFICATION_GRADIENT_FOURIER_SPACE: As the name suggests, use "ik" as the gradient operator; otherwise
# uses a fourth order stencil in real space. Enabling this is essential if you disable CUBIC_INTERPOLATION.
# -DZELDOVICH_GRADIENT_FOURIER_SPACE: Same as VELOCITY_MODIFICATION_GRADIENT_FOURIER_SPACE, but for computing the
# Zeldovich displacement field.
# Zeldovich displacement field. Should be commented out if splicing the potential.
# -DFRACTIONAL_K_SPLIT: This defines the characteristic k0 of the filter used to split information between zoom levels,
# defined by k0 = k_nyquist * FRACTIONAL_K_SPLIT, where k_nyquist is the Nyquist frequency of the lower-resolution grid.
# Higher values correlate the zoom grids more precisely with the unzoomed base grids, but at the cost of errors
Expand All @@ -20,6 +20,7 @@ CFLAGS ?= -Wall -g -lpthread -O3 -fopenmp -std=c++17 -fdiagnostics-color=auto -I
# -DFILTER_ON_COARSE_GRID: When moving long wavelength information onto a zoom grid, filters on the base grid
# and then interpolates into the zoom, rather than the default which is to interpolate and then filter.

# Comment out -DZELDOVICH_GRADIENT_FOURIER_SPACE for potential splicing
CODEOPTIONS = -DDOUBLEPRECISION -DOUTPUT_IN_DOUBLEPRECISION -DCUBIC_INTERPOLATION -DFRACTIONAL_K_SPLIT=0.3 -DFRACTIONAL_FILTER_TEMPERATURE=0.1 -DFILTER_ON_COARSE_GRID -DZELDOVICH_GRADIENT_FOURIER_SPACE
CPATH ?= /opt/local/include/
LPATH ?= /opt/local/lib
Expand Down Expand Up @@ -68,6 +69,14 @@ ifeq ($(USE_CUFFT), 1)
CFLAGS=-O3 -I`pwd` -I`pwd`/HighFive/include -Xcompiler="-O3 -fopenmp -std=c++14 -Wall"
CXX=nvcc
endif

ifeq ($(HOST3), Ana)
CXX = /opt/homebrew/bin/c++-14
CPATH = /opt/homebrew/include/
LPATH = /opt/homebrew/lib
CFLAGS = -O3 -fopenmp -std=c++14 -fdiagnostics-color=auto -I`pwd` -DOPENMP -DDOUBLEPRECISION
endif

ifeq ($(HOST3), pfe)
CXX = /nasa/pkgsrc/2016Q2/gcc5/bin/g++
CPATH = /u/apontzen/genetIC/genetIC:/nasa/gsl/1.14/include/:/nasa/intel/Compiler/2016.2.181/compilers_and_libraries_2016.2.181/linux/mkl/include/fftw
Expand Down
106 changes: 95 additions & 11 deletions genetIC/src/ic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class ICGenerator {
//! Vector of output fields (defaults to just a single field)
std::vector<std::shared_ptr<fields::OutputField<GridDataType>>> outputFields;
bool useBaryonTransferFunction{false}; //!< True if gas particles should use a different transfer function
modifications::ModificationManager<GridDataType> modificationManager; //!< Handles applying modificaitons to the various fields.
modifications::ModificationManager<GridDataType> modificationManager; //!< Handles applying modifications to the various fields.
std::unique_ptr<fields::RandomFieldGenerator<GridDataType>> randomFieldGenerator; //!< Generate white noise for the output fields
std::unique_ptr<cosmology::PowerSpectrum<GridDataType>> spectrum; //!< Transfer function data

Expand Down Expand Up @@ -160,6 +160,27 @@ class ICGenerator {
int initial_number_steps = 10; //!< Number of steps always used by quadratic modifications.
T precision = 0.001; //!< Target precision required of quadratic modifications.

//! Accuracy of the minimization method for splicing
T splicing_rel_tol = 1e-6;
T splicing_abs_tol = 1e-12;

//! Set the standard minimization method for splicing (CG or MINRES)
std::string minimization_method = "CG";

//! (does not work yet) Allows to continue minimizing a spliced field from a previous run
bool restart = false;

//! Using fourier parallel seeding for splicing
bool setSplicedSeedFourierParallel = false;
AnatoleStorck marked this conversation as resolved.
Show resolved Hide resolved
//! Using fourier series seeding for splicing
bool setSplicedSeedFourierSeries = false;
//! Using real seeding for splicing
std::string spliceSeedingType = "Real";

//! The brake time in hours, set to 0 by default. If set to a positive value, splicing will stop after the given time,
// if it has not yet met the minimization threshold.
double brake_time = 0;

//! Mapper that keep track of particles in the mulit-level context.
shared_ptr<particle::mapper::ParticleMapper<GridDataType>> pMapper = nullptr;
//! Input mapper, used to relate particles in a different simulation to particles in this one.
Expand Down Expand Up @@ -259,7 +280,7 @@ class ICGenerator {
allowStrayParticles = true;
}

//!\brief Enables the use of a baryon density field.
//!\brief Enables the use of a baryon density field.
//! If flagged on, the code will extract the transfer function for baryons from CAMB separately from
//! the dark matter transfer. This causes twice as many fields to be stored and generated, but
//! produces more accurate results for baryons than assuming they follow the same transfer function
Expand Down Expand Up @@ -713,11 +734,6 @@ class ICGenerator {
this->updateParticleMapper();
}






//! \brief Obtain power spectrum from a CAMB data file
/*!
* \param cambFieldPath - string of path to CAMB file
Expand Down Expand Up @@ -1655,7 +1671,7 @@ class ICGenerator {
}

//! Splicing: fixes the flagged region, while reinitialising the exterior from a new random field
virtual void splice(size_t newSeed) {
virtual void spliceWithFactor(size_t newSeed, int k_factor=0) {
initialiseRandomComponentIfUninitialised();
if(outputFields.size()>1)
throw std::runtime_error("Splicing is not yet implemented for the case of multiple transfer functions");
Expand All @@ -1673,19 +1689,87 @@ class ICGenerator {

logging::entry() << "Constructing new random field for exterior of splice" << endl;
newGenerator.seed(newSeed);
if(setSplicedSeedFourierParallel == true || setSplicedSeedFourierSeries == true) {
logging::entry() << "-!- Drawing splice seed in " << spliceSeedingType << " -!-" << endl;
newGenerator.setDrawInFourierSpace(true);
if(setSplicedSeedFourierParallel == true)
newGenerator.setParallel(true);
newGenerator.setReverseRandomDrawOrder(false);
}
newGenerator.draw();
logging::entry() << "Finished constructing new random field. Beginning splice operation." << endl;
logging::entry() << "Finished constructing new random field" << endl;
logging::entry() << "Beginning splice operation using the " << minimization_method << " method." << endl;

for(size_t level=0; level<multiLevelContext.getNumLevels(); ++level) {
auto &originalFieldThisLevel = outputFields[0]->getFieldForLevel(level);
auto &newFieldThisLevel = newField.getFieldForLevel(level);
auto splicedFieldThisLevel = modifications::spliceOneLevel(newFieldThisLevel, originalFieldThisLevel,
*multiLevelContext.getCovariance(level, particle::species::all));
auto splicedFieldThisLevel = modifications::spliceOneLevel(
newFieldThisLevel,
originalFieldThisLevel,
*multiLevelContext.getCovariance(level, particle::species::all),
splicing_rel_tol,
splicing_abs_tol,
k_factor,
minimization_method,
restart,
brake_time
);
splicedFieldThisLevel.toFourier();
originalFieldThisLevel = std::move(splicedFieldThisLevel);
}
}

//! Set the conjugate gradient precision for the splicing method
/*!
* @param type Precision can be relative or absolute
* @param tolerance Precision of the CG
*/
virtual void setSpliceAccuracy(string type, double tolerance) {
if (type == "absolute") {
splicing_abs_tol = tolerance;
logging::entry() << "Setting splicing " << minimization_method << " absolute tolerance to " << tolerance << std::endl;
} else if (type == "relative") {
splicing_rel_tol = tolerance;
logging::entry() << "Setting splicing " << minimization_method << " relative tolerance to " << tolerance << std::endl;
}
}

virtual void spliceSeedFourierSeries() {
setSplicedSeedFourierSeries = true;
spliceSeedingType = "fourier and series";
}

virtual void spliceSeedFourierParallel() {
setSplicedSeedFourierParallel = true;
spliceSeedingType = "fourier and parallel";
}

virtual void restartSplice() {
restart = true;
}

virtual void setSpliceMinimization(string set_minMethod) {
minimization_method = set_minMethod;
}

virtual void stopSplicingAfter(double time_to_brake) {
brake_time = time_to_brake;
}

virtual void spliceDensity(size_t newSeed) {
spliceWithFactor(newSeed, 0);
}

virtual void splicePotential(size_t newSeed) {
#ifdef ZELDOVICH_GRADIENT_FOURIER_SPACE
logging::entry(logging::level::warning) << "WARNING: You are splicing the potential field with ZELDOVICH_GRADIENT_FOURIER_SPACE." << std::endl;
logging::entry(logging::level::warning) << " Due to non-locality, the density field may not exactly match within the" << std::endl;
logging::entry(logging::level::warning) << " spliced region. Consider recompiling with ZELDOVICH_GRADIENT_FOURIER_SPACE" << std::endl;
logging::entry(logging::level::warning) << " disabled if precise density field matching is important to you." << std::endl;
#endif
spliceWithFactor(newSeed, -2);
}

//! Reverses the sign of the low-k modes.
virtual void reverseSmallK(T kmax) {

Expand Down
18 changes: 14 additions & 4 deletions genetIC/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,26 @@ void setup_parser(tools::ClassDispatch<ICType, void> &dispatch) {

dispatch.add_class_route("reverse", static_cast<void (ICType::*)()>(&ICType::reverse));
dispatch.add_class_route("reverse_small_k", static_cast<void (ICType::*)(FloatType)>(&ICType::reverseSmallK));
dispatch.add_class_route("splice", &ICType::splice);

dispatch.add_deprecated_class_route("splice_accuracy", "set_splice_accuracy", &ICType::setSpliceAccuracy);
dispatch.add_class_route("set_splice_accuracy", &ICType::setSpliceAccuracy);
dispatch.add_class_route("splice_seedfourier_parallel", &ICType::spliceSeedFourierParallel);
dispatch.add_class_route("splice_seedfourier_series", &ICType::spliceSeedFourierSeries);
dispatch.add_deprecated_class_route("set_minimization", "set_splice_minimization", &ICType::setSpliceMinimization);
dispatch.add_class_route("set_splice_minimization", &ICType::setSpliceMinimization);
dispatch.add_deprecated_class_route("splice", "splice_density", &ICType::spliceDensity);
dispatch.add_class_route("splice_density", &ICType::spliceDensity);
dispatch.add_class_route("splice_potential", &ICType::splicePotential);

dispatch.add_deprecated_class_route("stop_after", "stop_splicing_after", &ICType::stopSplicingAfter);
dispatch.add_class_route("stop_splicing_after", &ICType::stopSplicingAfter);

// Write objects to files
// dispatch.add_class_route("dump_grid", &ICType::dumpGrid);
dispatch.add_class_route("dump_grid", static_cast<void (ICType::*)(size_t)>(&ICType::dumpGrid));
dispatch.add_class_route("dump_vx", static_cast<void (ICType::*)(size_t)>(&ICType::dumpVelocityX));
dispatch.add_class_route("dump_grid_for_field", static_cast<void (ICType::*)(size_t, particle::species)>(&ICType::dumpGrid));
dispatch.add_class_route("dump_grid_fourier", static_cast<void (ICType::*)(size_t)>(&ICType::dumpGridFourier));
dispatch.add_class_route("dump_grid_fourier_for_field",
static_cast<void (ICType::*)(size_t, particle::species)>(&ICType::dumpGridFourier));
dispatch.add_class_route("dump_grid_fourier_for_field", static_cast<void (ICType::*)(size_t, particle::species)>(&ICType::dumpGridFourier));
dispatch.add_class_route("dump_ps", static_cast<void (ICType::*)(size_t)>(&ICType::dumpPS));
dispatch.add_class_route("dump_ps_field", static_cast<void (ICType::*)(size_t, particle::species)>(&ICType::dumpPS));
dispatch.add_class_route("dump_tipsy", static_cast<void (ICType::*)(std::string)>(&ICType::saveTipsyArray));
Expand Down
13 changes: 13 additions & 0 deletions genetIC/src/simulation/field/field.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,19 @@ namespace fields {
}
}

//! Single grid maximum. Only implemented for real space
auto maximum() const {
assert(!isFourier());

tools::datatypes::strip_complex<DataType> max=0;
size_t N = data.size();

for(size_t i=0; i<N; i++) {
max = std::max(max, std::abs(data[i]));
}
return max;
}

//! Single grid inner product. Only implemented for real space.
auto innerProduct(const Field<DataType, CoordinateType> & other) const {
assert(!other.isFourier());
Expand Down
32 changes: 29 additions & 3 deletions genetIC/src/simulation/modifications/splice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <complex>
#include <src/tools/data_types/complex.hpp>
#include <src/tools/numerics/cg.hpp>
#include <src/tools/numerics/minres.hpp>

namespace modifications {
template<typename T>
Expand Down Expand Up @@ -37,7 +38,14 @@ namespace modifications {
template<typename DataType, typename T=tools::datatypes::strip_complex<DataType>>
fields::Field<DataType,T> spliceOneLevel(fields::Field<DataType,T> & a,
fields::Field<DataType,T> & b,
const fields::Field<DataType,T> & cov) {
const fields::Field<DataType,T> & cov,
const double rtol,
const double atol,
const int k_factor=0,
const std::string minimization_method="CG",
const bool restart=false,
const double brake_time=0
) {

// To understand the implementation below, first read Appendix A of Cadiou et al (2021),
// and/or look at the 1D toy implementation (in tools/toy_implementation/gene_splicing.ipynb) which
Expand All @@ -55,7 +63,19 @@ namespace modifications {
// We however set the fundamental of the power spectrum to a non-null value,
// otherwise, the mean value in the spliced region is unconstrained.
fields::Field<DataType,T> preconditioner(cov);

preconditioner.setFourierCoefficient(0, 0, 0, 1);
if (k_factor != 0) {
auto divide_by_k = [k_factor](std::complex<DataType> val, DataType kx, DataType ky, DataType kz){
DataType k2 = kx * kx + ky * ky + kz * kz;
if (k2 == 0 && k_factor < 0) {
return std::complex<DataType>(0, 0);
} else {
return val * DataType(pow(k2, k_factor));
}
};
preconditioner.forEachFourierCell(divide_by_k);
}

fields::Field<DataType,T> delta_diff = b-a;
delta_diff.applyTransferFunction(preconditioner, 0.5);
Expand Down Expand Up @@ -91,8 +111,14 @@ namespace modifications {
return v;
};


fields::Field<DataType,T> alpha = tools::numerics::conjugateGradient<DataType>(X,z);
fields::Field<DataType,T> alpha(z);
if (minimization_method == "CG") {
alpha = tools::numerics::conjugateGradient<DataType>(X, z, rtol, atol);
} else if (minimization_method == "MINRES") {
alpha = tools::numerics::minres<DataType>(X, z, rtol, atol, restart, brake_time);
} else {
throw std::runtime_error("Minimization method is invalid. Current implementations are CG and MINRES");
}

alpha.toFourier();
alpha.applyTransferFunction(preconditioner, 0.5);
Expand Down
23 changes: 16 additions & 7 deletions genetIC/src/tools/numerics/cg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#include <src/simulation/field/field.hpp>
#include <src/tools/data_types/complex.hpp>
#include <src/tools/logging.hpp>
#include <ctime>
#include <iostream>
#include <fstream>
#include <sys/stat.h>

namespace tools {
namespace numerics {
Expand All @@ -14,18 +18,22 @@ namespace tools {
fields::Field<T> conjugateGradient(std::function<fields::Field<T>(const fields::Field<T> &)> Q,
const fields::Field<T> &b,
double rtol = 1e-6,
double atol = 1e-12) {
double atol = 1e-12)
{
fields::Field<T> residual(b);
fields::Field<T> direction = -residual;
fields::Field<T> x = fields::Field<T>(b.getGrid(), false);

double scale = b.norm();
// double scaleNorm = b.norm();
double scaleMax = b.maximum();

if(scale==0.0) {
if(scaleMax==0.0) {
logging::entry(logging::warning) << "Conjugate gradient: result is zero!" << std::endl;
return x;
}

logging::entry() << "Splicing will stop when the maximum drops below " << rtol * scaleMax << std::endl;

size_t dimension = b.getGrid().size3;

size_t i;
Expand All @@ -40,11 +48,13 @@ namespace tools {
residual = Q(x);
residual -= b;

auto norm = residual.norm();
if (norm < rtol * scale || norm < atol)
// auto norm = residual.norm();
auto norm = residual.maximum();

if (norm < rtol * scaleMax || norm < atol)
break;

logging::entry() << "Conjugate gradient iteration " << i << " residual=" << norm << std::endl;
logging::entry() << "CG iteration " << i << " maximum=" << norm << std::endl;

// update direction for next cycle; must be Q-orthogonal to all previous updates
double beta = residual.innerProduct(Q_direction) / direction.innerProduct(Q_direction);
Expand All @@ -55,7 +65,6 @@ namespace tools {
logging::entry() << "Conjugate gradient ended after " << i << " iterations" << std::endl;

return x;

}
}
}
Expand Down
Loading
Loading