1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// This file copyright (C) 2006 Andres Jordan <ajordan@eso.org>
// and Simon Casassus <simon@das.uchile.cl>
// All rights reserved. There is no warranty. You are allowed to
// redistribute this software/documentation under certain conditions.
// For details, see the file COPYING in the PDL distribution. If this file
// is separated from the PDL distribution, the copyright notice should be
// included in the file.
#include <gsl/gsl_vector.h>
#include <gsl/gsl_multiroots.h>
#include "EXTERN.h"
#include "perl.h"
#include "pdl.h"
#include "pdlcore.h"
#define PDL PDL_GSL_MROOT
extern Core *PDL;
static SV* ext_funname1;
static PDL_Indx ene;
void set_funname(SV *fn, PDL_Indx n) {
ext_funname1 = fn;
ene = n;
}
void DFF(double* xval, double* vector){
//this version tries just to get the output
dSP;
ENTER;
SAVETMPS;
pdl* px = PDL->pdlnew();
if (!px) PDL->pdl_barf("Failed to create pdl");
SV* pxsv = sv_newmortal();
PDL->SetSV_PDL(pxsv, px);
int ndims = 1;
PDL_Indx pdims[] = { (PDL_Indx) ene };
PDL->barf_if_error(PDL->setdims(px,pdims,ndims));
px->datatype = PDL_D;
px->data = (void *) xval;
px->state |= PDL_ALLOCATED | PDL_DONTTOUCHDATA;
/* get function name on the perl side */
PUSHMARK(SP);
XPUSHs(pxsv);
PUTBACK;
int count=call_sv(ext_funname1,G_SCALAR);
SPAGAIN;
SP -= count ;
I32 ax = (SP - PL_stack_base) + 1 ;
if (count!=1)
croak("error calling perl function\n");
/* recover output value */
pdl* pvector = PDL->SvPDLV(ST(0));
PDL->barf_if_error(PDL->make_physical(pvector));
double *xpass = (double *) pvector->data;
PDL_Indx i;
for(i=0;i<ene;i++) {
vector[i] = xpass[i];
}
px->data = NULL;
PUTBACK;
FREETMPS;
LEAVE;
}
int my_f (const gsl_vector * v, void * params, gsl_vector * df)
{
double dp = *((double *)params);
int nelem = (int) dp;
double xfree[nelem], vector[nelem];
int iloop;
for (iloop=0;iloop< nelem;iloop++) {
xfree[iloop] = gsl_vector_get(v, iloop);
vector[iloop] = gsl_vector_get(v, iloop) * gsl_vector_get(v, iloop);
}
DFF(xfree, vector);
for (iloop=0;iloop< nelem;iloop++) {
gsl_vector_set(df, iloop, vector[iloop]);
}
return GSL_SUCCESS;
}
int
print_state (size_t iter, gsl_multiroot_fsolver * s)
{
printf ("iter = %3zu x = % .3f % .3f "
"f(x) = % .3e % .3e\n",
iter,
gsl_vector_get (s->x, 0),
gsl_vector_get (s->x, 1),
gsl_vector_get (s->f, 0),
gsl_vector_get (s->f, 1));
return 1;
}
int fsolver (double *xfree, int nelem, double epsabs, int method)
{
gsl_multiroot_fsolver_type *T;
gsl_multiroot_fsolver *s;
int status;
size_t i, iter = 0;
size_t n = nelem;
double p[1] = { nelem };
int iloop;
// struct func_params p = {1.0, 10.0};
gsl_multiroot_function func = {&my_f, n, p};
gsl_vector *x = gsl_vector_alloc (n);
for (iloop=0;iloop<nelem; iloop++) {
//printf("in fsovler2D, C side, input is %g \n",xfree[iloop]);
gsl_vector_set (x, iloop, xfree[iloop]);
}
switch (method){
case 0 : T = (gsl_multiroot_fsolver_type *) gsl_multiroot_fsolver_hybrids; break;
case 1 : T = (gsl_multiroot_fsolver_type *) gsl_multiroot_fsolver_hybrid; break;
case 2 : T = (gsl_multiroot_fsolver_type *) gsl_multiroot_fsolver_dnewton; break;
case 3 : T = (gsl_multiroot_fsolver_type *) gsl_multiroot_fsolver_broyden; break;
default: return GSL_EINVAL; break;
}
s = gsl_multiroot_fsolver_alloc (T, nelem);
gsl_multiroot_fsolver_set (s, &func, x);
do
{
iter++;
//printf("GSL iter %d \n",iter);
status = gsl_multiroot_fsolver_iterate (s);
if (status) /* check if solver is stuck */
break;
status = gsl_multiroot_test_residual (s->f, epsabs);
}
while (status == GSL_CONTINUE && iter < 1000);
if (status)
warn ("Final status = %s\n", gsl_strerror (status));
for (iloop=0;iloop<nelem; iloop++) {
xfree[iloop] = gsl_vector_get (s->x, iloop);
}
gsl_multiroot_fsolver_free (s);
gsl_vector_free (x);
return GSL_SUCCESS;
}
|