I am not going to tell what DASSL is; since you've continued past the semicolon, I'll just assume you already know that. What I am going to tell you here is how you can go about calling DASSL, which is written in FORTRAN, from within a C++ program. If any of this matters to you, you may read on.
I've written this howto out of my own experience. For a simulation application I'm writing, I needed to call DASSL from within Microsoft Visual C++ 6.0; and I didn't know how to do that. I searched for days over the Internet but found only scattered pieces of information that each, taken alone, was of as much use to me as a pair of low-rise jeans is to a dining table. Yet, I continued to experiment and try all sorts of things (some of which can't be mentioned in a polite gathering); and so it went on for a week. Then, after all the efforts, one day, a call to DASSL went through -- just like that. The code ran without a hitch.
And as I sat there shouting, "Yoo hoo. Sweet bleedin' mama", I knew, the way had been found.
So, since I've been there and done all that, you can appreciate that I understand your pain very well. And as a pioneer, I feel but bound to share my experience in a simple, step-by-step format to spare you, and all those yet to be born, any more undeserved distress.
Take heart ye all, for the fort of Calling DASSL from C++ has been taken.
Okay, without any further ado and bad metaphors, comerades, here down to business we get:
First, assumptions and other prologue-y things:
1) DASSL is written in FORTRAN. I don't know if it's FORTRAN 77, FORTRAN 95 or FORTRAN TWO THOUSAND AND FIFTY FOUR. It makes no difference to what we are trying to achieve here.
2) I work on Microsoft Visual C++ 6.0 (MSVC6) on Windows XP. So whatever I say here applies to this platform alone. I'm not sure if this works with GCC and Unix or even the old versions of Windows and MSCV; but I believe whatever I did in my case would not be too different from what you’ll need to do on your platform. So, if you have to, adapt this howto to your needs.
3) My FORTRAN compiler is g95. It’s a free, open-source compiler. FORTRAN compilers vary in how they decorate compiled code and all that. I do not claim knowledge about all those issues. I used g95 and was happy. You will be too; take my word.
4) Three flavours of DASSL are available: DASKR, DASPK and DASSL. In this howto I shall use the name DASSL, irrespective of which of the three you're using. What I say here applies to all of them equally well.
So that’s that. Let’s now get on with how actually to do it.
The steps for making it happen:1) Download the DASSL source code from
here. Choose DASKR, DASPK, or DASSL as per your requirements. The procedure for calling them from MSVC is exactly the same, except, of course, the signature of the function call in each case.
After downloading the zipped file (
ddassl.tgz), unzip it. You’ll now have a folder called DASSL with the following files in it:
daux.f,
ddassl.f, and
dlinpk.f.
2) Download g95 from
this place. Follow the instructions on the g95
website and install it.
3) Next, you need to compile the DASSL code with g95. Go to the DASSL folder, compile the three files with the following command:
g95 –c daux.f ddassl.f dlinpkAfter compilation you’ll find three new, object files in the same folder:
daux.o,
ddassl.o, and
dlinpk.o. The option “
-c” ensures that g95 merely compiles the three files and does not attempt to link them together. We’ll be doing the linking job later with MSVC.
4) Create your C++ project in MSVC6. Declare the DASSL call in C++. In my case the declaration looked like this:
extern "C" void ddassl_(
void (*funcptr)(const double& time, const double y[], const double yPrime[], double residue[], int& iRes, const double rPar[], const int iPar[]),
const int& noOfEquations,
const double& currentTime,
const double initialY[],
const double initialYPrime[],
const double& finalTime,
const int info[15],
const double& relativeTolerance,
const double& absoluteTolerance,
int& outputStatusFlag,
const double dWorkArray[],
const int& lengthOfDWork,
const int iWorkArray[],
const int& lengthOfIWork,
const double rParArray[],
const int iParArray[],
void (*jacobian)(const double& time, const double y[], const double yPrime[], double** PD, double& CJ, double rPar[], int iPar[])
);There are two important aspects of this declaration. First, the declaration is preceded with an
extern "C". You need this to avoid name mangling which C++ compilers do. Second, the function name
ddassl is suffixed with an underscore. This is important owing to function name issues involved in calling FORTRAN and C++ code from each other. Since I stumbled upon al this by hit and trial, don't expect reasons for this. It works, and that's enough.
The rest of the declaration is nothing remarkable. Read your DASSL documentation to understand it.
5) Next, copy the three object files obtained in step 3 to the folder where your above-mentioned MSVC6 project lies (let's call it the 'project folder'). Also go to the folder where g95 is installed. Once in the g95 folder, follow this path: \lib\gcc-lib\i686-pc-mingw32\4.0.2. In the folder 4.0.2 find two files:
libf95.a and
libgcc.a. Copy them to the project folder. Now, apart from the C++ files and MSVC files, you have the following files in the project folder:
daux.o,
ddassl.o,
dlinpk.o,
libf95.a and
libgcc.a. We're going to need these files for linking.
6) Open your C++ prject. Go to Project->Settings->link. Under the field "Object/library modules", enter this:
daux.o,
ddassl.o,
dlinpk.o,
libf95.a,
libgcc.a. This step adds the requisite libraries and object files the MSVC6 linker is going to need.
7) You're ready to link now. Run the MSVC6 linker. It'll first -- of course -- compile the C++ code and then link it with the above mentioned 5 files.
8) Your work is done. Now call DASSL with apropriate arguments. It should run without problem.
9) Let out a sigh of relief. Go get yourself coffee. Come back. Backslap the dude sitting next to you and ask, "Isn't it a lovely motherfuckin' day, my friend?".
Last words:
I did this exactly as I've described. If it doesn't work for you, you can write to me the email address: gurry_uor at yahoo dot co dot uk. I might also in haste have made mistakes above; point them out to me.
Another friendly tip: your simulation is most likely to be a hybrid simulation. What that means is that you have at least one variable which, with time, goes through a variation which is either discontinuous or its first derivative is discontinuous. DASSL, let it be known, cannot reliably integrate past such discontinuities in the zeroth and the first order. So you'll have to stop your integration whenever any discontinuity is encountered, then reset the initial conditions and then restart it. All major simulation software packages do that; you shall have to too. Read
this book for more information.
Though I've focussed on DASSL here, you can use the same approach as above to call
any FORTRAN function from MSVC6. I'm sure the astute reader -- look how the rascal's smiling -- would have figured that out already.
Allright, I hope this helps. Google spiders will pick this page up the next month and I hope troubled souls with DASSL afflictions like mine shall then come and find solace here.
I'm outta here.