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

Feature libROM for reduced order modelling #1310

Merged
merged 31 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e31fecf
add librom data capture capability
jtlau Jun 22, 2021
b3d8f4c
bugfix
jtlau Jun 23, 2021
a9a1657
add librom support to meson build
jtlau Jun 23, 2021
daa7204
update number after adding librom
jtlau Jun 23, 2021
4d2b5cf
add librom params to config
jtlau Jun 23, 2021
fc2b49c
Merge branch 'feature_libROM' of https://github.com/su2code/SU2 into …
jtlau Jun 23, 2021
e88250a
Merge remote-tracking branch 'origin/develop' into feature_libROM
jtlau Jun 24, 2021
5c295ad
move librom bool to inside ifdef
jtlau Jun 24, 2021
e89cc36
remove commented code and unique ptr in destructor
jtlau Jun 28, 2021
1525388
Update Common/include/option_structure.hpp
jtlau Jun 28, 2021
4ed3d7f
update config class POD_KIND
jtlau Jun 28, 2021
8c09c8f
nodes to base_nodes
jtlau Jun 28, 2021
0e5ba98
update config params in librom function
jtlau Jun 28, 2021
689b4c4
use empty method to clean up ifdefs
jtlau Jun 29, 2021
e09b277
fix spacing
jtlau Jun 29, 2021
ad1914a
update messages for parallel
jtlau Jun 29, 2021
1d5feae
Update config_template.cfg
jtlau Jun 29, 2021
a5a8d18
local variables
jtlau Jun 29, 2021
874f096
clean up ifdefs
jtlau Jun 29, 2021
7c63f53
Update SU2_CFD/src/solvers/CSolver.cpp
jtlau Jun 29, 2021
ff927c5
Update SU2_CFD/src/solvers/CSolver.cpp
jtlau Jun 29, 2021
095bc0b
Update SU2_CFD/src/solvers/CSolver.cpp
jtlau Jun 29, 2021
f1bb21b
Update SU2_CFD/src/solvers/CSolver.cpp
jtlau Jun 29, 2021
29f27b9
update get solution call
jtlau Jun 29, 2021
975f08b
add save freq config option
jtlau Jun 29, 2021
f690ce2
Update Common/include/option_structure.hpp
pcarruscag Jun 30, 2021
04a8dfb
double -> su2double and static_cast instead of c-style (int)
pcarruscag Jun 30, 2021
bd9e5e9
bug: 2d -> 3d
jtlau Jul 12, 2021
7d11bbe
Merge branch 'feature_libROM' of https://github.com/su2code/SU2 into …
jtlau Jul 12, 2021
69387e7
fixes
jtlau Jul 13, 2021
7b2dc5b
Merge remote-tracking branch 'origin/develop' into feature_libROM
jtlau Jul 14, 2021
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
36 changes: 36 additions & 0 deletions Common/include/CConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,13 @@ class CConfig {
INLET_INTERP_TYPE Kind_Inlet_InterpolationType; /*!brief type of spanwise interpolation data to use for the inlet face. */
bool PrintInlet_InterpolatedData; /*!brief option for printing the interpolated data file. */

/*--- libROM configure options ---*/
bool libROM; /*!< \brief Toggle saving to libROM. */
string libROMbase_FileName; /*!< \brief Base filename for libROM file saving. */
POD_KIND POD_Basis_Gen; /*!< \brief Type of POD basis generation (static or incremental). */
unsigned short maxBasisDim, /*!< \brief Maximum number of POD basis dimensions. */
rom_save_freq; /*!< \brief Frequency of unsteady time steps to save. */

/* other NEMO configure options*/
unsigned short nSpecies, /*!< \brief No of species present in flow */
iWall_Catalytic,
Expand Down Expand Up @@ -9292,4 +9299,33 @@ class CConfig {
*/
short FindInterfaceMarker(unsigned short iInterface) const;

/*!
* \brief Get whether or not to save solution data to libROM.
* \return True if specified in config file.
*/
bool GetSave_libROM(void) const {return libROM; }

/*!
* \brief Get the name of the file for libROM to save.
* \return Filename prefix for libROM to save to (default: "su2").
*/
string GetlibROMbase_FileName(void) const { return libROMbase_FileName; }

/*!
* \brief Static or incremental toggle for POD basis generation type.
* \return Type of POD generation type
*/
POD_KIND GetKind_PODBasis(void) const { return POD_Basis_Gen; }

/*!
* \brief Get maximum number of POD basis dimensions (default: 100).
* \return Maximum number of POD basis vectors.
*/
unsigned short GetMax_BasisDim(void) const { return maxBasisDim; }

/*!
* \brief Get frequency of unsteady time steps to save (default: 1).
* \return Save frequency for unsteady time steps.
*/
unsigned short GetRom_SaveFreq(void) const { return rom_save_freq; }
};
12 changes: 12 additions & 0 deletions Common/include/option_structure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,18 @@ struct StreamwisePeriodicValues {
su2double Streamwise_Periodic_InletTemperature; /*!< \brief Area avg static Temp [K] at the periodic inlet. Used for adaptive outlet heatsink. */
};

/*!
* \brief Type of POD basis generation (for use with libROM)
*/
enum class POD_KIND {
STATIC, /*!< \brief Use static SVD for POD basis generation. */
INCREMENTAL, /*!< \brief Use incremental SVD for POD basis generation. */
};
static const MapType<std::string, POD_KIND> POD_Map = {
MakePair("STATIC_POD", POD_KIND::STATIC)
MakePair("INCREMENTAL_POD", POD_KIND::INCREMENTAL)
};

#undef MakePair
/* END_CONFIG_ENUMS */

Expand Down
19 changes: 19 additions & 0 deletions Common/src/CConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2778,6 +2778,25 @@ void CConfig::SetConfig_Options() {

/* DESCRIPTION: Size of the edge groups colored for thread parallel edge loops (0 forces the reducer strategy). */
addUnsignedLongOption("EDGE_COLORING_GROUP_SIZE", edgeColorGroupSize, 512);

/*--- options that are used for libROM ---*/
/*!\par CONFIG_CATEGORY:libROM options \ingroup Config*/

/*!\brief SAVE_LIBROM \n DESCRIPTION: Flag for saving data with libROM. */
addBoolOption("SAVE_LIBROM", libROM, false);

/*!\brief LIBROM_BASE_FILENAME \n DESCRIPTION: Output base file name for libROM \ingroup Config*/
addStringOption("LIBROM_BASE_FILENAME", libROMbase_FileName, string("su2"));

/*!\brief BASIS_GENERATION \n DESCRIPTION: Flag for saving data with libROM. */
addEnumOption("BASIS_GENERATION", POD_Basis_Gen, POD_Map, POD_KIND::STATIC);

/*!\brief MAX_BASIS_DIM \n DESCRIPTION: Maximum number of basis vectors.*/
addUnsignedShortOption("MAX_BASIS_DIM", maxBasisDim, 100);

/*!\brief MAX_BASIS_DIM \n DESCRIPTION: Maximum number of basis vectors.*/
addUnsignedShortOption("ROM_SAVE_FREQ", rom_save_freq, 1);

/* END_CONFIG_OPTIONS */

}
Expand Down
20 changes: 19 additions & 1 deletion SU2_CFD/include/solvers/CSolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
#include "../../../Common/include/toolboxes/MMS/CVerificationSolution.hpp"
#include "../variables/CVariable.hpp"

#ifdef HAVE_LIBROM
#include "BasisGenerator.h"
#include "QDEIM.h"
#include "DEIM.h"
#endif

using namespace std;

class CSolver {
Expand Down Expand Up @@ -196,6 +202,11 @@ class CSolver {
CVerificationSolution *VerificationSolution; /*!< \brief Verification solution class used within the solver. */

vector<string> fields;

#ifdef HAVE_LIBROM
std::unique_ptr<CAROM::BasisGenerator> u_basis_generator;
#endif

/*!
* \brief Constructor of the class.
*/
Expand Down Expand Up @@ -4326,7 +4337,14 @@ class CSolver {
* \return Struct holding 4 su2doubles.
*/
virtual StreamwisePeriodicValues GetStreamwisePeriodicValues() const { return StreamwisePeriodicValues(); }


/*!
* \brief Save snapshot or POD data using libROM
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] config - Definition of the particular problem.
* \param[in] converged - Whether or not solution has converged.
*/
void SavelibROM(CGeometry *geometry, CConfig *config, bool converged);

protected:
/*!
Expand Down
6 changes: 6 additions & 0 deletions SU2_CFD/src/drivers/CSinglezoneDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ void CSinglezoneDriver::StartSolver() {
/*--- Output the solution in files. ---*/

Output(TimeIter);

/*--- Save iteration solution for libROM ---*/
if (config_container[MESH_0]->GetSave_libROM()) {
solver_container[ZONE_0][INST_0][MESH_0][FLOW_SOL]->SavelibROM(geometry_container[ZONE_0][INST_0][MESH_0],
config_container[ZONE_0], StopCalc);
}

/*--- If the convergence criteria has been met, terminate the simulation. ---*/

Expand Down
91 changes: 90 additions & 1 deletion SU2_CFD/src/solvers/CSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ CSolver::~CSolver(void) {
delete [] Restart_Data;

delete VerificationSolution;

}

void CSolver::GetPeriodicCommCountAndType(const CConfig* config,
Expand Down Expand Up @@ -4212,3 +4211,93 @@ void CSolver::BasicLoadRestart(CGeometry *geometry, const CConfig *config, const
string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
}
}

void CSolver::SavelibROM(CGeometry *geometry, CConfig *config, bool converged) {

#if defined(HAVE_LIBROM) && !defined(CODI_FORWARD_TYPE) && !defined(CODI_REVERSE_TYPE)
const bool unsteady = config->GetTime_Domain();
const string filename = config->GetlibROMbase_FileName();
const unsigned long TimeIter = config->GetTimeIter();
const unsigned long nTimeIter = config->GetnTime_Iter();
const int maxBasisDim = config->GetMax_BasisDim();
const int save_freq = config->GetRom_SaveFreq();
int dim = int(nPointDomain * nVar);
bool incremental = false;

if (!u_basis_generator) {

/*--- Define SVD basis generator ---*/
auto timesteps = static_cast<int>(nTimeIter - TimeIter);
CAROM::Options svd_options = CAROM::Options(dim, timesteps, -1,
false, true).setMaxBasisDimension(int(maxBasisDim));

if (config->GetKind_PODBasis() == POD_KIND::STATIC) {
if (rank == MASTER_NODE) std::cout << "Creating static basis generator." << std::endl;

if (unsteady) {
if (rank == MASTER_NODE) std::cout << "Incremental basis generator recommended for unsteady simulations." << std::endl;
}
}
else {
if (rank == MASTER_NODE) std::cout << "Creating incremental basis generator." << std::endl;

svd_options.setIncrementalSVD(1.0e-3, config->GetDelta_UnstTime(),
1.0e-2, config->GetDelta_UnstTime()*nTimeIter, true).setDebugMode(false);
incremental = true;
}

u_basis_generator.reset(new CAROM::BasisGenerator(
svd_options, incremental,
filename));

// Save mesh ordering
std::ofstream f;
f.open(filename + "_mesh_" + to_string(rank) + ".csv");
for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
unsigned long globalPoint = geometry->nodes->GetGlobalIndex(iPoint);
auto Coord = geometry->nodes->GetCoord(iPoint);

for (unsigned long iDim; iDim < nDim; iDim++) {
f << Coord[iDim] << ", ";
}
f << globalPoint << "\n";
}
f.close();
}

if (unsteady && (TimeIter % save_freq == 0)) {
// give solution and time steps to libROM:
su2double dt = config->GetDelta_UnstTime();
su2double t = config->GetCurrent_UnstTime();
u_basis_generator->takeSample(const_cast<su2double*>(base_nodes->GetSolution().data()), t, dt);
}

/*--- End collection of data and save POD ---*/

if (converged) {

if (!unsteady) {
// dt is different for each node, so just use a placeholder dt
su2double dt = base_nodes->GetDelta_Time(0);
su2double t = dt*TimeIter;
u_basis_generator->takeSample(const_cast<su2double*>(base_nodes->GetSolution().data()), t, dt);
}

if (config->GetKind_PODBasis() == POD_KIND::STATIC) {
u_basis_generator->writeSnapshot();
}

if (rank == MASTER_NODE) std::cout << "Computing SVD" << std::endl;
int rom_dim = u_basis_generator->getSpatialBasis()->numColumns();

if (rank == MASTER_NODE) std::cout << "Basis dimension: " << rom_dim << std::endl;
u_basis_generator->endSamples();

if (rank == MASTER_NODE) std::cout << "ROM Sampling ended" << std::endl;
}

#else
SU2_MPI::Error("SU2 was not compiled with libROM support.", CURRENT_FUNCTION);
#endif

}
18 changes: 18 additions & 0 deletions config_template.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -1692,3 +1692,21 @@ DEFINITION_DV= ( 1, 1.0 | airfoil | 0, 0.05 ); ( 1, 1.0 | airfoil | 0, 0.10 ); (
%
% Use combined objective within gradient evaluation: may reduce cost to compute gradients when using the adjoint formulation.
OPT_COMBINE_OBJECTIVE = NO
%
% --------------------- LIBROM PARAMETERS -----------------------%
% LibROM can be found here: https://github.com/LLNL/libROM
%
% Toggle saving to librom (NO, YES)
SAVE_LIBROM = NO
%
% Prefix to the saved libROM files (default: su2)
LIBROM_BASE_FILENAME = su2
%
% Specify POD basis generation algorithm (STATIC_POD, INCREMENTAL_POD)
% STATIC_POD recommended for steady problems
BASIS_GENERATION = STATIC_POD
%
% Maximum number of basis vectors to keep (default: 100)
MAX_BASIS_DIM = 100
%

29 changes: 27 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,21 @@ elif get_option('enable-openblas')

endif

if get_option('enable-librom')

assert(get_option('librom_root')!='',
'Must specify librom folder (-Dlibrom_root=path/to/libROM)')
pcarruscag marked this conversation as resolved.
Show resolved Hide resolved

su2_cpp_args += '-DHAVE_LIBROM'

librom_root = get_option('librom_root')
librom_dep = declare_dependency(include_directories: librom_root,
link_args: ['-L'+librom_root+'/build', '-lROM'])

su2_deps += librom_dep

endif

extra_deps = get_option('extra-deps').split(',')
foreach dep : extra_deps
if dep != ''
Expand Down Expand Up @@ -234,6 +249,7 @@ message('''---------------------------------------------------------------------
OpenBlas: @8@
PaStiX: @9@
Mixed Float: @10@
libROM: @11@

Please be sure to add the $SU2_HOME and $SU2_RUN environment variables,
and update your $PATH (and $PYTHONPATH if applicable) with $SU2_RUN
Expand All @@ -245,10 +261,10 @@ message('''---------------------------------------------------------------------
export PATH=$PATH:$SU2_RUN
export PYTHONPATH=$PYTHONPATH:$SU2_RUN

Use './ninja -C @11@ install' to compile and install SU2
Use './ninja -C @12@ install' to compile and install SU2
'''.format(get_option('prefix')+'/bin', meson.source_root(), get_option('enable-tecio'), get_option('enable-cgns'),
get_option('enable-autodiff'), get_option('enable-directdiff'), get_option('enable-pywrapper'), get_option('enable-mkl'),
get_option('enable-openblas'), get_option('enable-pastix'), get_option('enable-mixedprec'), meson.build_root().split('/')[-1]))
get_option('enable-openblas'), get_option('enable-pastix'), get_option('enable-mixedprec'), get_option('enable-librom'), meson.build_root().split('/')[-1]))

if get_option('enable-mpp')
message(''' To run SU2 with Mutation++ library, add these lines to your .bashrc file:
Expand All @@ -258,3 +274,12 @@ if get_option('enable-mpp')

''')
endif

if get_option('enable-librom')
message(''' To run SU2 with libROM library, add this line to your .bashrc file:

export LD_LIBRARY_PATH=@0@/build/:$LD_LIBRARY_PATH

'''.format(get_option('librom_root')))

endif
2 changes: 2 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ option('enable-mixedprec', type : 'boolean', value : false, description: 'use si
option('extra-deps', type : 'string', value : '', description: 'comma-separated list of extra (custom) dependencies to add for compilation')
option('enable-mpp', type : 'boolean', value : false, description: 'enable Mutation++ support')
option('opdi-backend', type : 'combo', choices : ['auto', 'macro', 'ompt'], value : 'auto', description: 'OpDiLib backend choice')
option('librom_root', type : 'string', value : '', description: 'libROM base directory')
option('enable-librom', type : 'boolean', value : false, description: 'enable LLNL libROM support')