In 2024, Alex Bercik tried updating the code to work with the 2022 Niagara environment and compilers. In general, these compilers are stricter (i.e. catch more bugs) and ~in theory~ produce more optimized code. While this works for the majority of Jetstream, significant challenges were encountered with TACS. These are summarized below.
The compilation with 2022 compilers fails because of how the TACSFunction is defined in TACS_typemaps.i, where we let TACSFunction be polymorphic through specifying it as "class(TACSFunction)" instead of "type(TACSFunction)". A comment above this line written by Tom Reist says that this is because the TACSFunction class is extended by other objects in C++ like KSFailure, StructuralMass, etc., and this code needs to be able to handle them all.
Unfortunately, the fortran code in TACSWrapper.f90 generated by TACS_typemaps.i contains the line "farg2 = c_loc(funcs)", where we have defined
class(TACSFunction), dimension(:), target :: funcs
type(C_PTR) :: farg2
This primarily comes from the following line TACS_typemaps.i
%typemap(fin) DOUBLE_POINTER
"$1 = c_loc($input)”
(You can make a separate "%typemap(fin) TACS_FUNCTION" but the result is the same)
The main problem is, (as raised by the compiler) “the argument to c_loc must not be polymorphic". This error is raised by the 2022 compiler, even though very strangely it doesn’t get raised by the 2019 compiler. So far I have been unable to find a workaround. I don’t see how to set the C++ pointer farg2 from the polymorphic Fortran target funcs - it seems one way or another we have to use c_loc.
The simplest idea was to compile TACS with 2019 compilers and the rest of the code with 2022 compilers, but this leads to memory issues. The TACS objects fVec, uVec, and xVec should point to the same memory adress as the fortran arrays f_tacs, u_tacs, and x_tacs, but this was not working, eventually leading to PETSc errors.
Another idea was to use type(TACSFunction) instead of class(TACSFunction), essentially assuming that it was indeed monomorphic, but then unsurprisingly this leads to errors when compiling our Fortran code because subroutines called with KSFailure have arguments of the wrong type (i.e. not TACSFunction).
Other ideas involved either complicating the TACS_typemaps.i file and trying to write dedicated helper functions, or simply setting farg2 = funcs, but all of these ideas failed too.
The same issue persisted with several different versions of TACS and SWIG, as well.
The solution is to rewrite the SWIG wrappers. A couple notes:
Since that’s a lot of work, for now the temporary solution is simply that the main group uses the 2022 compilers, and whoever needs to work with TACS sticks with the 2019 compilers.
If at some point you (yes you reading this page) decide to fix it, I would also take it as an opportunity to upgrade TACS. TACS underwent a major API rewrite which, when Tom Reist and Cindy looked at upgrading, would have meant the SWIG interface would have needed to be updated. If you need to update the wrappers, I would recommend taking it as an opportunity to do it for the newer TACS API.
You could also reevaluate the approach of calling TACS (C++) directly from Jetstream (Fortran), and look at setting up a separate layer, e.g. Python, that could call both. When Tom Reist went the SWIG path (so that we could call TACS directly from Jetstream) it was to make the use of aerostructural as seamless for the user as possible (it is just additional lines in the input.param and input files) instead of a completely different front end and workflow (e.g. Like what Jenmy had with Python), as well as to use as much of Jetstream's capabilities verbatim as possible. SWIG-Fortran is indeed a bit of a headache to get working (although it seems like they now have a much better user manual! When Tom put the wrappers together there was no good SWIG-Fortran documentation, and he had to cobble things together by inferring relations from code examples, etc.) Hopefully they've invested in SWIG-Fortran.
As one more potential solution, the main developers of TACS have since moved away from using SWIG towards cython since it provides more complete support for C++ and is easier to use. The open source TACS has cython wrappers on GitHub, which are comprehensive. It might be best to use that as a guide for rewriting our wrappers.