geoschem / geos-chem

GEOS-Chem "Science Codebase" repository. Contains GEOS-Chem science routines, run directory generation scripts, and interface code. This repository is used as a submodule within the GCClassic and GCHP wrappers, as well as in other modeling contexts (external ESMs).
http://geos-chem.org
Other
168 stars 165 forks source link

[FEATURE REQUEST] Building GEOS-Chem as a library in CMake #195

Closed jimmielin closed 3 years ago

jimmielin commented 4 years ago

Problem description

With the migration to CMake in GEOS-Chem 13+, it is important to consider that other coupled models (e.g. WRF, CESM2, BCC) are compiling GEOS-Chem as a library, based on the compile routines of the parent model. Their compile routines are likely not CMake-based.

Current status

Currently, WRF-GC compiles GEOS-Chem as a library using a compile call in the GEOS-Chem source code directory directly: (linebreak added for clarity)

FC=$(SFC) CC=$(SCC) F77=$(SFC) F90=$(SFC) CXX=$(OMPI_CXX) 
$(MAKE) $(J) NC_DIAG=y CHEM=Standard 
EXTERNAL_GRID=y DEBUG=n TRACEBACK=y MET=geos-fp GRID=4x5 NO_REDUCED=y UCX=yes NO_EXE=y hpc

Note the NO_EXE=y option, which override certain GEOS-Chem compile routines:

WRF then links to the modules and libraries built in the GEOS-Chem compile process to its main executable, through something like

-DLINUX_IFORT -DEXTERNAL_GRID -DNC_DIAG -DUCX -DGEOS_FP -DNC_HAS_COMPRESSION -DMODEL_ -DMODEL_WRF -DUSE_REAL8 -lGIGC $(MPI_OPT) -L$(ROOTDIR)/chem/gc/lib -lHistory -lGeosCore -lHistory -lKpp -lGeosCore -lIsorropia -lHCOI -lHCOX -lHCO -lGeosUtil -lKpp -lHeaders -lNcUtils -L$(NETCDFPATH) -lnetcdff -lnetcdf -L$(HDF5PATH)/lib -I$(ROOTDIR)/chem/gc/mod -lnetcdf

Feature request

Would it be possible to preserve some kind of similar functionality in GEOS-Chem built with CMake? The main requirements would be:

The way this is implemented is open to discussion but I just wanted to raise the issue before 13.0 is code frozen, as the removal of GNU Make will not allow compiling with some other models coupled to GEOS-Chem.

Thanks!

lizziel commented 4 years ago

This might fit in well with our plan to create a GEOS-Chem Classic wrapper repository for 13.0.0 that includes the GEOS-Chem and HEMCO repositories as submodules. The compilation of GC-Classic could be controlled at the highest level in the wrapper, like how it will also be done in the GCHP ctm wrapper. If other models use GEOS-Chem, all of that high-level build code will not be included.

There's still a lot to discuss about this, but does this sound like a good plan to address the issues in your use cases?

jimmielin commented 4 years ago

Hi Lizzie, indeed it is a good idea. I think like GCHP_ctm, we could have a structure like:

src/
   GeosCore/
   GeosUtil/
   HEMCO/
   ...
main.F
CMakeLists.txt

Where main.F is just linked to everything else in src/ to yield a final geos executable. Or if we want to make more drastic changes, this would be even more organized (or more confusing 🤣 ):

src/
    HEMCO/ @ submodule
    geos-chem/ @ submodule
main.F
jimmielin commented 4 years ago

Pinging @fritzt as this is relevant to all coupled models. Compiling CESM2 is more complex with a bunch of custom scripts so it may be necessary to design and build something that works for everyone before nuking GNU Make in 13.0.0 (which I absolutely support).

lizziel commented 4 years ago

I think main.F should still be in the src folder to keep all the source code together, but as you say, CMakeLists.txt driver would be at the same level as src/. This is how it is in GCHPctm, but with main.F renamed as GEOSchem.F90 right now (name may change).

jimmielin commented 4 years ago

Yes, it would make sense to have a structure that looks like GCHPctm so the hierarchies are not wildly different. It would make it easier for new developers to navigate through the code - it's important to keep the simplicity we have in the GEOS-Chem repo right now.

yantosca commented 4 years ago

FYI.... I believe that Cmake creates Makefiles that can be compiled via GNU Make. For example, this is the command to build GEOS-Chem classic.

cd geosfp_4x5_standard
mkdir gcbuild
cmake -S CodeDir -B gcbuild
make -C  CodeDir -j4 install

So note, the ```make -C```` command is I believe GNU Make syntax (unless I am wrong). Maybe @LiamBindle can confirm.

Just putting this here for reference.

LiamBindle commented 4 years ago

Hi everyone,

@jimmielin this is should be possible in 12.6. This is actually pretty similar to how GCHPctm's build works—GCHPctm does use CMake but it's ok if the super-project is Make-based. I agree this is important though, and any feedback would be appreciated!

@yantosca is on the right track. Note that the -C CodeDir arguments should be -C gcbuild though. You can set GC_EXTERNAL_CONFIG=TRUE to get control of GEOS-Chem's build configuration. This gives you complete control over the compiler flags and preprocessor definitions that are used, and the components that are built. Below is an example of commands that manually configure GeosCore's build, and then compile libGeosCore.a.

# Initialize cwd as your build directory and specify manual config
cmake -DGC_EXTERNAL_CONFIG=TRUE $GC_SOURCE_DIR

#  Set the compiler flags and definitions you want
cmake -DCMAKE_Fortran_FLAGS="-cpp -w -std=legacy -fautomatic -fno-align-commons -fconvert=big-endian -O3 -funroll-loops -DNC_HAS_COMPRESSION -DUSE_REAL8 -DUSE_TIMERS" .

# Turn off the components you don't need
cmake -DMECH=Standard -DTOMAS=OFF -DAPM=OFF -DRRTMG=OFF -DGTMM=OFF . 

# Build the GeosCore target (libGeosCore.a)
make -j GeosCore 

These worked ok for me with 12.6.3. Let me know if you run into any problems! If your super-project is Make-based, the idea is that you would run these commands in your Makefiles.

Note that the path to libGeosCore.a is GeosCore/libGeosCore.a (relative to your build directory). The install rules for libraries haven't been implemented, but this could be added if it would be a useful.

Note that you can put the build directory anywhere (including in the source code). The build directory is just where the generated Makefiles go. You can find the full list of CMake arguments here.

yantosca commented 3 years ago

I am going to close out this issue due to lack of recent activity. If you are still interested in pursuing this, let us know and we can reopen it.