nextsimhub / nextsimdg

neXtSIM_DG : next generation sea-ice model with DG
https://nextsim-dg.readthedocs.io/en/latest/?badge=latest
Apache License 2.0
10 stars 13 forks source link

Melt/issue378 dynamicsswitcher2 #498

Closed TomMelt closed 4 months ago

TomMelt commented 4 months ago

@timspainNERSC was getting an error when trying to compile branch relating to undefined references:

/usr/bin/ld: ../../libnextsimlib.so: undefined reference to `Eigen::Matrix<double, ((2)==(1))?(4) : (9), 1, ((Eigen::StorageOptions)0)|((((((2)==(1))?(4) : (9))==(1))&&((1)!=(1)))?((Eigen::StorageOptions)1) : ((((1)==(1))&&((((2)==(1))?(4) : (9))!=(1)))?((Eigen::StorageOptions)0) :
 ((Eigen::StorageOptions)0))), ((2)==(1))?(4) : (9), 1> Nextsim::cgLocal<2>(Nextsim::CGVector<2> const&, int, int)'                          
collect2: error: ld returned 1 exit status

This PR fixes the issue.

The key was missing template<> specifier.

https://github.com/nextsimhub/nextsimdg/blob/281915017acc8e659a688d78bc9e7c3a2a2d4697/dynamics/src/CGDynamicsKernel.cpp#L113

I'll be honest I am not super familiar with template specialization. I believe what you were trying to do is called Explicit specializations of function templates (but don't quote me on it).

When compiling with g++ I also had to make the using statements public in the kernel headers. I am not sure that this is necessary. I didn't try all combinations to see if I could just expose some and not all. So you might want to check this yourself.

FYI I used the following mwe to figure it out. Compile and run with g++ test.cpp && ./a.out

test.cpp ```cpp #include #include using std::cout; template struct Vector { int array[S]; }; template<> struct Vector<1>{ int array[1]; }; template<> struct Vector<2>{ float darry[2]; }; template< size_t n > Vector foo( ) { Vector x; for (size_t i = 0; i < n; ++i) { x.array[i] = (i+1)*(i+1); } return x; } template<> Vector<1> foo( ) { Vector<1> x; for (size_t i = 0; i < 1; ++i) { x.array[i] = (i+1)*(i+1); } return x; } template<> Vector<2> foo( ) { Vector<2> x; for (size_t i = 0; i < 2; ++i) { x.darry[i] = (i+1)*(i+1) + 0.5; } return x; } int main() { cout << "1=" << foo<1>().array[0] << ", 2=" << foo<2>().darry[0] << ", "<< foo<2>().darry[1] << "\n"; } ```