/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Annotation of /trunk/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 122 - (hide annotations)
Thu Jun 9 05:38:05 2005 UTC (14 years, 5 months ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.h
File MIME type: text/plain
File size: 35806 byte(s)
Merge of development branch back to main trunk on 2005-06-09

1 jgs 94 // $Id$
2 jgs 121 /*
3 jgs 94 ******************************************************************************
4     * *
5     * COPYRIGHT ACcESS 2004 - All Rights Reserved *
6     * *
7     * This software is the property of ACcESS. No part of this code *
8     * may be copied in any form or by any means without the expressed written *
9     * consent of ACcESS. Copying, use or modification of this software *
10     * by any unauthorised person is illegal unless that *
11     * person has a software license agreement with ACcESS. *
12     * *
13     ******************************************************************************
14 jgs 121 */
15 jgs 94
16 jgs 121 /** \file Data.h */
17 jgs 94
18     #ifndef DATA_H
19     #define DATA_H
20    
21     #include "escript/Data/DataAbstract.h"
22     #include "escript/Data/DataTagged.h"
23 jgs 122 #include "escript/Data/DataAlgorithm.h"
24 jgs 94 #include "escript/Data/FunctionSpace.h"
25     #include "escript/Data/BinaryOp.h"
26     #include "escript/Data/UnaryOp.h"
27 jgs 108 #include "escript/Data/DataException.h"
28 jgs 94
29     extern "C" {
30     #include "escript/Data/DataC.h"
31     }
32    
33     #include <iostream>
34     #include <string>
35     #include <memory>
36     #include <algorithm>
37    
38     #include <boost/shared_ptr.hpp>
39     #include <boost/python/object.hpp>
40     #include <boost/python/list.hpp>
41     #include <boost/python/tuple.hpp>
42     #include <boost/python/numeric.hpp>
43    
44 jgs 121 namespace escript {
45    
46     //
47     // Forward declaration for various implimentations of Data.
48     class DataEmpty;
49     class DataConstant;
50     class DataTagged;
51     class DataExpanded;
52    
53 jgs 94 /**
54     \brief
55 jgs 121 Data creates the appropriate Data object for the given construction
56     arguments.
57 jgs 94
58     Description:
59     Data is essentially a factory class which creates the appropriate Data
60     object for the given construction arguments. It retains control over
61     the object created for the lifetime of the object.
62     The type of Data object referred to may change during the lifetime of
63     the Data object.
64     */
65     class Data {
66    
67     public:
68    
69 jgs 110 // These typedefs allow function names to be cast to pointers
70     // to functions of the appropriate type when calling unaryOp etc.
71 jgs 94 typedef double (*UnaryDFunPtr)(double);
72     typedef double (*BinaryDFunPtr)(double,double);
73    
74     /**
75 jgs 102 Constructors.
76     */
77    
78     /**
79 jgs 94 \brief
80     Default constructor.
81     Creates a DataEmpty object.
82     */
83     Data();
84    
85     /**
86     \brief
87     Copy constructor.
88     WARNING: Only performs a shallow copy.
89     */
90     Data(const Data& inData);
91    
92     /**
93     \brief
94     Constructor from another Data object. If "what" is different from the
95 jgs 102 function space of inData the inData are tried to be interpolated to what,
96 jgs 94 otherwise a shallow copy of inData is returned.
97     */
98     Data(const Data& inData,
99     const FunctionSpace& what);
100    
101     /**
102     \brief
103     Constructor which copies data from a DataArrayView.
104    
105     \param value - Input - Data value for a single point.
106     \param what - Input - A description of what this data represents.
107     \param expanded - Input - Flag, if true fill the entire container with
108     the value. Otherwise a more efficient storage
109     mechanism will be used.
110     */
111     Data(const DataArrayView& value,
112     const FunctionSpace& what=FunctionSpace(),
113     bool expanded=false);
114    
115     /**
116     \brief
117     Constructor which creates a Data from a DataArrayView shape.
118    
119     \param value - Input - Single value applied to all Data.
120     \param dataPointShape - Input - The shape of each data point.
121     \param what - Input - A description of what this data represents.
122     \param expanded - Input - Flag, if true fill the entire container with
123     the given value. Otherwise a more efficient storage
124     mechanism will be used.
125     */
126     Data(double value,
127     const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),
128     const FunctionSpace& what=FunctionSpace(),
129     bool expanded=false);
130    
131     /**
132     \brief
133     Constructor which performs a deep copy of a region from another Data object.
134    
135     \param inData - Input - Input Data object.
136     \param region - Input - Region to copy.
137     */
138     Data(const Data& inData,
139     const DataArrayView::RegionType& region);
140    
141     /**
142     \brief
143     Constructor which will create Tagged data if expanded is false.
144     No attempt is made to ensure the tag keys match the tag keys
145     within the function space.
146    
147     \param tagKeys - Input - List of tag values.
148     \param values - Input - List of values, one for each tag.
149     \param defaultValue - Input - A default value, used if tag doesn't exist.
150     \param what - Input - A description of what this data represents.
151     \param expanded - Input - Flag, if true fill the entire container with
152     the appropriate values.
153     */
154     Data(const DataTagged::TagListType& tagKeys,
155     const DataTagged::ValueListType& values,
156     const DataArrayView& defaultValue,
157     const FunctionSpace& what=FunctionSpace(),
158     bool expanded=false);
159    
160     /**
161     \brief
162     Constructor which copies data from a python numarray.
163    
164     \param value - Input - Data value for a single point.
165     \param what - Input - A description of what this data represents.
166     \param expanded - Input - Flag, if true fill the entire container with
167     the value. Otherwise a more efficient storage
168     mechanism will be used.
169     */
170     Data(const boost::python::numeric::array& value,
171     const FunctionSpace& what=FunctionSpace(),
172     bool expanded=false);
173    
174     /**
175     \brief
176     Constructor which copies data from any object that can be converted into
177     a python numarray.
178    
179     \param value - Input - Input data.
180     \param what - Input - A description of what this data represents.
181     \param expanded - Input - Flag, if true fill the entire container with
182     the value. Otherwise a more efficient storage
183     mechanism will be used.
184     */
185     Data(const boost::python::object& value,
186     const FunctionSpace& what=FunctionSpace(),
187     bool expanded=false);
188    
189     /**
190     \brief
191     Constructor which creates a DataConstant.
192     Copies data from any object that can be converted
193     into a numarray. All other parameters are copied from other.
194    
195     \param value - Input - Input data.
196     \param other - Input - contains all other parameters.
197     */
198     Data(const boost::python::object& value,
199     const Data& other);
200    
201     /**
202     \brief
203     Constructor which creates a DataConstant of "shape" with constant value.
204     */
205     Data(double value,
206     const boost::python::tuple& shape=boost::python::make_tuple(),
207     const FunctionSpace& what=FunctionSpace(),
208     bool expanded=false);
209    
210     /**
211     \brief
212 jgs 102 Perform a deep copy.
213 jgs 94 */
214     void
215 jgs 102 copy(const Data& other);
216 jgs 94
217     /**
218 jgs 102 Member access methods.
219 jgs 94 */
220    
221     /**
222     \brief
223 jgs 121 Return the values of all data-points as a single python numarray object.
224 jgs 117 */
225 jgs 121 const boost::python::numeric::array
226 jgs 117 convertToNumArray();
227    
228     /**
229     \brief
230 jgs 121 Return the values of all data-points for the given sample as a single python numarray object.
231     */
232     const boost::python::numeric::array
233     convertToNumArrayFromSampleNo(int sampleNo);
234    
235     /**
236     \brief
237     Return the value of the specified data-point as a single python numarray object.
238     */
239     const boost::python::numeric::array
240     convertToNumArrayFromDPNo(int sampleNo,
241     int dataPointNo);
242    
243     /**
244     \brief
245 jgs 94 Return the C wrapper for the Data object.
246     */
247 jgs 102 escriptDataC
248     getDataC();
249 jgs 94
250     /**
251     \brief
252     Return the C wrapper for the Data object - const version.
253     */
254 jgs 102 escriptDataC
255     getDataC() const;
256 jgs 94
257     /**
258     \brief
259     Write the data as a string.
260     */
261 jgs 102 inline
262     std::string
263     toString() const
264     {
265     return m_data->toString();
266     }
267 jgs 94
268     /**
269     \brief
270     Return the DataArrayView of the point data. This essentially contains
271     the shape information for each data point although it also may be used
272     to manipulate the point data.
273     */
274     inline
275     const DataArrayView&
276     getPointDataView() const
277     {
278     return m_data->getPointDataView();
279     }
280    
281     /**
282     \brief
283 jgs 102 Whatever the current Data type make this into a DataExpanded.
284 jgs 94 */
285     void
286     expand();
287    
288     /**
289     \brief
290 jgs 102 If possible convert this Data to DataTagged. This will only allow
291 jgs 94 Constant data to be converted to tagged. An attempt to convert
292     Expanded data to tagged will throw an exception.
293     */
294     void
295     tag();
296    
297     /**
298     \brief
299     Return true if this Data is expanded.
300     */
301     bool
302     isExpanded() const;
303    
304     /**
305     \brief
306     Return true if this Data is tagged.
307     */
308     bool
309     isTagged() const;
310    
311     /**
312     \brief
313 jgs 102 Return true if this Data is constant.
314 jgs 94 */
315     bool
316 jgs 102 isConstant() const;
317 jgs 94
318     /**
319     \brief
320 jgs 102 Return true if this Data is empty.
321 jgs 94 */
322     bool
323 jgs 102 isEmpty() const;
324 jgs 94
325     /**
326     \brief
327     Return the function space.
328     */
329     inline
330     const FunctionSpace&
331     getFunctionSpace() const
332     {
333     return m_data->getFunctionSpace();
334     }
335    
336     /**
337     \brief
338     Return a copy of the function space.
339     */
340     const FunctionSpace
341     getCopyOfFunctionSpace() const;
342    
343     /**
344     \brief
345     Return the domain.
346     */
347     inline
348     const AbstractDomain&
349     getDomain() const
350     {
351     return getFunctionSpace().getDomain();
352     }
353    
354     /**
355     \brief
356     Return a copy of the domain.
357     */
358     const AbstractDomain
359     getCopyOfDomain() const;
360    
361     /**
362     \brief
363     Return the rank of the point data.
364     */
365     inline
366     int
367     getDataPointRank() const
368     {
369     return m_data->getPointDataView().getRank();
370     }
371    
372     /**
373     \brief
374 jgs 102 Return the number of samples.
375 jgs 94 */
376     inline
377     int
378 jgs 102 getNumSamples() const
379 jgs 94 {
380 jgs 102 return m_data->getNumSamples();
381 jgs 94 }
382    
383     /**
384     \brief
385 jgs 102 Return the number of data points per sample.
386 jgs 94 */
387 jgs 102 inline
388 jgs 94 int
389 jgs 102 getNumDataPointsPerSample() const
390     {
391     return m_data->getNumDPPSample();
392     }
393 jgs 94
394     /**
395     \brief
396     Return the sample data for the given sample no. This is not the
397     preferred interface but is provided for use by C code.
398     \param sampleNo - Input - the given sample no.
399     */
400 jgs 102 inline
401 jgs 94 DataAbstract::ValueType::value_type*
402 jgs 102 getSampleData(DataAbstract::ValueType::size_type sampleNo)
403     {
404     return m_data->getSampleData(sampleNo);
405     }
406 jgs 94
407     /**
408     \brief
409     Return the sample data for the given tag. If an attempt is made to
410     access data that isn't tagged an exception will be thrown.
411     \param tag - Input - the tag key.
412     */
413 jgs 102 inline
414 jgs 94 DataAbstract::ValueType::value_type*
415 jgs 102 getSampleDataByTag(int tag)
416     {
417     return m_data->getSampleDataByTag(tag);
418     }
419 jgs 94
420     /**
421     \brief
422 jgs 110 Assign the given value to the data-points referenced by the given
423     reference number.
424    
425     The value supplied is a python numarray object. The data from this numarray
426     is unpacked into a DataArray, and this is used to set the corresponding
427     data-points in the underlying Data object.
428    
429     If the underlying Data object cannot be accessed via reference numbers, an
430     exception will be thrown.
431    
432     \param ref - Input - reference number.
433     \param value - Input - value to assign to data-points associated with
434     the given reference number.
435     */
436     void
437     setRefValue(int ref,
438     const boost::python::numeric::array& value);
439    
440     /**
441     \brief
442     Return the values associated with the data-points referenced by the given
443     reference number.
444    
445     The value supplied is a python numarray object. The data from the corresponding
446     data-points in this Data object are packed into the given numarray object.
447    
448     If the underlying Data object cannot be accessed via reference numbers, an
449     exception will be thrown.
450    
451     \param ref - Input - reference number.
452     \param value - Output - object to receive values from data-points
453     associated with the given reference number.
454     */
455     void
456     getRefValue(int ref,
457     boost::python::numeric::array& value);
458    
459     /**
460     \brief
461 jgs 94 Return a view into the data for the data point specified.
462     NOTE: Construction of the DataArrayView is a relatively expensive
463     operation.
464     \param sampleNo - Input -
465     \param dataPointNo - Input -
466     */
467     inline
468     DataArrayView
469     getDataPoint(int sampleNo,
470     int dataPointNo)
471     {
472     return m_data->getDataPoint(sampleNo,dataPointNo);
473     }
474    
475     /**
476     \brief
477     Return a reference to the data point shape.
478     */
479     const DataArrayView::ShapeType&
480     getDataPointShape() const;
481    
482     /**
483     \brief
484 jgs 102 Return the data point shape as a tuple of integers.
485 jgs 94 */
486 jgs 121 const boost::python::tuple
487 jgs 94 getShapeTuple() const;
488    
489     /**
490     \brief
491     Return the size of the data point. It is the product of the
492     data point shape dimensions.
493     */
494     int
495     getDataPointSize() const;
496    
497     /**
498     \brief
499 jgs 102 Return the number of doubles stored for this Data.
500 jgs 94 */
501     DataArrayView::ValueType::size_type
502     getLength() const;
503    
504     /**
505     \brief
506 jgs 102 Assign the given value to the tag. Implicitly converts this
507     object to type DataTagged. Throws an exception if this object
508     cannot be converted to a DataTagged object.
509     \param tagKey - Input - Integer key.
510     \param value - Input - Value to associate with given key.
511 jgs 94 */
512 jgs 102 void
513     setTaggedValue(int tagKey,
514     const boost::python::object& value);
515    
516     /**
517     \brief
518     Assign the given value to the tag. Implicitly converts this
519     object to type DataTagged. Throws an exception if this object
520     cannot be converted to a DataTagged object.
521     \param tagKey - Input - Integer key.
522     \param value - Input - Value to associate with given key.
523     */
524     void
525 jgs 121 setTaggedValueFromCPP(int tagKey,
526     const DataArrayView& value);
527 jgs 102
528     /**
529     \brief
530     Copy other Data object into this Data object where mask is positive.
531     */
532     void
533     copyWithMask(const Data& other,
534     const Data& mask);
535    
536     /**
537     Data object operation methods and operators.
538     */
539    
540     /**
541     \brief
542     Interpolates this onto the given functionspace and returns
543     the result as a Data object.
544     */
545 jgs 94 Data
546     interpolate(const FunctionSpace& functionspace) const;
547    
548     /**
549     \brief
550     Calculates the gradient of the data at the data points of functionspace.
551     If functionspace is not present the function space of Function(getDomain()) is used.
552     */
553     Data
554     gradOn(const FunctionSpace& functionspace) const;
555    
556     Data
557     grad() const;
558    
559     /**
560     \brief
561     Calculate the integral over the function space domain.
562     */
563     boost::python::numeric::array
564     integrate() const;
565    
566     /**
567     \brief
568     Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
569     */
570     Data
571     wherePositive() const;
572    
573     /**
574     \brief
575 jgs 102 Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
576 jgs 94 */
577     Data
578 jgs 102 whereNegative() const;
579    
580     /**
581     \brief
582     Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.
583     */
584     Data
585 jgs 94 whereNonNegative() const;
586    
587     /**
588     \brief
589 jgs 102 Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.
590 jgs 94 */
591     Data
592 jgs 102 whereNonPositive() const;
593 jgs 94
594     /**
595     \brief
596 jgs 102 Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.
597 jgs 94 */
598     Data
599     whereZero() const;
600    
601     /**
602     \brief
603 jgs 102 Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.
604 jgs 94 */
605     Data
606 jgs 102 whereNonZero() const;
607    
608     /**
609     \brief
610     Return the sin of each data point of this Data object.
611     */
612     Data
613 jgs 94 sin() const;
614    
615     /**
616     \brief
617 jgs 102 Return the cos of each data point of this Data object.
618 jgs 94 */
619     Data
620     cos() const;
621    
622     /**
623     \brief
624 jgs 102 Return the tan of each data point of this Data object.
625 jgs 94 */
626     Data
627     tan() const;
628    
629     /**
630     \brief
631 jgs 102 Return the log to base 10 of each data point of this Data object.
632 jgs 94 */
633     Data
634     log() const;
635    
636     /**
637     \brief
638 jgs 102 Return the natural log of each data point of this Data object.
639 jgs 94 */
640     Data
641     ln() const;
642    
643     /**
644     \brief
645 jgs 102 Return the maximum absolute value of this Data object.
646 jgs 94 */
647 jgs 102 double
648     Lsup() const;
649 jgs 94
650     /**
651     \brief
652 jgs 117 Return the minimum absolute value of this Data object.
653     */
654     double
655     Linf() const;
656    
657     /**
658     \brief
659 jgs 102 Return the maximum value of this Data object.
660 jgs 94 */
661 jgs 102 double
662     sup() const;
663 jgs 94
664     /**
665     \brief
666 jgs 102 Return the minimum value of this Data object.
667 jgs 94 */
668     double
669 jgs 102 inf() const;
670 jgs 94
671     /**
672     \brief
673 jgs 102 Return the absolute value of each data point of this Data object.
674 jgs 94 */
675 jgs 102 Data
676     abs() const;
677 jgs 94
678     /**
679     \brief
680 jgs 102 Return the maximum value of each data point of this Data object.
681 jgs 94 */
682 jgs 102 Data
683     maxval() const;
684 jgs 94
685     /**
686     \brief
687 jgs 102 Return the minimum value of each data point of this Data object.
688 jgs 94 */
689     Data
690 jgs 102 minval() const;
691 jgs 94
692     /**
693     \brief
694 jgs 121 Return the (sample number, data-point number) of the data point with
695     the minimum value in this Data object.
696     */
697     const boost::python::tuple
698     mindp() const;
699    
700     /**
701     \brief
702 jgs 102 Return the length of each data point of this Data object.
703     sqrt(sum(A[i,j,k,l]^2))
704 jgs 94 */
705 jgs 102 Data
706     length() const;
707 jgs 94
708     /**
709     \brief
710 jgs 102 Return the sign of each data point of this Data object.
711     -1 for negative values, zero for zero values, 1 for positive values.
712 jgs 94 */
713 jgs 102 Data
714     sign() const;
715 jgs 94
716     /**
717 jgs 121 \brief
718 jgs 102 Transpose each data point of this Data object around the given axis.
719 jgs 106 --* not implemented yet *--
720 jgs 102 */
721     Data
722     transpose(int axis) const;
723    
724     /**
725 jgs 121 \brief
726 jgs 102 Calculate the trace of each data point of this Data object.
727     sum(A[i,i,i,i])
728     */
729     Data
730     trace() const;
731    
732     /**
733 jgs 121 \brief
734 jgs 102 Return the exponential function of each data point of this Data object.
735     */
736     Data
737     exp() const;
738    
739     /**
740 jgs 121 \brief
741 jgs 102 Return the square root of each data point of this Data object.
742     */
743     Data
744     sqrt() const;
745    
746     /**
747 jgs 121 \brief
748     Return the negation of each data point of this Data object.
749     */
750     Data
751     neg() const;
752    
753     /**
754     \brief
755     Return the identity of each data point of this Data object.
756     Simply returns this object unmodified.
757     */
758     Data
759     pos() const;
760    
761     /**
762 jgs 94 \brief
763 jgs 102 Return the given power of each data point of this Data object.
764 jgs 121
765     \param right Input - the power to raise the object to.
766 jgs 102 */
767     Data
768     powD(const Data& right) const;
769    
770 jgs 121 /**
771     * \brief
772     * Return the given power of each data point of this boost python object.
773     *
774     * \param right Input - the power to raise the object to.
775     */
776 jgs 102 Data
777     powO(const boost::python::object& right) const;
778    
779     /**
780     \brief
781 jgs 104 writes the object to a file in the DX file format
782     */
783     void
784     saveDX(std::string fileName) const;
785    
786     /**
787     \brief
788 jgs 110 writes the object to a file in the VTK file format
789     */
790     void
791     saveVTK(std::string fileName) const;
792    
793     /**
794 jgs 102 \brief
795     Overloaded operator +=
796     \param right - Input - The right hand side.
797     */
798     Data& operator+=(const Data& right);
799     Data& operator+=(const boost::python::object& right);
800    
801     /**
802     \brief
803     Overloaded operator -=
804     \param right - Input - The right hand side.
805     */
806     Data& operator-=(const Data& right);
807     Data& operator-=(const boost::python::object& right);
808    
809     /**
810     \brief
811     Overloaded operator *=
812     \param right - Input - The right hand side.
813     */
814     Data& operator*=(const Data& right);
815     Data& operator*=(const boost::python::object& right);
816    
817     /**
818     \brief
819     Overloaded operator /=
820     \param right - Input - The right hand side.
821     */
822     Data& operator/=(const Data& right);
823     Data& operator/=(const boost::python::object& right);
824    
825     /**
826     \brief
827 jgs 94 Returns true if this can be interpolated to functionspace.
828     */
829     bool
830     probeInterpolation(const FunctionSpace& functionspace) const;
831    
832     /**
833 jgs 102 Data object slicing methods.
834     */
835    
836     /**
837 jgs 94 \brief
838 jgs 102 Returns a slice from this Data object.
839    
840     /description
841     Implements the [] get operator in python.
842     Calls getSlice.
843    
844     \param key - Input - python slice tuple specifying
845     slice to return.
846 jgs 94 */
847 jgs 102 Data
848     getItem(const boost::python::object& key) const;
849    
850     /**
851     \brief
852     Copies slice from value into this Data object.
853    
854     Implements the [] set operator in python.
855     Calls setSlice.
856    
857     \param key - Input - python slice tuple specifying
858     slice to copy from value.
859     \param value - Input - Data object to copy from.
860     */
861 jgs 94 void
862 jgs 102 setItemD(const boost::python::object& key,
863     const Data& value);
864 jgs 94
865 jgs 102 void
866     setItemO(const boost::python::object& key,
867     const boost::python::object& value);
868    
869     // These following public methods should be treated as private.
870    
871 jgs 94 /**
872     \brief
873 jgs 102 Perform the given unary operation on every element of every data point in
874     this Data object.
875 jgs 94 */
876 jgs 102 template <class UnaryFunction>
877     inline
878 jgs 94 void
879 jgs 102 unaryOp(UnaryFunction operation);
880    
881     /**
882     \brief
883     Return a Data object containing the specified slice of
884     this Data object.
885     \param region - Input - Region to copy.
886 jgs 94 */
887 jgs 102 Data
888     getSlice(const DataArrayView::RegionType& region) const;
889 jgs 94
890 jgs 102 /**
891     \brief
892     Copy the specified slice from the given value into this
893     Data object.
894     \param value - Input - Data to copy from.
895     \param region - Input - Region to copy.
896     */
897     void
898     setSlice(const Data& value,
899     const DataArrayView::RegionType& region);
900    
901 jgs 119 /**
902     \brief
903     Archive the current Data object to the given file.
904     \param fileName - Input - file to archive to.
905     */
906     void
907     archiveData(const std::string fileName);
908    
909     /**
910     \brief
911     Extract the Data object archived in the given file, overwriting
912     the current Data object.
913     Note - the current object must be of type DataEmpty.
914     \param fileName - Input - file to extract from.
915 jgs 121 \param fspace - Input - a suitable FunctionSpace descibing the data.
916 jgs 119 */
917     void
918     extractData(const std::string fileName,
919     const FunctionSpace& fspace);
920    
921 jgs 102 protected:
922    
923 jgs 94 private:
924    
925     /**
926     \brief
927 jgs 102 Check *this and the right operand are compatible. Throws
928     an exception if they aren't.
929     \param right - Input - The right hand side.
930     */
931     inline
932     void
933     operandCheck(const Data& right) const
934     {
935     return m_data->operandCheck(*(right.m_data.get()));
936     }
937    
938     /**
939     \brief
940     Perform the specified reduction algorithm on every element of every data point in
941 jgs 113 this Data object according to the given function and return the single value result.
942 jgs 102 */
943     template <class UnaryFunction>
944     inline
945     double
946     algorithm(UnaryFunction operation) const;
947    
948 jgs 113 /**
949     \brief
950     Reduce each data-point in this Data object using the given operation. Return a Data
951     object with the same number of data-points, but with each data-point containing only
952     one value - the result of the reduction operation on the corresponding data-point in
953     this Data object
954     */
955 jgs 106 template <class UnaryFunction>
956     inline
957     Data
958     dp_algorithm(UnaryFunction operation) const;
959    
960 jgs 102 /**
961     \brief
962     Perform the given binary operation on all of the data's elements.
963     The underlying type of the right hand side (right) determines the final
964     type of *this after the operation. For example if the right hand side
965     is expanded *this will be expanded if necessary.
966     RHS is a Data object.
967     */
968     template <class BinaryFunction>
969     inline
970     void
971     binaryOp(const Data& right,
972     BinaryFunction operation);
973    
974     /**
975     \brief
976     Perform the given binary operation on all of the data's elements.
977     RHS is a boost::python object.
978     */
979     template <class BinaryFunction>
980     inline
981     void
982     binaryOp(const boost::python::object& right,
983     BinaryFunction operation);
984    
985     /**
986     \brief
987     Convert the data type of the RHS to match this.
988     \param right - Input - data type to match.
989     */
990     void
991     typeMatchLeft(Data& right) const;
992    
993     /**
994     \brief
995     Convert the data type of this to match the RHS.
996     \param right - Input - data type to match.
997     */
998     void
999     typeMatchRight(const Data& right);
1000    
1001     /**
1002     \brief
1003 jgs 94 Construct a Data object of the appropriate type.
1004     */
1005     template <class IValueType>
1006     void
1007     initialise(const IValueType& value,
1008     const FunctionSpace& what,
1009     bool expanded);
1010    
1011     /**
1012     \brief
1013     Reshape the data point if the data point is currently rank 0.
1014     Will throw an exception if the data points are not rank 0.
1015     The original data point value is used for all values of the new
1016     data point.
1017     */
1018     void
1019     reshapeDataPoint(const DataArrayView::ShapeType& shape);
1020    
1021     //
1022 jgs 102 // pointer to the actual data object
1023 jgs 94 boost::shared_ptr<DataAbstract> m_data;
1024    
1025     };
1026    
1027     template <class IValueType>
1028     void
1029     Data::initialise(const IValueType& value,
1030     const FunctionSpace& what,
1031     bool expanded)
1032     {
1033     //
1034     // Construct a Data object of the appropriate type.
1035     // Construct the object first as there seems to be a bug which causes
1036     // undefined behaviour if an exception is thrown during construction
1037     // within the shared_ptr constructor.
1038     if (expanded) {
1039     DataAbstract* temp=new DataExpanded(value,what);
1040 jgs 102 boost::shared_ptr<DataAbstract> temp_data(temp);
1041     m_data=temp_data;
1042 jgs 94 } else {
1043     DataAbstract* temp=new DataConstant(value,what);
1044 jgs 102 boost::shared_ptr<DataAbstract> temp_data(temp);
1045     m_data=temp_data;
1046 jgs 94 }
1047     }
1048    
1049 jgs 102 /**
1050     Binary Data object operators.
1051     */
1052 jgs 94
1053     /**
1054     \brief
1055     Operator+
1056     Takes two Data objects.
1057     */
1058     Data operator+(const Data& left, const Data& right);
1059    
1060     /**
1061     \brief
1062     Operator-
1063     Takes two Data objects.
1064     */
1065     Data operator-(const Data& left, const Data& right);
1066    
1067     /**
1068     \brief
1069     Operator*
1070     Takes two Data objects.
1071     */
1072     Data operator*(const Data& left, const Data& right);
1073    
1074     /**
1075     \brief
1076     Operator/
1077     Takes two Data objects.
1078     */
1079     Data operator/(const Data& left, const Data& right);
1080    
1081     /**
1082     \brief
1083     Operator+
1084     Takes LHS Data object and RHS python::object.
1085     python::object must be convertable to Data type.
1086     */
1087     Data operator+(const Data& left, const boost::python::object& right);
1088    
1089     /**
1090     \brief
1091     Operator-
1092     Takes LHS Data object and RHS python::object.
1093     python::object must be convertable to Data type.
1094     */
1095     Data operator-(const Data& left, const boost::python::object& right);
1096    
1097     /**
1098     \brief
1099     Operator*
1100     Takes LHS Data object and RHS python::object.
1101     python::object must be convertable to Data type.
1102     */
1103     Data operator*(const Data& left, const boost::python::object& right);
1104    
1105     /**
1106     \brief
1107     Operator/
1108     Takes LHS Data object and RHS python::object.
1109     python::object must be convertable to Data type.
1110     */
1111     Data operator/(const Data& left, const boost::python::object& right);
1112    
1113     /**
1114     \brief
1115     Operator+
1116     Takes LHS python::object and RHS Data object.
1117     python::object must be convertable to Data type.
1118     */
1119     Data operator+(const boost::python::object& left, const Data& right);
1120    
1121     /**
1122     \brief
1123     Operator-
1124     Takes LHS python::object and RHS Data object.
1125     python::object must be convertable to Data type.
1126     */
1127     Data operator-(const boost::python::object& left, const Data& right);
1128    
1129     /**
1130     \brief
1131     Operator*
1132     Takes LHS python::object and RHS Data object.
1133     python::object must be convertable to Data type.
1134     */
1135     Data operator*(const boost::python::object& left, const Data& right);
1136    
1137     /**
1138     \brief
1139     Operator/
1140     Takes LHS python::object and RHS Data object.
1141     python::object must be convertable to Data type.
1142     */
1143     Data operator/(const boost::python::object& left, const Data& right);
1144    
1145     /**
1146     \brief
1147     Output operator
1148     */
1149     std::ostream& operator<<(std::ostream& o, const Data& data);
1150    
1151     /**
1152     \brief
1153     Return true if operands are equivalent, else return false.
1154     NB: this operator does very little at this point, and isn't to
1155     be relied on. Requires further implementation.
1156     */
1157 jgs 102 //bool operator==(const Data& left, const Data& right);
1158 jgs 94
1159 jgs 102 /**
1160     \brief
1161     Perform the given binary operation with this and right as operands.
1162     Right is a Data object.
1163     */
1164 jgs 94 template <class BinaryFunction>
1165     inline
1166     void
1167     Data::binaryOp(const Data& right,
1168     BinaryFunction operation)
1169     {
1170     //
1171     // if this has a rank of zero promote it to the rank of the RHS
1172     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
1173     reshapeDataPoint(right.getPointDataView().getShape());
1174     }
1175     //
1176     // initially make the temporary a shallow copy
1177     Data tempRight(right);
1178     if (getFunctionSpace()!=right.getFunctionSpace()) {
1179     if (right.probeInterpolation(getFunctionSpace())) {
1180     //
1181     // an interpolation is required so create a new Data
1182     tempRight=Data(right,this->getFunctionSpace());
1183     } else if (probeInterpolation(right.getFunctionSpace())) {
1184     //
1185     // interpolate onto the RHS function space
1186     Data tempLeft(*this,right.getFunctionSpace());
1187     m_data=tempLeft.m_data;
1188     }
1189     }
1190     operandCheck(tempRight);
1191     //
1192     // ensure this has the right type for the RHS
1193 jgs 102 typeMatchRight(tempRight);
1194 jgs 94 //
1195     // Need to cast to the concrete types so that the correct binaryOp
1196     // is called.
1197     if (isExpanded()) {
1198     //
1199     // Expanded data will be done in parallel, the right hand side can be
1200     // of any data type
1201     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1202     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1203     escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);
1204     } else if (isTagged()) {
1205     //
1206     // Tagged data is operated on serially, the right hand side can be
1207     // either DataConstant or DataTagged
1208     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1209     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1210     if (right.isTagged()) {
1211     DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1212     EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1213     escript::binaryOp(*leftC,*rightC,operation);
1214     } else {
1215     DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1216     EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1217     escript::binaryOp(*leftC,*rightC,operation);
1218     }
1219 jgs 102 } else if (isConstant()) {
1220 jgs 94 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1221     DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1222     EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1223     escript::binaryOp(*leftC,*rightC,operation);
1224     }
1225     }
1226    
1227 jgs 102 /**
1228     \brief
1229     Perform the given binary operation with this and right as operands.
1230     Right is a boost::python object.
1231     */
1232 jgs 94 template <class BinaryFunction>
1233     inline
1234     void
1235     Data::binaryOp(const boost::python::object& right,
1236     BinaryFunction operation)
1237     {
1238     DataArray temp(right);
1239     //
1240     // if this has a rank of zero promote it to the rank of the RHS.
1241     if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {
1242     reshapeDataPoint(temp.getView().getShape());
1243     }
1244     //
1245     // Always allow scalar values for the RHS but check other shapes
1246     if (temp.getView().getRank()!=0) {
1247     if (!getPointDataView().checkShape(temp.getView().getShape())) {
1248     throw DataException(getPointDataView().createShapeErrorMessage(
1249     "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));
1250     }
1251     }
1252     if (isExpanded()) {
1253     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1254     EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");
1255     escript::binaryOp(*leftC,temp.getView(),operation);
1256     } else if (isTagged()) {
1257     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1258     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1259     escript::binaryOp(*leftC,temp.getView(),operation);
1260 jgs 102 } else if (isConstant()) {
1261 jgs 94 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1262     EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");
1263     escript::binaryOp(*leftC,temp.getView(),operation);
1264     }
1265     }
1266    
1267 jgs 102 /**
1268     \brief
1269     Perform the given unary operation on other and return the result.
1270     Given operation is performed on each element of each data point, thus
1271     argument object is a rank n Data object, and returned object is a rank n
1272     Data object.
1273     Calls Data::unaryOp.
1274     */
1275 jgs 94 template <class UnaryFunction>
1276     inline
1277 jgs 102 Data
1278     unaryOp(const Data& other,
1279     UnaryFunction operation)
1280     {
1281     Data result;
1282     result.copy(other);
1283     result.unaryOp(operation);
1284     return result;
1285     }
1286    
1287     /**
1288     \brief
1289     Perform the given unary operation on this.
1290     Given operation is performed on each element of each data point.
1291     Calls escript::unaryOp.
1292     */
1293     template <class UnaryFunction>
1294     inline
1295 jgs 94 void
1296     Data::unaryOp(UnaryFunction operation)
1297     {
1298     if (isExpanded()) {
1299     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1300     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1301     escript::unaryOp(*leftC,operation);
1302     } else if (isTagged()) {
1303     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1304     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1305     escript::unaryOp(*leftC,operation);
1306 jgs 102 } else if (isConstant()) {
1307 jgs 94 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1308     EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1309     escript::unaryOp(*leftC,operation);
1310     }
1311     }
1312    
1313 jgs 102 /**
1314     \brief
1315     Perform the given Data object reduction algorithm on this and return the result.
1316     Given operation combines each element of each data point, thus argument
1317     object (*this) is a rank n Data object, and returned object is a scalar.
1318     Calls escript::algorithm.
1319     */
1320 jgs 94 template <class UnaryFunction>
1321     inline
1322     double
1323     Data::algorithm(UnaryFunction operation) const
1324     {
1325     if (isExpanded()) {
1326     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1327     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1328     return escript::algorithm(*leftC,operation);
1329 jgs 102 } else if (isTagged()) {
1330 jgs 94 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1331     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1332     return escript::algorithm(*leftC,operation);
1333 jgs 102 } else if (isConstant()) {
1334 jgs 94 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1335     EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1336     return escript::algorithm(*leftC,operation);
1337     }
1338 jgs 102 return 0;
1339 jgs 94 }
1340    
1341 jgs 102 /**
1342     \brief
1343     Perform the given data point reduction algorithm on data and return the result.
1344     Given operation combines each element within each data point into a scalar,
1345     thus argument object is a rank n Data object, and returned object is a
1346     rank 0 Data object.
1347     Calls escript::dp_algorithm.
1348     */
1349 jgs 94 template <class UnaryFunction>
1350     inline
1351     Data
1352 jgs 106 Data::dp_algorithm(UnaryFunction operation) const
1353 jgs 94 {
1354 jgs 106 Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());
1355     if (isExpanded()) {
1356     DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1357 jgs 102 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1358     EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1359     EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1360     escript::dp_algorithm(*dataE,*resultE,operation);
1361 jgs 106 } else if (isTagged()) {
1362     DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1363 jgs 102 DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1364     EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1365     EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1366     escript::dp_algorithm(*dataT,*resultT,operation);
1367 jgs 106 } else if (isConstant()) {
1368     DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1369 jgs 102 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1370     EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1371     EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1372     escript::dp_algorithm(*dataC,*resultC,operation);
1373     }
1374 jgs 94 return result;
1375     }
1376    
1377     }
1378     #endif

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26