# HG changeset patch
# User Daniel Kraft
# Date 1393931450 -3600
# Node ID 76829daacb1251f674922f572ca99ea1e69db5cf
# Parent eaba4d4eaf1536bb5a85c6140855a67f0dacbe60
Extend feval function to support also passing the coordinates separately
as multiple arguments and evaluating the function at multiple
points at once.
diff -r eaba4d4eaf15 -r 76829daacb12 src/feval.cc
--- a/src/feval.cc Tue Mar 04 12:10:11 2014 +0100
+++ b/src/feval.cc Tue Mar 04 12:10:50 2014 +0100
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Marco Vassallo
+ Copyright (C) 2013-2014 Marco Vassallo
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -17,20 +17,48 @@
#include "function.h"
+/**
+ * Internal helper routine to evaluate the given function at a single
+ * point (as Array). Returned is the function value also as
+ * Array, which gets stored into the given array.
+ * too, so that they don't have to be constructed.
+ * @param f Dolfin function handle to evaluate.
+ * @param pt Point where we want to evaluate f as Octave array of coordinates.
+ * @param res Store the value here, should already be of the correct size.
+ */
+static void
+evaluate (const dolfin::Function& f, const Array& pt,
+ Array& res)
+{
+ Array& ptNonconst = const_cast&> (pt);
+ dolfin::Array x(ptNonconst.length (), ptNonconst.fortran_vec ());
+ dolfin::Array values(res.length (), res.fortran_vec ());
+
+ f.eval (values, x);
+}
+
DEFUN_DLD (feval, args, , "-*- texinfo -*-\n\
@deftypefn {Function File} address@hidden = \
feval (@var{function_name}, @var{Coordinate})\n\
address@hidden {Function File} address@hidden = \
+feval (@var{function_name}, @var{x}, @var{y})\n\
address@hidden {Function File} address@hidden = \
+feval (@var{function_name}, @var{x}, @var{y}, @var{z})\n\
Evaluate a function at a specific point of the domain and return the value. \n\
-The input parameters are the function and the point where it has to\
-be evaluated.\n\
+With only two arguments, @var{Coordinate} is assumed to be an array holding \n\
+the coordinates of the point where the function should be evaluated. With \n\
+three or more arguments, the coordinates are passed separately in @var{x}, \n\
address@hidden and optionally @var{z}. In the latter case and if the function \n\
+returns scalar values, @var{x}, @var{y} and @var{z} may also be arrays to \n\
+evaluate the function at multiple points at once.\n\
@seealso{Function}\n\
@end deftypefn")
{
int nargin = args.length ();
- octave_value retval=0;
+ octave_value retval = 0;
- if (nargin < 2 || nargin > 2)
+ if (nargin < 2)
print_usage ();
else
{
@@ -45,25 +73,68 @@
{
const function & fspo =
static_cast (args(0).get_rep ());
- Array point= args(1).array_value ();
+ const boost::shared_ptr
+ & f = fspo.get_pfun ();
+ dim_vector dims;
+ dims.resize (2);
+ dims(0) = 1;
+ dims(1) = f->value_dimension (0);
+ Array res(dims);
- if (!error_state)
+ if (nargin == 2)
{
- const boost::shared_ptr
- & f = fspo.get_pfun ();
- dim_vector dims;
- dims.resize (2);
- dims(0) = 1;
- dims(1) = f->value_dimension (0);
- Array res (dims);
- dolfin::Array x(point.length (), point.fortran_vec ());
- dolfin::Array values(res.length (), res.fortran_vec ());
+ Array point = args(1).array_value ();
+ if (!error_state)
+ {
+ evaluate (*f, point, res);
+ retval = octave_value (res);
+ }
+ }
+ else
+ {
+ dim_vector inDims;
+ inDims.resize (2);
+ inDims(0) = 1;
+ inDims(1) = nargin - 1;
+ Array point(inDims);
- f->eval (values, x);
+ std::vector > coords;
+ coords.reserve (inDims(1));
+ dim_vector argDims;
+ for (unsigned i = 1; i < nargin; ++i)
+ {
+ coords.push_back (args(i).array_value ());
+ const dim_vector curDims = coords.back ().dims ();
+ if (i > 1 && argDims != curDims)
+ {
+ error ("feval: coordinate dimensions mismatch");
+ break;
+ }
+ argDims = curDims;
+ }
- retval = octave_value (res);
+ if (res.nelem () != 1)
+ error ("feval: separate coordinate version only supported"
+ "for scalar functions");
+
+ if (!error_state)
+ {
+ Array retValArray(argDims);
+
+ for (size_t i = 0; i < retValArray.nelem (); ++i)
+ {
+ for (unsigned j = 0; j < coords.size (); ++j)
+ point(j) = coords[j].fortran_vec ()[i];
+
+ evaluate (*f, point, res);
+ retValArray.fortran_vec ()[i] = res(0);
+ }
+
+ retval = octave_value (retValArray);
+ }
}
}
}
+
return retval;
}