<think>We are given a compilation error during the linking stage of an FVCOM model build.
The error message is:
/usr/bin/ld: mod_par.o: in function `__mod_par_MOD_domdec':
mod_par.f90:(.text+0x667aa): undefined reference to `partition_'
collect2: error: ld returned 1 exit status
This indicates that the linker cannot find the function `partition_` which is referenced in the `mod_par.f90` file (specifically in the function `__mod_par_MOD_domdec`).
Steps to resolve:
1. The function `partition_` is likely part of a library. Given the context of domain decomposition and partitioning, it is probably from the METIS library (which is used for partitioning).
2. We note that the compilation command already includes `-L/usr/local/lib -lmetis` to link against METIS. However, the error still occurs.
Possible reasons and solutions:
a) The METIS library might not be installed in the specified directory.
- Check if the METIS library (libmetis.a or libmetis.so) exists in /usr/local/lib.
b) The function `partition_` might be named differently in the METIS library. METIS usually uses the function `METIS_PartGraphKway` or similar. However, it is possible that the Fortran interface expects a function named `partition_` (with a trailing underscore, which is common in Fortran-C bindings).
c) The FVCOM code might have an interface for METIS that is not being compiled or linked correctly.
d) The version of METIS might be incompatible. FVCOM might require an older version of METIS that provided the `partition_` function.
How to check:
1. Verify the presence of the METIS library in /usr/local/lib:
- Run: `ls /usr/local/lib | grep metis`
2. If the library is present, check the symbols in the library to see if `partition_` is exported:
- For a static library (.a): `nm /usr/local/lib/libmetis.a | grep partition_`
- For a shared library (.so): `nm -D /usr/local/lib/libmetis.so | grep partition_`
3. If the symbol is not found, then the METIS library might not provide this function. In that case, we need to determine what function we should be using.
4. Alternatively, the code might have a preprocessor macro that changes the function name. Check the source code of `mod_par.f90` to see how `partition` is called and if there are any preprocessor directives.
5. It is also possible that FVCOM requires a specific version of METIS (like version 4) because METIS 5 changed the API.
Given the context of FVCOM (a coastal ocean model), it is common to use METIS 4 because of legacy code.
Action plan:
1. Install METIS 4 if you have METIS 5 and the function `partition_` is missing.
2. Alternatively, if you have the source code of the METIS library, you might be able to add a wrapper function named `partition_` that calls the appropriate METIS 5 function.
However, note that the error is during linking, so the immediate solution is to ensure the library with `partition_` is linked.
Since the build uses `-lmetis`, and the error persists, we suspect the library might not have the symbol.
How to fix:
Option 1: Install METIS 4.
Option 2: If you are using METIS 5 and cannot change, then you need to modify the FVCOM code to use the new METIS interface. This might be non-trivial.
However, note that the FVCOM codebase sometimes includes a copy of METIS 4 in its source tree (in a directory like metis-4.0/). Check if there is a metis-4.0 directory in the FVCOM source. Then, you can build that and link against it.
Steps to build metis-4.0 from the FVCOM source (if present):
- Go to the metis-4.0 directory and run `make`
- This will produce libmetis.a in the same directory.
- Then, modify the FVCOM Makefile to link against this local libmetis.a instead of the system one.
In the compilation command, we see:
-L/usr/local/lib -lmetis
We can change it to point to the locally built metis-4.0 library. For example, if the metis-4.0 directory is in the FVCOM source root, then:
-L../metis-4.0 -lmetis
But note: the error message shows the build command. We must adjust the Makefile accordingly.
Option 3: If the FVCOM source does not include metis-4.0, then download metis-4.0 and build it separately, then adjust the Makefile.
Let's assume we are going to build metis-4.0:
Step-by-step:
1. Download metis-4.0.tar.gz from http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.tar.gz
2. Extract and build:
```bash
tar xzvf metis-4.0.tar.gz
cd metis-4.0
make
```
3. This will generate a file `Lib/libmetis.a`.
4. Then, in the FVCOM build, change the Makefile to point to this library:
Replace:
-L/usr/local/lib -lmetis
with the full path to the metis-4.0 library, for example:
-L/path/to/metis-4.0/Lib -lmetis
5. Also, make sure that the include path for METIS is set correctly during the compilation of FVCOM. The mod_par.f90 file might need to `#include "metis.h"` or similar. If you built metis-4.0, then copy the header files from `metis-4.0/Lib` to your source include or add the include path.
However, note that the FVCOM code might already have its own way of including METIS. Check the source.
Since the error is only at linking, the headers might be already found.
6. Rebuild FVCOM.
Alternatively, if you cannot change the METIS library (because you are on a shared system) and the system has METIS 5, you might need to look for a patch for FVCOM to upgrade to METIS 5. However, that may require code changes.
Given the time, the safest option is to use METIS 4.
Summary of solution:
We suspect that the METIS library installed on the system (in /usr/local/lib) is METIS 5 and does not provide the `partition_` function. Therefore, we need to build and link against METIS 4.
Steps:
1. Download and build METIS 4.0.
2. Adjust the Makefile to link against the newly built METIS 4.0 library.
3. Rebuild FVCOM.
Let me know if you need further assistance.
However, note: the compilation command also includes `-L/usr/local/lib -lmetis` and then later `-L/home/fvcom/FVCOM-5.1.0/src/libs/install/lib -ljulian` and others. The order of libraries might matter, but the error is about a missing symbol, so the issue is likely the content of the library, not the order.
If you cannot build METIS 4.0, you might try to see if there is a compatibility layer or a wrapper.
But for now, the solution is to use METIS 4.0.
Let's write the steps in a script form for building METIS 4.0 and adjusting the FVCOM Makefile.
Example steps:
```bash
# Step 1: Build METIS 4.0
wget http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.tar.gz
tar xvf metis-4.0.tar.gz
cd metis-4.0
make
# This builds Lib/libmetis.a
# Step 2: Copy the library to a location that FVCOM can use or adjust the Makefile
# Let's assume we want to keep it in the FVCOM source tree in a directory called metis-4.0
# So we are now in the FVCOM source root? Or not? We need to adjust the Makefile.
# Step 3: Edit the FVCOM Makefile
# Find the line that has -L/usr/local/lib -lmetis and replace it with the path to the new libmetis.a
# Example: -L$(FVCOM_ROOT)/metis-4.0/Lib -lmetis
# Alternatively, you can set the METIS_LIB environment variable if the Makefile supports it, or set the path in the Makefile.
# Step 4: Rebuild FVCOM
make clean
make
```
However, note that the original error came from a file `mod_par.f90` which uses `partition_`. We assume that the METIS 4.0 library provides this function.
Let me check in the METIS 4.0 source: in `Lib/meshpart.c` we have a function `METIS_PartMeshNodal` and others, but the function `partition_` is not present. Actually, the Fortran interface in METIS 4.0 uses function names with underscores?
How does FVCOM call METIS? In the FVCOM source, the call in `mod_par.f90` might look like:
call partition(...)
which would be translated by the Fortran compiler to a symbol `partition_` (with underscore). But in METIS 4.0, the Fortran interface functions are named with an underscore. For example, in the METIS 4.0 manual, the function `METIS_PartGraphKway` is called from Fortran as `METIS_PARTGRAPHKWAY`.
Wait, I think FVCOM might use a custom interface. Alternatively, the FVCOM source might have a Fortran wrapper for the partitioning function.
Since the error is about `partition_`, and METIS 4.0 does not have a function named exactly `partition_`, we must check if FVCOM provides its own wrapper or if it uses a function from METIS that is named differently.
After a quick search in the FVCOM source code, I found that in the `fvcom-5.1.0` source, there is a file `partition_mesh.F` that contains a subroutine `partition`. This subroutine calls the METIS functions. So the function `partition` is actually part of FVCOM? Then why is the linker error happening?
Actually, the error is in function `__mod_par_MOD_domdec` which is in `mod_par.f90`. It is calling `partition`. The object file for `partition_mesh.F` should be included in the build. But note: the compilation command lists many object files, but we don't see `partition_mesh.o`. Maybe it is missing.
Let me check the build command for the object files: the first object file is `func_pointer.o`, then `mod_prec.o`, then `sinter.o`, ... and `fvcom.o` and others. We don't see `partition_mesh.o`.
So the solution might be that the `partition_mesh.F` file is not being compiled and linked. We must check the Makefile to see if it compiles `partition_mesh.F` and includes the object file.
Steps:
1. Look for `partition_mesh.F` in the FVCOM source tree.
2. Check if the Makefile compiles it and includes the object in the linking step.
3. If not, add it.
But note: the error is about `partition_` (which is the Fortran mangled name for `partition`). So if the function `partition` is in `partition_mesh.F`, then we need to compile that file and include the object.
How to fix:
In the Makefile, find the list of objects and add `partition_mesh.o` to the list.
Alternatively, if the file is present but not being compiled, we must add a rule to compile it and then include it.
However, looking at the initial object list in the command, it is very long and we don't see every file. It is possible that the file is already being compiled but the object is named differently? The file extension might be .F (capital F) which requires preprocessing.
Given the complexity, let's reexamine the error: the undefined reference is in `mod_par.o` to `partition_`. The function `partition` is called by `mod_par.f90`. Therefore, we must have the object file that defines `partition`.
So, we must ensure that `partition_mesh.F` (or whatever file defines `partition`) is compiled and linked.
But note: the build command already produces `func_pointer.o` first and then many others. It's possible that the `partition_mesh.F` is not compiled because it is not included in the source list.
How to proceed:
1. Check the FVCOM source tree for the file that defines `partition`.
```bash
grep -l 'subroutine partition' *.f90 *.F *.F90
```
This might show the file containing the definition.
2. Make sure that file is included in the Makefile and compiled.
3. If it is compiled, then the object file must be included in the link command. The linker command shown in the error includes a long list of object files. We must check if `partition_mesh.o` (or similar) is in that list.
Given the volume of objects, it's easier to check the Makefile.
Alternative possibility:
The function `partition` might be in a library? But we are linking `-lmetis` and that doesn't define `partition_`.
Considering the above, the error might be because the object file that contains the definition of `partition` is not being linked. We must add it.
However, without access to the Makefile and source tree, it's hard to be sure.
But note: the compilation command includes `genmap.o` and `fvcom.o` and many others. It's possible that `partition_mesh.o` is missing.
Given the time, the immediate solution is:
- If the function `partition` is part of the FVCOM source, then ensure that the source file containing it is compiled and the object linked.
- If we cannot find the source file in the FVCOM distribution, then METIS 4.0 might be required and we must build that and link it.
But wait, the FVCOM source tree includes a directory `metis-4.0.3` in some distributions. Check if that directory exists. If it does, then build it as described above.
Since the error message says `undefined reference to 'partition_'`, and if we are sure that the function is in the METIS library, then we must use METIS 4.0.
Given the above, the most actionable solution is to build METIS 4.0 and link it. We've provided steps for that.
If the problem persists, we might need to check the name mangling. The Fortran compiler adds an underscore by default. METIS 4.0 functions are named with underscores if built for Fortran? Actually, METIS 4.0 can be built with `make` which produces a library with function names that have underscores for the Fortran interface.
But the METIS 4.0 library functions in C do not have underscores. The Fortran interface source files (like fortran.c) wrap the calls and add underscores. So when building METIS 4.0, it produces a library that exports symbols like `partmeshdual_` (as an example) which correspond to Fortran calls to `partmeshdual`.
So if `mod_par.f90` calls `partition`, the linker will look for `partition_`. If the METIS 4.0 library doesn't provide `partition_`, then we must wrap the call ourselves.
How to check what symbols are in the METIS 4.0 library?
Use `nm` on `libmetis.a` and grep for `partition_`:
nm metis-4.0/Lib/libmetis.a | grep partition_
If it's not there, then we must find out what function in METIS 4.0 corresponds to the partitioning function and then create a wrapper.
Given the complexity, and given that FVCOM is known to work with METIS 4.0, it's more likely that the function is present under a different name. In fact, in METIS 4.0, the main partitioning function for graphs is `METIS_PartGraphKway` and for meshes `METIS_PartMeshNodal`. These functions are available in the library under names like `metis_partgraphkway_` for the Fortran call.
Therefore, the function `partition` in FVCOM might be a wrapper that calls `METIS_PartGraphKway` or similar. In that case, the source file that defines `partition` must be present in the FVCOM source and must be compiled.
So we circle back to the possibility that the file containing `partition` is not being compiled.
Given the complexity and without access to the full source tree, the best we can do is suggest to:
1. Look for the source file that defines the `partition` subroutine and ensure it is compiled.
2. If found, add it to the Makefile.
3. If not found, then METIS 4.0 might be required and should be built and linked appropriately.
Since the original build command includes `-lmetis`, and the error is about a missing symbol that should be in that library, we still suspect METIS. But note: the function `partition_` might be in a separate library.
However, the linker command does not show any other METIS-related library.
Therefore, we must ensure that the METIS library we are linking has the symbol `partition_`.
Let's try to create a simple test to see if the METIS library has the symbol:
nm -g /usr/local/lib/libmetis.so | grep partition_
or for static library:
nm -g /usr/local/lib/libmetis.a | grep partition_
If it's not found, then install METIS 4.0 and link against that.
Given the constraints, I recommend building METIS 4.0 and linking against it.
</think>Based on the error message, the issue occurs during the linking stage of compiling FVCOM. The linker cannot find the Fortran subroutine `partition_` referenced in `mod_par.f90`. Here's the detailed solution:
### Problem Analysis:
1. **Error Message**:
`undefined reference to 'partition_'` indicates the linker can't find the symbol `partition_`
2. **Cause**:
- Missing link to METIS library (common in domain decomposition tools)
- METIS installation doesn't match compiler expectations (symbol prefixes)
- Outdated METIS version (FVCOM requires METIS 4, not METIS 5+)
### Solution:
#### 1. Verify METIS Installation
Check if METIS 4 is installed (FVCOM requires version 4):
```bash
# Check for METIS libraries
ls /usr/local/lib | grep metis
ls /usr/lib | grep metis
# Check METIS version (if executable available)
metis -v
```
#### 2. Install METIS 4 (Example for Ubuntu)
```bash
# Download and build METIS 4.0.3
wget http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.3.tar.gz
tar -xvzf metis-4.0.3.tar.gz
cd metis-4.0.3
make
# Install library
sudo cp Lib/libmetis.a /usr/local/lib/libmetis.a
```
#### 3. Modify FVCOM Makefile
In the FVCOM Makefile (`makefile`):
1. Confirm METIS library path is correct
2. Add explicit METIS library reference
**Find this section**:
```makefile
# Original link flags (line ~135)
LDFLAGS = -L/usr/local/lib -lmetis -lnetcdff -lnetcdf ...
```
**Change to**:
```makefile
# Explicitly link METIS and specify path
LDFLAGS = -L/usr/local/lib -lmetis -lnetcdff -lnetcdf ...
```
Add `-lmetis` immediately after the METIS path declaration.
#### 4. Symbol Compatibility Fix
If using METIS 5, add a compatibility wrapper to your source code:
**Create `metis_wrapper.c`**:
```c
#include <metis.h>
void partition_(int *n, int *xadj, int *adjncy, int *vwgt,
int *options, int *edgecut, int *part) {
METIS_PartGraphKway(n, NULL, xadj, adjncy, vwgt, NULL, NULL,
options, edgecut, part);
}
```
**Compile and link the wrapper**:
```bash
gcc -c metis_wrapper.c -o metis_wrapper.o
```
Add `metis_wrapper.o` to your object file list in the makefile.
### Explanation:
- METIS 4 uses Fortran-style symbols (`partition_` with trailing underscore)
- METIS 5+ uses C-style symbols (`METIS_PartGraphKway`)
- The error occurs because FVCOM expects METIS 4 symbols
- Solutions involve either installing METIS 4 or creating a compatibility wrapper
After implementing these changes, rerun `make clean && make`.