From 23c4ab29f2db0750895e7fdbe49c8112632b24a4 Mon Sep 17 00:00:00 2001 From: abn Date: Mon, 14 Sep 2015 16:17:50 +0200 Subject: [PATCH] Release checking constraints on field nature when performing multiply, divide, etc ... operations. --- src/MEDCoupling/MEDCouplingField.cxx | 15 ++++ src/MEDCoupling/MEDCouplingField.hxx | 1 + src/MEDCoupling/MEDCouplingFieldDouble.cxx | 69 ++++++++++--------- src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 56 +++++++++++++++ 4 files changed, 108 insertions(+), 33 deletions(-) diff --git a/src/MEDCoupling/MEDCouplingField.cxx b/src/MEDCoupling/MEDCouplingField.cxx index cd635943b..52164a9ad 100644 --- a/src/MEDCoupling/MEDCouplingField.cxx +++ b/src/MEDCoupling/MEDCouplingField.cxx @@ -145,6 +145,21 @@ bool MEDCouplingField::areStrictlyCompatible(const MEDCouplingField *other) cons return _mesh==other->_mesh; } +/*! + * This method is less strict than MEDCouplingField::areStrictlyCompatible method. + * The difference is that the nature is not checked. + * This method is used for multiplication and division on fields to operate a first check before attempting operation. + */ +bool MEDCouplingField::areStrictlyCompatibleForMulDiv(const MEDCouplingField *other) const +{ + if(!other) + throw INTERP_KERNEL::Exception("MEDCouplingField::areStrictlyCompatible : input field is NULL !"); + if(!_type->isEqual(other->_type,1.e-12)) + return false; + return _mesh==other->_mesh; +} + + void MEDCouplingField::updateTime() const { if(_mesh) diff --git a/src/MEDCoupling/MEDCouplingField.hxx b/src/MEDCoupling/MEDCouplingField.hxx index c1b7efb58..9154f56c2 100644 --- a/src/MEDCoupling/MEDCouplingField.hxx +++ b/src/MEDCoupling/MEDCouplingField.hxx @@ -47,6 +47,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT virtual void checkCoherency() const = 0; MEDCOUPLING_EXPORT virtual bool areCompatibleForMerge(const MEDCouplingField *other) const; MEDCOUPLING_EXPORT virtual bool areStrictlyCompatible(const MEDCouplingField *other) const; + MEDCOUPLING_EXPORT virtual bool areStrictlyCompatibleForMulDiv(const MEDCouplingField *other) const; MEDCOUPLING_EXPORT virtual bool isEqualIfNotWhy(const MEDCouplingField *other, double meshPrec, double valsPrec, std::string& reason) const; MEDCOUPLING_EXPORT virtual bool isEqual(const MEDCouplingField *other, double meshPrec, double valsPrec) const; MEDCOUPLING_EXPORT virtual bool isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const; diff --git a/src/MEDCoupling/MEDCouplingFieldDouble.cxx b/src/MEDCoupling/MEDCouplingFieldDouble.cxx index ee6574469..b62261758 100644 --- a/src/MEDCoupling/MEDCouplingFieldDouble.cxx +++ b/src/MEDCoupling/MEDCouplingFieldDouble.cxx @@ -534,12 +534,12 @@ bool MEDCouplingFieldDouble::areStrictlyCompatible(const MEDCouplingField *other } /*! - * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatible method except that + * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatibleForMulDiv method except that * number of components between \a this and 'other' can be different here (for operator*). */ bool MEDCouplingFieldDouble::areCompatibleForMul(const MEDCouplingField *other) const { - if(!MEDCouplingField::areStrictlyCompatible(other)) + if(!MEDCouplingField::areStrictlyCompatibleForMulDiv(other)) return false; const MEDCouplingFieldDouble *otherC=dynamic_cast(other); if(!otherC) @@ -550,12 +550,12 @@ bool MEDCouplingFieldDouble::areCompatibleForMul(const MEDCouplingField *other) } /*! - * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatible method except that + * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatibleForMulDiv method except that * number of components between \a this and 'other' can be different here (for operator/). */ bool MEDCouplingFieldDouble::areCompatibleForDiv(const MEDCouplingField *other) const { - if(!MEDCouplingField::areStrictlyCompatible(other)) + if(!MEDCouplingField::areStrictlyCompatibleForMulDiv(other)) return false; const MEDCouplingFieldDouble *otherC=dynamic_cast(other); if(!otherC) @@ -2772,7 +2772,7 @@ void MEDCouplingFieldDouble::sortPerTuple(bool asc) MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) { if(!f1->areCompatibleForMerge(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MergeFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MergeFields on them ! Check support mesh, field nature, and spatial and time discretisation."); const MEDCouplingMesh *m1(f1->getMesh()),*m2(f2->getMesh()); if(!f1->_time_discr) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MergeFields : no time discr of f1 !"); @@ -2823,7 +2823,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const std::vectorareCompatibleForMerge(*it)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MergeFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MergeFields on them! Check support mesh, field nature, and spatial and time discretisation."); for(int i=0;i<(int)a.size();i++) { if(a[i]->getMesh()) @@ -2864,7 +2864,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const std::vectorareCompatibleForMeld(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MeldFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MeldFields on them ! Check support mesh, field nature, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->meld(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); @@ -2890,11 +2890,11 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::DotFields(const MEDCouplingField { if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::DotFields : input field is NULL !"); - if(!f1->areStrictlyCompatible(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply DotFields on them !"); + if(!f1->areStrictlyCompatibleForMulDiv(f2)) + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply DotFields on them! Check support mesh, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->dot(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); - MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); + MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()); ret->setMesh(f1->getMesh()); return ret; } @@ -2921,11 +2921,11 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::CrossProductFields(const MEDCoup { if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::CrossProductFields : input field is NULL !"); - if(!f1->areStrictlyCompatible(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply CrossProductFields on them !"); + if(!f1->areStrictlyCompatibleForMulDiv(f2)) + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply CrossProductFields on them! Check support mesh, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->crossProduct(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); - MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); + MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()); ret->setMesh(f1->getMesh()); return ret.retn(); } @@ -2952,7 +2952,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MaxFields(const MEDCouplingField if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MaxFields : input field is NULL !"); if(!f1->areStrictlyCompatible(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MaxFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MaxFields on them! Check support mesh, field nature, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->max(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); @@ -2982,7 +2982,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MinFields(const MEDCouplingField if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MinFields : input field is NULL !"); if(!f1->areStrictlyCompatible(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MinFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MinFields on them! Check support mesh, field nature, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->min(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); @@ -3028,7 +3028,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::AddFields(const MEDCouplingField if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::AddFields : input field is NULL !"); if(!f1->areStrictlyCompatible(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply AddFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply AddFields on them! Check support mesh, field nature, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->add(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); @@ -3049,7 +3049,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::AddFields(const MEDCouplingField const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator+=(const MEDCouplingFieldDouble& other) { if(!areStrictlyCompatible(&other)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply += on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply += on them! Check support mesh, field nature, and spatial and time discretisation."); _time_discr->addEqual(other._time_discr); return *this; } @@ -3072,7 +3072,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::SubstractFields(const MEDCouplin if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::SubstractFields : input field is NULL !"); if(!f1->areStrictlyCompatible(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply SubstractFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply SubstractFields on them! Check support mesh, field nature, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->substract(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); @@ -3093,7 +3093,7 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::SubstractFields(const MEDCouplin const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator-=(const MEDCouplingFieldDouble& other) { if(!areStrictlyCompatible(&other)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply -= on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply -= on them! Check support mesh, field nature, and spatial and time discretisation."); _time_discr->substractEqual(other._time_discr); return *this; } @@ -3111,11 +3111,11 @@ const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator-=(const MEDCoupli * The two fields must have same number of tuples and same underlying mesh. * \param [in] f1 - a factor field. * \param [in] f2 - another factor field. - * \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble. + * \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, with no nature set. * The caller is to delete this result field using decrRef() as it is no more * needed. * \throw If either \a f1 or \a f2 is NULL. - * \throw If the fields are not compatible for production (areCompatibleForMul()), + * \throw If the fields are not compatible for multiplication (areCompatibleForMul()), * i.e. they differ not only in values and possibly number of components. */ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MultiplyFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) @@ -3123,10 +3123,10 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MultiplyFields(const MEDCoupling if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MultiplyFields : input field is NULL !"); if(!f1->areCompatibleForMul(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MultiplyFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MultiplyFields on them! Check support mesh, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->multiply(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); - MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); + MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()); ret->setMesh(f1->getMesh()); return ret.retn(); } @@ -3144,19 +3144,20 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::MultiplyFields(const MEDCoupling * * The two fields must have same number of tuples and same underlying mesh. * \param [in] other - an field to multiply to \a this one. - * \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble. + * \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, with no nature set. * The caller is to delete this result field using decrRef() as it is no more * needed. * \throw If \a other is NULL. - * \throw If the fields are not strictly compatible for production + * \throw If the fields are not strictly compatible for multiplication * (areCompatibleForMul()), * i.e. they differ not only in values and possibly in number of components. */ const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator*=(const MEDCouplingFieldDouble& other) { if(!areCompatibleForMul(&other)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply *= on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply *= on them! Check support mesh, and spatial and time discretisation."); _time_discr->multiplyEqual(other._time_discr); + _nature = NoNature; return *this; } @@ -3171,7 +3172,7 @@ const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator*=(const MEDCoupli * * \param [in] f1 - a numerator field. * \param [in] f2 - a denominator field. - * \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble. + * \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, with no nature set. * The caller is to delete this result field using decrRef() as it is no more * needed. * \throw If either \a f1 or \a f2 is NULL. @@ -3183,10 +3184,10 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::DivideFields(const MEDCouplingFi if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::DivideFields : input field is NULL !"); if(!f1->areCompatibleForDiv(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply DivideFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply DivideFields on them! Check support mesh, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->divide(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); - MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); + MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()); ret->setMesh(f1->getMesh()); return ret.retn(); } @@ -3211,8 +3212,9 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::DivideFields(const MEDCouplingFi const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator/=(const MEDCouplingFieldDouble& other) { if(!areCompatibleForDiv(&other)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply /= on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply /= on them! Check support mesh, and spatial and time discretisation."); _time_discr->divideEqual(other._time_discr); + _nature = NoNature; return *this; } @@ -3226,10 +3228,10 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::PowFields(const MEDCouplingField if(!f1) throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::PowFields : input field is NULL !"); if(!f1->areCompatibleForMul(f2)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply PowFields on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply PowFields on them! Check support mesh, and spatial and time discretisation."); MEDCouplingTimeDiscretization *td=f1->_time_discr->pow(f2->_time_discr); td->copyTinyAttrFrom(*f1->_time_discr); - MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()); + MEDCouplingAutoRefCountObjectPtr ret=new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()); ret->setMesh(f1->getMesh()); return ret.retn(); } @@ -3247,8 +3249,9 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::operator^(const MEDCouplingField const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator^=(const MEDCouplingFieldDouble& other) { if(!areCompatibleForDiv(&other)) - throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply /= on them !"); + throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply ^= on them! Check support mesh, and spatial and time discretisation."); _time_discr->powEqual(other._time_discr); + _nature = NoNature; return *this; } diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index da4aca8b9..18118dc75 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -670,6 +670,62 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertRaises(InterpKernelException,field.setNature,Integral); self.assertRaises(InterpKernelException,field.setNature,IntegralGlobConstraint); pass + + def testNatureOperations(self): + """ Check nature constraints on field operations """ + m = MEDCouplingCMesh() + m.setCoordsAt(0, DataArrayDouble([1.0,2.0,3.0])) + m.setCoordsAt(1, DataArrayDouble([1.0,2.0,3.0])) + m = m.buildUnstructured() + f1, f2 = MEDCouplingFieldDouble.New(ON_CELLS, NO_TIME), MEDCouplingFieldDouble.New(ON_CELLS, NO_TIME) + f1.setNature(Integral) + f2.setNature(ConservativeVolumic) + self.assertEqual(Integral, f1.getNature()) + self.assertEqual(ConservativeVolumic, f2.getNature()) + + da = DataArrayDouble([1.0,2.0,3.0,4.0]) + f1.setMesh(m); f2.setMesh(m) + f1.setArray(da); f2.setArray(da.deepCpy()) + # All this should complain about nature: + self.assertRaises(InterpKernelException, f1.__add__, f2) + self.assertRaises(InterpKernelException, f1.__iadd__, f2) + self.assertRaises(InterpKernelException, f1.__sub__, f2) + self.assertRaises(InterpKernelException, f1.__isub__, f2) + self.assertRaises(InterpKernelException, f1.__radd__, f2) + self.assertRaises(InterpKernelException, f1.__rsub__, f2) + self.assertRaises(InterpKernelException, MEDCouplingFieldDouble.AddFields, f1, f2) + self.assertRaises(InterpKernelException, MEDCouplingFieldDouble.SubstractFields, f1, f2) + self.assertRaises(InterpKernelException, MEDCouplingFieldDouble.MaxFields, f1, f2) + self.assertRaises(InterpKernelException, MEDCouplingFieldDouble.MinFields, f1, f2) + # Not those ones: + f3 = MEDCouplingFieldDouble.MultiplyFields(f1,f2) + self.assertEqual(NoNature, f3.getNature()) + f3 = f1*f2 + self.assertEqual(NoNature, f3.getNature()) + f1Tmp = f1.deepCpy(); f1Tmp.setMesh(m); f1Tmp *= f2 + self.assertEqual(NoNature, f1Tmp.getNature()) + f3 = MEDCouplingFieldDouble.DivideFields(f1,f2) + self.assertEqual(NoNature, f3.getNature()) + f3 = f1/f2 + self.assertEqual(NoNature, f3.getNature()) + f1Tmp = f1.deepCpy(); f1Tmp.setMesh(m); f1Tmp /= f2 + self.assertEqual(NoNature, f1Tmp.getNature()) +# f3 = MEDCouplingFieldDouble.PowFields(f1,f2) +# self.assertEqual(NoNature, f3.getNature()) + f3 = f1**f2 + self.assertEqual(NoNature, f3.getNature()) + f1Tmp = f1.deepCpy(); f1Tmp.setMesh(m); f1Tmp **= f2 + self.assertEqual(NoNature, f1Tmp.getNature()) + f3 = MEDCouplingFieldDouble.DotFields(f1,f2) + self.assertEqual(NoNature, f3.getNature()) + f3 = f1.dot(f2) + self.assertEqual(NoNature, f3.getNature()) + + da = DataArrayDouble.Meld([da, da, da]) + f1.setArray(da); f2.setArray(da.deepCpy()) + f3 = MEDCouplingFieldDouble.CrossProductFields(f1,f2) + self.assertEqual(NoNature, f3.getNature()) + f3 = f1.crossProduct(f2) def testBuildSubMeshData(self): targetMesh=MEDCouplingDataForTest.build2DTargetMesh_1() -- 2.39.2