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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 117 - (hide annotations)
Fri Apr 1 05:48:57 2005 UTC (14 years ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.h
File MIME type: text/plain
File size: 34748 byte(s)
*** empty log message ***

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26