comparison src/feval.cc @ 216:a28b50969020

New version of feval which accept a matrix or an array as points where the evaluation is done.
author gedeone-octave <marcovass89@hotmail.it>
date Wed, 05 Mar 2014 11:59:02 +0000
parents ca7eb016cf64
children b07ec30369ab
comparison
equal deleted inserted replaced
215:cdbf0263863b 216:a28b50969020
1 /* 1 /*
2 Copyright (C) 2013-2014 Marco Vassallo <gedeone-octave@users.sourceforge.net> 2 Copyright (C) 2013 Marco Vassallo <gedeone-octave@users.sourceforge.net>
3 3
4 This program is free software; you can redistribute it and/or modify it under 4 This program is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free Software 5 the terms of the GNU General Public License as published by the Free Software
6 Foundation; either version 3 of the License, or (at your option) any later 6 Foundation; either version 3 of the License, or (at your option) any later
7 version. 7 version.
15 this program; if not, see <http://www.gnu.org/licenses/>. 15 this program; if not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include "function.h" 18 #include "function.h"
19 19
20 /**
21 * Internal helper routine to evaluate the given function at a single
22 * point (as Array<double>). Returned is the function value also as
23 * Array<double>, which gets stored into the given array.
24 * too, so that they don't have to be constructed.
25 * @param f Dolfin function handle to evaluate.
26 * @param pt Point where we want to evaluate f as Octave array of coordinates.
27 * @param res Store the value here, should already be of the correct size.
28 */
29 static void
30 evaluate (const dolfin::Function& f, const Array<double>& pt,
31 Array<double>& res)
32 {
33 Array<double>& ptNonconst = const_cast<Array<double>&> (pt);
34 dolfin::Array<double> x(ptNonconst.length (), ptNonconst.fortran_vec ());
35 dolfin::Array<double> values(res.length (), res.fortran_vec ());
36
37 f.eval (values, x);
38 }
39
40 DEFUN_DLD (feval, args, , "-*- texinfo -*-\n\ 20 DEFUN_DLD (feval, args, , "-*- texinfo -*-\n\
41 @deftypefn {Function File} {[@var{value}]} = \ 21 @deftypefn {Function File} {[@var{value}]} = \
42 feval (@var{function_name}, @var{Coordinate})\n\ 22 feval (@var{function_name}, @var{Coordinate})\n\
43 @deftypefnx {Function File} {[@var{value}]} = \
44 feval (@var{function_name}, @var{x}, @var{y})\n\
45 @deftypefnx {Function File} {[@var{value}]} = \
46 feval (@var{function_name}, @var{x}, @var{y}, @var{z})\n\
47 Evaluate a function at a specific point of the domain and return the value. \n\ 23 Evaluate a function at a specific point of the domain and return the value. \n\
48 With only two arguments, @var{Coordinate} is assumed to be an array holding \n\ 24 The input parameters are the function and the point where it has to\
49 the coordinates of the point where the function should be evaluated. With \n\ 25 be evaluated.\n\
50 three or more arguments, the coordinates are passed separately in @var{x}, \n\ 26 The point can be either a vector or a matrix. If it is a matrix, each column\
51 @var{y} and optionally @var{z}. In the latter case and if the function \n\ 27 represents a different point at which we evaluates the function.\n\
52 returns scalar values, @var{x}, @var{y} and @var{z} may also be arrays to \n\
53 evaluate the function at multiple points at once.\n\
54 @seealso{Function}\n\ 28 @seealso{Function}\n\
55 @end deftypefn") 29 @end deftypefn")
56 { 30 {
57 31
58 int nargin = args.length (); 32 int nargin = args.length ();
59 octave_value retval = 0; 33 octave_value retval=0;
60 34
61 if (nargin < 2) 35 if (nargin < 2 || nargin > 2)
62 print_usage (); 36 print_usage ();
63 else 37 else
64 { 38 {
65 if (! function_type_loaded) 39 if (! function_type_loaded)
66 { 40 {
71 45
72 if (args(0).type_id () == function::static_type_id ()) 46 if (args(0).type_id () == function::static_type_id ())
73 { 47 {
74 const function & fspo = 48 const function & fspo =
75 static_cast<const function&> (args(0).get_rep ()); 49 static_cast<const function&> (args(0).get_rep ());
76 const boost::shared_ptr<const dolfin::Function> 50 Matrix point= args(1).matrix_value ();
77 & f = fspo.get_pfun ();
78 dim_vector dims;
79 dims.resize (2);
80 dims(0) = 1;
81 dims(1) = f->value_dimension (0);
82 Array<double> res(dims);
83 51
84 if (nargin == 2) 52 if (!error_state)
85 { 53 {
86 Array<double> point = args(1).array_value (); 54 const boost::shared_ptr<const dolfin::Function>
87 if (!error_state) 55 & f = fspo.get_pfun ();
56
57 if (point.rows () == 1)
58 point = point.transpose ();
59
60 dim_vector dims;
61 dims.resize (2);
62 dims(0) = f->value_dimension (0);
63 dims(1) = point.cols ();
64 Matrix res (dims);
65
66 dim_vector dims_tmp;
67 dims_tmp.resize (2);
68 dims_tmp(0) = f->value_dimension (0);
69 dims_tmp(1) = 1;
70 Array<double> res_tmp (dims_tmp);
71
72 for (uint i = 0; i < point.cols (); ++i)
88 { 73 {
89 evaluate (*f, point, res); 74 Array<double> point_tmp = point.column (i);
90 retval = octave_value (res); 75 dolfin::Array<double>
76 x (point_tmp.length (), point_tmp.fortran_vec ());
77 dolfin::Array<double>
78 values (res_tmp.length (), res_tmp.fortran_vec ());
79 f->eval (values, x);
80 for (uint j = 0; j < res_tmp.length (); ++j)
81 res(i, j) = res_tmp (j);
91 } 82 }
92 } 83 retval = octave_value (res);
93 else
94 {
95 dim_vector inDims;
96 inDims.resize (2);
97 inDims(0) = 1;
98 inDims(1) = nargin - 1;
99 Array<double> point(inDims);
100
101 std::vector<Array<double> > coords;
102 coords.reserve (inDims(1));
103 dim_vector argDims;
104 for (unsigned i = 1; i < nargin; ++i)
105 {
106 coords.push_back (args(i).array_value ());
107 const dim_vector curDims = coords.back ().dims ();
108 if (i > 1 && argDims != curDims)
109 {
110 error ("feval: coordinate dimensions mismatch");
111 break;
112 }
113 argDims = curDims;
114 }
115
116 if (res.nelem () != 1)
117 error ("feval: separate coordinate version only supported"
118 "for scalar functions");
119
120 if (!error_state)
121 {
122 Array<double> retValArray(argDims);
123
124 for (size_t i = 0; i < retValArray.nelem (); ++i)
125 {
126 for (unsigned j = 0; j < coords.size (); ++j)
127 point(j) = coords[j].fortran_vec ()[i];
128
129 evaluate (*f, point, res);
130 retValArray.fortran_vec ()[i] = res(0);
131 }
132
133 retval = octave_value (retValArray);
134 }
135 } 84 }
136 } 85 }
137 } 86 }
138
139 return retval; 87 return retval;
140 } 88 }