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

Contents of /trunk/escript/src/Data/Data.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 100 - (show annotations)
Wed Dec 15 03:48:48 2004 UTC (14 years, 6 months ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.cpp
File size: 21577 byte(s)
*** empty log message ***

1 // $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 #include "escript/Data/Data.h"
19
20 #include <iostream>
21 #include <algorithm>
22 #include <vector>
23 #include <exception>
24 #include <functional>
25 #include <math.h>
26
27 #include <boost/python/str.hpp>
28 #include <boost/python/extract.hpp>
29 #include <boost/python/long.hpp>
30
31 #include "escript/Data/DataException.h"
32
33 #include "escript/Data/DataExpanded.h"
34 #include "escript/Data/DataConstant.h"
35 #include "escript/Data/DataTagged.h"
36 #include "escript/Data/DataEmpty.h"
37 #include "escript/Data/DataArray.h"
38 #include "escript/Data/DataAlgorithm.h"
39 #include "escript/Data/FunctionSpaceFactory.h"
40 #include "escript/Data/AbstractContinuousDomain.h"
41
42 using namespace std;
43 using namespace boost::python;
44 using namespace boost;
45 using namespace escript;
46
47 Data::Data()
48 {
49 //
50 // Default data is type DataEmpty
51 DataAbstract* temp=new DataEmpty();
52 m_data=shared_ptr<DataAbstract>(temp);
53 }
54
55 Data::Data(double value,
56 const tuple& shape,
57 const FunctionSpace& what,
58 bool expanded)
59 {
60 DataArrayView::ShapeType dataPointShape;
61 for (int i = 0; i < shape.attr("__len__")(); ++i) {
62 dataPointShape.push_back(extract<const int>(shape[i]));
63 }
64 DataArray temp(dataPointShape,value);
65 initialise(temp.getView(),what,expanded);
66 }
67
68 Data::Data(double value,
69 const DataArrayView::ShapeType& dataPointShape,
70 const FunctionSpace& what,
71 bool expanded)
72 {
73 DataArray temp(dataPointShape,value);
74 pair<int,int> dataShape=what.getDataShape();
75 initialise(temp.getView(),what,expanded);
76 }
77
78 Data::Data(const Data& inData):
79 m_data(inData.m_data)
80 {
81 }
82
83 Data::Data(const Data& inData,
84 const DataArrayView::RegionType& region)
85 {
86 //
87 // Create data which is a subset(slice) of another Data
88 DataAbstract* tmp=inData.m_data->getSlice(region);
89 m_data=shared_ptr<DataAbstract>(tmp);
90 }
91
92 Data::Data(const Data& inData,
93 const FunctionSpace& functionspace)
94 {
95 if (inData.getFunctionSpace()==functionspace) {
96 m_data=inData.m_data;
97 } else {
98 Data tmp(0,inData.getPointDataView().getShape(),functionspace,true);
99 // Note for Lutz, Must use a reference or pointer to a derived object
100 // in order to get polymorphic behaviour. Shouldn't really
101 // be able to create an instance of AbstractDomain but that was done
102 // as a boost python work around which may no longer be required.
103 const AbstractDomain& inDataDomain=inData.getDomain();
104 if (inDataDomain==functionspace.getDomain()) {
105 inDataDomain.interpolateOnDomain(tmp,inData);
106 } else {
107 inDataDomain.interpolateACross(tmp,inData);
108 }
109 m_data=tmp.m_data;
110 }
111 }
112
113 Data::Data(const DataTagged::TagListType& tagKeys,
114 const DataTagged::ValueListType & values,
115 const DataArrayView& defaultValue,
116 const FunctionSpace& what,
117 bool expanded)
118 {
119 DataAbstract* temp=new DataTagged(tagKeys,values,defaultValue,what);
120 m_data=shared_ptr<DataAbstract>(temp);
121 if (expanded) {
122 expand();
123 }
124 }
125
126 Data::Data(const numeric::array& value,
127 const FunctionSpace& what,
128 bool expanded)
129 {
130 initialise(value,what,expanded);
131 }
132
133 Data::Data(const DataArrayView& value,
134 const FunctionSpace& what,
135 bool expanded)
136 {
137 initialise(value,what,expanded);
138 }
139
140 Data::Data(const object& value,
141 const FunctionSpace& what,
142 bool expanded)
143 {
144 numeric::array asNumArray(value);
145 initialise(asNumArray,what,expanded);
146 }
147
148 Data::Data(const object& value,
149 const Data& other)
150 {
151 //
152 // Create DataConstant using the given value and all other parameters
153 // copied from other. If value is a rank 0 object this Data
154 // will assume the point data shape of other.
155 DataArray temp(value);
156 if (temp.getView().getRank()==0) {
157 //
158 // Create a DataArray with the scalar value for all elements
159 DataArray temp2(other.getPointDataView().getShape(),temp.getView()());
160 initialise(temp2.getView(),other.getFunctionSpace(),false);
161 } else {
162 //
163 // Create a DataConstant with the same sample shape as other
164 initialise(temp.getView(),other.getFunctionSpace(),false);
165 }
166 }
167
168 escriptDataC
169 Data::getDataC()
170 {
171 escriptDataC temp;
172 temp.m_dataPtr=(void*)this;
173 return temp;
174 }
175
176 escriptDataC
177 Data::getDataC() const
178 {
179 escriptDataC temp;
180 temp.m_dataPtr=(void*)this;
181 return temp;
182 }
183
184 tuple
185 Data::getShapeTuple() const
186 {
187 const DataArrayView::ShapeType& shape=getDataPointShape();
188 switch(getDataPointRank()) {
189 case 0:
190 return make_tuple();
191 case 1:
192 return make_tuple(long_(shape[0]));
193 case 2:
194 return make_tuple(long_(shape[0]),long_(shape[1]));
195 case 3:
196 return make_tuple(long_(shape[0]),long_(shape[1]),long_(shape[2]));
197 case 4:
198 return make_tuple(long_(shape[0]),long_(shape[1]),long_(shape[2]),long_(shape[3]));
199 default:
200 throw DataException("Error - illegal Data rank.");
201 }
202 }
203
204 void
205 Data::copy(const Data& other)
206 {
207 //
208 // Perform a deep copy
209 {
210 DataExpanded* temp=dynamic_cast<DataExpanded*>(other.m_data.get());
211 if (temp!=0) {
212 //
213 // Construct a DataExpanded copy
214 DataAbstract* newData=new DataExpanded(*temp);
215 m_data=shared_ptr<DataAbstract>(newData);
216 return;
217 }
218 }
219 {
220 DataTagged* temp=dynamic_cast<DataTagged*>(other.m_data.get());
221 if (temp!=0) {
222 //
223 // Construct a DataTaggeded copy
224 DataAbstract* newData=new DataTagged(*temp);
225 m_data=shared_ptr<DataAbstract>(newData);
226 return;
227 }
228 }
229 {
230 DataConstant* temp=dynamic_cast<DataConstant*>(other.m_data.get());
231 if (temp!=0) {
232 //
233 // Construct a DataConstant copy
234 DataAbstract* newData=new DataConstant(*temp);
235 m_data=shared_ptr<DataAbstract>(newData);
236 return;
237 }
238 }
239 throw DataException("Error - Copy not implemented for this Data type.");
240 }
241
242 void
243 Data::copyWithMask(const Data& other,
244 const Data& mask)
245 {
246 Data mask1;
247 Data mask2;
248
249 mask1 = mask.wherePositive();
250 mask2.copy(mask1);
251
252 mask1 *= other;
253 mask2 *= *this;
254 mask2 = *this - mask2;
255
256 *this = mask1 + mask2;
257 }
258
259 bool
260 Data::isExpanded() const
261 {
262 DataExpanded* temp=dynamic_cast<DataExpanded*>(m_data.get());
263 return (temp!=0);
264 }
265
266 bool
267 Data::isTagged() const
268 {
269 DataTagged* temp=dynamic_cast<DataTagged*>(m_data.get());
270 return (temp!=0);
271 }
272
273 bool
274 Data::isEmpty() const
275 {
276 DataEmpty* temp=dynamic_cast<DataEmpty*>(m_data.get());
277 return (temp!=0);
278 }
279
280 bool
281 Data::isConstant() const
282 {
283 DataConstant* temp=dynamic_cast<DataConstant*>(m_data.get());
284 return (temp!=0);
285 }
286
287 Data
288 Data::getSlice(const DataArrayView::RegionType& region) const
289 {
290 return Data(*this,region);
291 }
292
293 void
294 Data::setSlice(const Data& value,
295 const DataArrayView::RegionType& region)
296 {
297 m_data->setSlice(value.m_data.get(), region);
298 }
299
300 void
301 Data::expand()
302 {
303 if (isConstant()) {
304 DataConstant* tempDataConst=dynamic_cast<DataConstant*>(m_data.get());
305 DataAbstract* temp=new DataExpanded(*tempDataConst);
306 m_data=shared_ptr<DataAbstract>(temp);
307 } else if (isTagged()) {
308 DataTagged* tempDataTag=dynamic_cast<DataTagged*>(m_data.get());
309 DataAbstract* temp=new DataExpanded(*tempDataTag);
310 m_data=shared_ptr<DataAbstract>(temp);
311 } else if (isExpanded()) {
312 //
313 // do nothing
314 } else if (isEmpty()) {
315 throw DataException("Error - Expansion of DataEmpty not possible.");
316 } else {
317 throw DataException("Error - Expansion not implemented for this Data type.");
318 }
319 }
320
321 void
322 Data::reshapeDataPoint(const DataArrayView::ShapeType& shape)
323 {
324 m_data->reshapeDataPoint(shape);
325 }
326
327 void
328 Data::tag()
329 {
330 if (isConstant()) {
331 DataConstant* tempDataConst=dynamic_cast<DataConstant*>(m_data.get());
332 DataAbstract* temp=new DataTagged(*tempDataConst);
333 m_data=shared_ptr<DataAbstract>(temp);
334 } else if (isTagged()) {
335 // do nothing
336 } else if (isExpanded()) {
337 throw DataException("Error - Creating tag data from DataExpanded not possible.");
338 } else if (isEmpty()) {
339 throw DataException("Error - Creating tag data from DataEmpty not possible.");
340 } else {
341 throw DataException("Error - Tagging not implemented for this Data type.");
342 }
343 }
344
345 Data
346 Data::wherePositive() const
347 {
348 return escript::unaryOp(*this,bind2nd(greater<double>(),0.0));
349 }
350
351 Data
352 Data::whereNonNegative() const
353 {
354 return escript::unaryOp(*this,bind2nd(greater_equal<double>(),0.0));
355 }
356
357 Data
358 Data::whereNegative() const
359 {
360 return escript::unaryOp(*this,bind2nd(less<double>(),0.0));
361 }
362
363 Data
364 Data::whereZero() const
365 {
366 return escript::unaryOp(*this,bind2nd(equal_to<double>(),0.0));
367 }
368
369 Data
370 Data::interpolate(const FunctionSpace& functionspace) const
371 {
372 return Data(*this,functionspace);
373 }
374
375 bool
376 Data::probeInterpolation(const FunctionSpace& functionspace) const
377 {
378 if (getFunctionSpace()==functionspace) {
379 return true;
380 } else {
381 const AbstractDomain& domain=getDomain();
382 if (domain==functionspace.getDomain()) {
383 return domain.probeInterpolationOnDomain(getFunctionSpace().getTypeCode(),functionspace.getTypeCode());
384 } else {
385 return domain.probeInterpolationACross(getFunctionSpace().getTypeCode(),functionspace.getDomain(),functionspace.getTypeCode());
386 }
387 }
388 }
389
390 Data
391 Data::gradOn(const FunctionSpace& functionspace) const
392 {
393 if (functionspace.getDomain()!=getDomain())
394 throw DataException("Error - gradient cannot be calculated on different domains.");
395 DataArrayView::ShapeType grad_shape=getPointDataView().getShape();
396 grad_shape.push_back(functionspace.getDim());
397 Data out(0.0,grad_shape,functionspace,true);
398 getDomain().setToGradient(out,*this);
399 return out;
400 }
401
402 Data
403 Data::grad() const
404 {
405 return gradOn(escript::function(getDomain()));
406 }
407
408 int
409 Data::getDataPointSize() const
410 {
411 return getPointDataView().noValues();
412 }
413
414 DataArrayView::ValueType::size_type
415 Data::getLength() const
416 {
417 return m_data->getLength();
418 }
419
420 const DataArrayView::ShapeType&
421 Data::getDataPointShape() const
422 {
423 return getPointDataView().getShape();
424 }
425
426 boost::python::numeric::array
427 Data::integrate() const
428 {
429 int index;
430 int rank = getDataPointRank();
431 DataArrayView::ShapeType shape = getDataPointShape();
432
433 //
434 // calculate the integral values
435 vector<double> integrals(getDataPointSize());
436 AbstractContinuousDomain::asAbstractContinuousDomain(getDomain()).setToIntegrals(integrals,*this);
437
438 //
439 // create the numeric array to be returned
440 // and load the array with the integral values
441 boost::python::numeric::array bp_array(1.0);
442 if (rank==0) {
443 index = 0;
444 bp_array[0] = integrals[index];
445 }
446 if (rank==1) {
447 bp_array.resize(shape[0]);
448 for (int i=0; i<shape[0]; i++) {
449 index = i;
450 bp_array[i] = integrals[index];
451 }
452 }
453 if (rank==2) {
454 bp_array.resize(shape[0],shape[1]);
455 for (int i=0; i<shape[0]; i++) {
456 for (int j=0; j<shape[1]; j++) {
457 index = i + shape[0] * j;
458 bp_array[i,j] = integrals[index];
459 }
460 }
461 }
462 if (rank==3) {
463 bp_array.resize(shape[0],shape[1],shape[2]);
464 for (int i=0; i<shape[0]; i++) {
465 for (int j=0; j<shape[1]; j++) {
466 for (int k=0; k<shape[2]; k++) {
467 index = i + shape[0] * ( j + shape[1] * k );
468 bp_array[i,j,k] = integrals[index];
469 }
470 }
471 }
472 }
473 if (rank==4) {
474 bp_array.resize(shape[0],shape[1],shape[2],shape[3]);
475 for (int i=0; i<shape[0]; i++) {
476 for (int j=0; j<shape[1]; j++) {
477 for (int k=0; k<shape[2]; k++) {
478 for (int l=0; l<shape[3]; l++) {
479 index = i + shape[0] * ( j + shape[1] * ( k + shape[2] * l ) );
480 bp_array[i,j,k,l] = integrals[index];
481 }
482 }
483 }
484 }
485 }
486
487 //
488 // return the loaded array
489 return bp_array;
490 }
491
492 Data
493 Data::sin() const
494 {
495 return escript::unaryOp(*this,(Data::UnaryDFunPtr)::sin);
496 }
497
498 Data
499 Data::cos() const
500 {
501 return escript::unaryOp(*this,(Data::UnaryDFunPtr)::cos);
502 }
503
504 Data
505 Data::tan() const
506 {
507 return escript::unaryOp(*this,(Data::UnaryDFunPtr)::tan);
508 }
509
510 Data
511 Data::log() const
512 {
513 return escript::unaryOp(*this,(Data::UnaryDFunPtr)::log10);
514 }
515
516 Data
517 Data::ln() const
518 {
519 return escript::unaryOp(*this,(Data::UnaryDFunPtr)::log);
520 }
521
522 double
523 Data::Lsup() const
524 {
525 //
526 // set the initial absolute maximum value to min possible
527 return algorithm(DataAlgorithmAdapter<AbsMax>(numeric_limits<double>::min()));
528 }
529
530 double
531 Data::sup() const
532 {
533 //
534 // set the initial maximum value to min possible
535 return algorithm(DataAlgorithmAdapter<FMax>(numeric_limits<double>::min()));
536 }
537
538 double
539 Data::inf() const
540 {
541 //
542 // set the initial minimum value to max possible
543 return algorithm(DataAlgorithmAdapter<FMin>(numeric_limits<double>::max()));
544 }
545
546 Data& Data::operator+=(const Data& right)
547 {
548 binaryOp(right,plus<double>());
549 return (*this);
550 }
551
552 Data& Data::operator+=(const boost::python::object& right)
553 {
554 binaryOp(right,plus<double>());
555 return (*this);
556 }
557
558 Data& Data::operator-=(const Data& right)
559 {
560 binaryOp(right,minus<double>());
561 return (*this);
562 }
563
564 Data& Data::operator-=(const boost::python::object& right)
565 {
566 binaryOp(right,minus<double>());
567 return (*this);
568 }
569
570 Data& Data::operator*=(const Data& right)
571 {
572 binaryOp(right,multiplies<double>());
573 return (*this);
574 }
575
576 Data& Data::operator*=(const boost::python::object& right)
577 {
578 binaryOp(right,multiplies<double>());
579 return (*this);
580 }
581
582 Data& Data::operator/=(const Data& right)
583 {
584 binaryOp(right,divides<double>());
585 return (*this);
586 }
587
588 Data& Data::operator/=(const boost::python::object& right)
589 {
590 binaryOp(right,divides<double>());
591 return (*this);
592 }
593
594 Data Data::powO(const boost::python::object& right) const
595 {
596 Data result;
597 result.copy(*this);
598 result.binaryOp(right,(Data::BinaryDFunPtr)::pow);
599 return result;
600 }
601
602 Data Data::powD(const Data& right) const
603 {
604 Data result;
605 result.copy(*this);
606 result.binaryOp(right,(Data::BinaryDFunPtr)::pow);
607 return result;
608 }
609
610 //
611 // NOTE: It is essential to specify the namepsace this operator belongs to
612 Data escript::operator+(const Data& left, const Data& right)
613 {
614 Data result;
615 //
616 // perform a deep copy
617 result.copy(left);
618 result+=right;
619 return result;
620 }
621
622 //
623 // NOTE: It is essential to specify the namepsace this operator belongs to
624 Data escript::operator-(const Data& left, const Data& right)
625 {
626 Data result;
627 //
628 // perform a deep copy
629 result.copy(left);
630 result-=right;
631 return result;
632 }
633
634 //
635 // NOTE: It is essential to specify the namepsace this operator belongs to
636 Data escript::operator*(const Data& left, const Data& right)
637 {
638 Data result;
639 //
640 // perform a deep copy
641 result.copy(left);
642 result*=right;
643 return result;
644 }
645
646 //
647 // NOTE: It is essential to specify the namepsace this operator belongs to
648 Data escript::operator/(const Data& left, const Data& right)
649 {
650 Data result;
651 //
652 // perform a deep copy
653 result.copy(left);
654 result/=right;
655 return result;
656 }
657
658 //
659 // NOTE: It is essential to specify the namepsace this operator belongs to
660 Data escript::operator+(const Data& left, const boost::python::object& right)
661 {
662 //
663 // Convert to DataArray format if possible
664 DataArray temp(right);
665 Data result;
666 //
667 // perform a deep copy
668 result.copy(left);
669 result+=right;
670 return result;
671 }
672
673 //
674 // NOTE: It is essential to specify the namepsace this operator belongs to
675 Data escript::operator-(const Data& left, const boost::python::object& right)
676 {
677 //
678 // Convert to DataArray format if possible
679 DataArray temp(right);
680 Data result;
681 //
682 // perform a deep copy
683 result.copy(left);
684 result-=right;
685 return result;
686 }
687
688 //
689 // NOTE: It is essential to specify the namepsace this operator belongs to
690 Data escript::operator*(const Data& left, const boost::python::object& right)
691 {
692 //
693 // Convert to DataArray format if possible
694 DataArray temp(right);
695 Data result;
696 //
697 // perform a deep copy
698 result.copy(left);
699 result*=right;
700 return result;
701 }
702
703 //
704 // NOTE: It is essential to specify the namepsace this operator belongs to
705 Data escript::operator/(const Data& left, const boost::python::object& right)
706 {
707 //
708 // Convert to DataArray format if possible
709 DataArray temp(right);
710 Data result;
711 //
712 // perform a deep copy
713 result.copy(left);
714 result/=right;
715 return result;
716 }
717
718 //
719 // NOTE: It is essential to specify the namepsace this operator belongs to
720 Data escript::operator+(const boost::python::object& left, const Data& right)
721 {
722 //
723 // Construct the result using the given value and the other parameters
724 // from right
725 Data result(left,right);
726 result+=right;
727 return result;
728 }
729
730 //
731 // NOTE: It is essential to specify the namepsace this operator belongs to
732 Data escript::operator-(const boost::python::object& left, const Data& right)
733 {
734 //
735 // Construct the result using the given value and the other parameters
736 // from right
737 Data result(left,right);
738 result-=right;
739 return result;
740 }
741
742 //
743 // NOTE: It is essential to specify the namepsace this operator belongs to
744 Data escript::operator*(const boost::python::object& left, const Data& right)
745 {
746 //
747 // Construct the result using the given value and the other parameters
748 // from right
749 Data result(left,right);
750 result*=right;
751 return result;
752 }
753
754 //
755 // NOTE: It is essential to specify the namepsace this operator belongs to
756 Data escript::operator/(const boost::python::object& left, const Data& right)
757 {
758 //
759 // Construct the result using the given value and the other parameters
760 // from right
761 Data result(left,right);
762 result/=right;
763 return result;
764 }
765
766 //
767 // NOTE: It is essential to specify the namepsace this operator belongs to
768 bool escript::operator==(const Data& left, const Data& right)
769 {
770 /*
771 NB: this operator does very little at this point, and isn't to
772 be relied on. Requires further implementation.
773 */
774
775 bool ret;
776
777 if (left.isEmpty()) {
778 if(!right.isEmpty()) {
779 ret = false;
780 } else {
781 ret = true;
782 }
783 }
784
785 if (left.isConstant()) {
786 if(!right.isConstant()) {
787 ret = false;
788 } else {
789 ret = true;
790 }
791 }
792
793 if (left.isTagged()) {
794 if(!right.isTagged()) {
795 ret = false;
796 } else {
797 ret = true;
798 }
799 }
800
801 if (left.isExpanded()) {
802 if(!right.isExpanded()) {
803 ret = false;
804 } else {
805 ret = true;
806 }
807 }
808
809 return ret;
810 }
811
812 Data
813 Data::getItem(const boost::python::object& key) const
814 {
815 const DataArrayView& view=getPointDataView();
816 DataArrayView::RegionType slice_region=view.getSliceRegion(key);
817 if (slice_region.size()!=view.getRank()) {
818 throw DataException("Error - slice size does not match Data rank.");
819 return Data();
820 }
821 //
822 // Create a new Data which is a slice of this one
823 return getSlice(slice_region);
824 }
825
826 void
827 Data::setItem(const boost::python::object& key,
828 const Data& value)
829 {
830 const DataArrayView& view=getPointDataView();
831 DataArrayView::RegionType slice_region=view.getSliceRegion(key);
832 if (slice_region.size()!=view.getRank()) {
833 throw DataException("Error - slice size does not match Data rank.");
834 }
835 typeMatch(value);
836 setSlice(value,slice_region);
837 }
838
839 void
840 Data::typeMatch(const Data& right)
841 {
842 //
843 // match the type of this to the RHS
844 if (isTagged()) {
845 if (right.isExpanded()) {
846 //
847 // if the right hand side is expanded so must this
848 expand();
849 }
850 } else if (isConstant()) {
851 if (right.isExpanded()) {
852 //
853 // if the right hand side is expanded so must this
854 expand();
855 } else if (right.isTagged()) {
856 //
857 // if the right hand side is tagged so must this
858 tag();
859 }
860 }
861 }
862
863 void
864 Data::setTaggedValue(int tagKey,
865 const boost::python::object& value)
866 {
867 //
868 // Ensure underlying data object is of type DataTagged
869 tag();
870
871 if (!isTagged()) {
872 throw DataException("Error - DataTagged conversion failed!!");
873 }
874
875 //
876 // Construct DataArray from boost::python::object input value
877 DataArray valueDataArray(value);
878
879 //
880 // Call DataAbstract::setTaggedValue
881 m_data->setTaggedValue(tagKey,valueDataArray.getView());
882 }
883
884 /*
885 Note: this version removed for now. Not needed, and breaks escript.cpp
886 void
887 Data::setTaggedValue(int tagKey,
888 const DataArrayView& value)
889 {
890 //
891 // Ensure underlying data object is of type DataTagged
892 tag();
893
894 if (!isTagged()) {
895 throw DataException("Error - DataTagged conversion failed!!");
896 }
897
898 //
899 // Call DataAbstract::setTaggedValue
900 m_data->setTaggedValue(tagKey,value);
901 }
902 */
903
904 ostream& escript::operator<<(ostream& o, const Data& data)
905 {
906 o << data.toString();
907 return o;
908 }

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26