X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDLoader%2FMEDFileField.cxx;h=dfff9dbcafbc3e66d7a2b538db14eb1a4e4e9440;hb=854b8c30cd78bd9c7679492863fab2128552bb92;hp=52b6b06576bf6a9900def8762dcbe46e21c03b28;hpb=58a8618446c11bb22f219209a512a00a705090ac;p=tools%2Fmedcoupling.git diff --git a/src/MEDLoader/MEDFileField.cxx b/src/MEDLoader/MEDFileField.cxx index 52b6b0657..dfff9dbca 100644 --- a/src/MEDLoader/MEDFileField.cxx +++ b/src/MEDLoader/MEDFileField.cxx @@ -22,6 +22,7 @@ #include "MEDFileMesh.hxx" #include "MEDLoaderBase.hxx" #include "MEDFileUtilities.hxx" +#include "MEDFileFieldOverView.hxx" #include "MEDCouplingFieldDouble.hxx" #include "MEDCouplingFieldDiscretization.hxx" @@ -143,11 +144,11 @@ bool MEDFileFieldLoc::isEqual(const MEDFileFieldLoc& other, double eps) const return false; if(_geo_type!=other._geo_type) return false; - if(MEDCouplingGaussLocalization::AreAlmostEqual(_ref_coo,other._ref_coo,eps)) + if(!MEDCouplingGaussLocalization::AreAlmostEqual(_ref_coo,other._ref_coo,eps)) return false; - if(MEDCouplingGaussLocalization::AreAlmostEqual(_gs_coo,other._gs_coo,eps)) + if(!MEDCouplingGaussLocalization::AreAlmostEqual(_gs_coo,other._gs_coo,eps)) return false; - if(MEDCouplingGaussLocalization::AreAlmostEqual(_w,other._w,eps)) + if(!MEDCouplingGaussLocalization::AreAlmostEqual(_w,other._w,eps)) return false; return true; @@ -414,7 +415,7 @@ MEDFileFieldPerMeshPerTypePerDisc *MEDFileFieldPerMeshPerTypePerDisc::deepCpy(ME } MEDFileFieldPerMeshPerTypePerDisc::MEDFileFieldPerMeshPerTypePerDisc(MEDFileFieldPerMeshPerType *fath, TypeOfField atype, int profileIt) throw(INTERP_KERNEL::Exception) -try:_type(atype),_father(fath) +try:_type(atype),_father(fath),_profile_it(profileIt) { } catch(INTERP_KERNEL::Exception& e) @@ -440,7 +441,7 @@ const MEDFileFieldPerMeshPerType *MEDFileFieldPerMeshPerTypePerDisc::getFather() return _father; } -void MEDFileFieldPerMeshPerTypePerDisc::loadOnlyStructureOfDataRecursively(med_idt fid, int profileIt, int& start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::loadOnlyStructureOfDataRecursively(med_idt fid, int& start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { INTERP_KERNEL::AutoPtr locname=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr pflname=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); @@ -453,7 +454,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::loadOnlyStructureOfDataRecursively(med_i int profilesize,nbi; med_geometry_type mgeoti; med_entity_type menti=MEDFileFieldPerMeshPerType::ConvertIntoMEDFileType(type,geoType,mgeoti); - _nval=MEDfieldnValueWithProfile(fid,fieldName.c_str(),iteration,order,menti,mgeoti,profileIt,MED_COMPACT_PFLMODE, + _nval=MEDfieldnValueWithProfile(fid,fieldName.c_str(),iteration,order,menti,mgeoti,_profile_it,MED_COMPACT_PFLMODE, pflname,&profilesize,locname,&nbi); _profile=MEDLoaderBase::buildStringFromFortran(pflname,MED_NAME_SIZE); _localization=MEDLoaderBase::buildStringFromFortran(locname,MED_NAME_SIZE); @@ -472,7 +473,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::loadOnlyStructureOfDataRecursively(med_i } } -void MEDFileFieldPerMeshPerTypePerDisc::loadBigArray(med_idt fid, int profileIt, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::loadBigArray(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { std::string fieldName=nasc.getName(); std::string meshName=getMeshName(); @@ -1021,7 +1022,8 @@ void MEDFileFieldPerMeshPerType::assignNodeFieldNoProfile(int& start, const MEDC void MEDFileFieldPerMeshPerType::assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr pfl2=pfl->deepCpy(); - // + if(!arr || !arr->isAllocated()) + throw INTERP_KERNEL::Exception("MEDFileFieldPerMeshPerType::assignNodeFieldProfile : input array is null, or not allocated !"); _field_pm_pt_pd.resize(1); _field_pm_pt_pd[0]=MEDFileFieldPerMeshPerTypePerDisc::New(this,ON_NODES,-3); _field_pm_pt_pd[0]->assignFieldProfile(start,pfl,pfl2,pfl2,-1,field,arr,0,glob,nasc);//mesh is not requested so 0 is send. @@ -1048,7 +1050,7 @@ std::vector MEDFileFieldPerMeshPerType::addNewEntryIfNecessary(const MEDCou _field_pm_pt_pd.resize(sz+1); _field_pm_pt_pd[sz]=MEDFileFieldPerMeshPerTypePerDisc::New(this,type,locIdToFind); } - std::vector ret(1,0); + std::vector ret(1,(int)sz); return ret; } else @@ -1450,31 +1452,32 @@ MEDFileFieldPerMeshPerType::MEDFileFieldPerMeshPerType(med_idt fid, MEDFileField INTERP_KERNEL::AutoPtr pflName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr locName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); med_geometry_type mgeoti; - med_entity_type menti=ConvertIntoMEDFileType(type,geoType,mgeoti); + med_entity_type menti; + menti=ConvertIntoMEDFileType(type,geoType,mgeoti); int nbProfiles=MEDfieldnProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),menti,mgeoti,pflName,locName); _field_pm_pt_pd.resize(nbProfiles); for(int i=0;i >::iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++,pflId++) - { - (*it)->loadOnlyStructureOfDataRecursively(fid,pflId+1,start,nasc);//tony - } + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++) + (*it)->loadOnlyStructureOfDataRecursively(fid,start,nasc); } void MEDFileFieldPerMeshPerType::loadBigArraysRecursively(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { - int pflId=0; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++,pflId++) - { - (*it)->loadBigArray(fid,pflId+1,nasc);//tony - } + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++) + (*it)->loadBigArray(fid,nasc); } void MEDFileFieldPerMeshPerType::writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) @@ -2236,7 +2239,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishField2(TypeOfField type, cons return finishField(type,glob,dads,locs,mesh,isPfl,arrOut,nasc); } MEDCouplingAutoRefCountObjectPtr m2=mesh->buildPart(da->getConstPointer(),da->getConstPointer()+da->getNbOfElems()); - m2->setName(mesh->getName()); + m2->setName(mesh->getName().c_str()); MEDCouplingAutoRefCountObjectPtr ret=finishField(type,glob,dads,locs,m2,isPfl,arrOut,nasc); isPfl=true; return ret.retn(); @@ -2288,7 +2291,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishFieldNode2(const MEDFileField { MEDCouplingAutoRefCountObjectPtr da3=da->transformWithIndArrR(arr2->begin(),arr2->end()); arrOut->renumberInPlace(da3->getConstPointer()); - mesh2->setName(mesh->getName()); + mesh2->setName(mesh->getName().c_str()); ret->setMesh(mesh2); return ret.retn(); } @@ -2339,17 +2342,17 @@ MEDFileFieldPerMesh::MEDFileFieldPerMesh(med_idt fid, MEDFileAnyTypeField1TSWith INTERP_KERNEL::AutoPtr locName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); for(int i=0;i0) + int nbProfile =MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_CELL ,typmai[i],_mesh_csit,meshName,pflName,locName); + std::string name0(MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1)); + int nbProfile2=MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE_ELEMENT,typmai[i],_mesh_csit,meshName,pflName,locName); + std::string name1(MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1)); + if(nbProfile>0 || nbProfile2>0) { _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_CELLS,typmai2[i],nasc)); - _mesh_name=MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1); - } - nbProfile=MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE_ELEMENT,typmai[i],_mesh_csit,meshName,pflName,locName); - if(nbProfile>0) - { - _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_GAUSS_NE,typmai2[i],nasc)); - _mesh_name=MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1); + if(nbProfile>0) + _mesh_name=name0; + else + _mesh_name=name1; } } int nbProfile=MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE,MED_NONE,_mesh_csit,meshName,pflName,locName); @@ -2430,7 +2433,7 @@ void MEDFileFieldGlobs::appendGlobs(const MEDFileFieldGlobs& other, double eps) } } std::vector locs=getLocs(); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_locs.begin();it!=_locs.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=other._locs.begin();it!=other._locs.end();it++) { std::vector::iterator it2=std::find(locs.begin(),locs.end(),(*it)->getName()); if(it2==locs.end()) @@ -3579,8 +3582,8 @@ void MEDFileAnyTypeField1TSWithoutSDA::simpleRepr(int bkOffset, std::ostream& os std::string startOfLine(bkOffset,' '); oss << startOfLine << "Field "; if(bkOffset==0) - oss << "[Type=" << getTypeStr() << "] "; - oss << "on One time Step "; + oss << "[Type=" << getTypeStr() << "] with name \"" << getName() << "\" "; + oss << "on one time Step "; if(f1tsId>=0) oss << "(" << f1tsId << ") "; oss << "on iteration=" << _iteration << " order=" << _order << "." << std::endl; @@ -3591,7 +3594,6 @@ void MEDFileAnyTypeField1TSWithoutSDA::simpleRepr(int bkOffset, std::ostream& os const std::vector &comps=arr->getInfoOnComponents(); if(f1tsId<0) { - oss << startOfLine << "Field Name : \"" << arr->getName() << "\"." << std::endl; oss << startOfLine << "Field has " << comps.size() << " components with the following infos :" << std::endl; for(std::vector::const_iterator it=comps.begin();it!=comps.end();it++) oss << startOfLine << " - \"" << (*it) << "\"" << std::endl; @@ -4132,7 +4134,7 @@ bool MEDFileAnyTypeField1TSWithoutSDA::allocIfNecessaryTheArrayToReceiveDataFrom throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::allocIfNecessaryTheArrayToReceiveDataFromFile : trying to read from a file an empty instance ! Need to prepare the structure before !"); if(_nb_of_tuples_to_be_allocated<-3) throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::allocIfNecessaryTheArrayToReceiveDataFromFile : internal error !"); - + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::allocIfNecessaryTheArrayToReceiveDataFromFile : internal error !"); } void MEDFileAnyTypeField1TSWithoutSDA::loadOnlyStructureOfDataRecursively(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) @@ -4252,8 +4254,11 @@ void MEDFileAnyTypeField1TSWithoutSDA::setFieldNoProfileSBT(const MEDCouplingFie */ void MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile(const MEDCouplingFieldDouble *field, const DataArray *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { + if(!field) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile : input field is null !"); + if(!arrOfVals || !arrOfVals->isAllocated()) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile : input array is null or not allocated !"); TypeOfField type=field->getTypeOfField(); - int start=copyTinyInfoFrom(field,arrOfVals); std::vector idsInPflPerType; std::vector idsPerType; std::vector code,code2; @@ -4261,20 +4266,42 @@ void MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile(const MEDCouplingFieldDou if(type!=ON_NODES) { m->splitProfilePerType(profile,code,idsInPflPerType,idsPerType); + std::vector< MEDCouplingAutoRefCountObjectPtr > idsInPflPerType2(idsInPflPerType.size()); std::copy(idsInPflPerType.begin(),idsInPflPerType.end(),idsInPflPerType2.begin()); + std::vector< MEDCouplingAutoRefCountObjectPtr > idsPerType2(idsPerType.size()); std::copy(idsPerType.begin(),idsPerType.end(),idsPerType2.begin()); + std::vector idsPerType3(idsPerType.size()); std::copy(idsPerType.begin(),idsPerType.end(),idsPerType3.begin()); + // start of check + MEDCouplingAutoRefCountObjectPtr field2=field->clone(false); + if(type==ON_GAUSS_NE) + { + MEDCouplingAutoRefCountObjectPtr mPart=m->buildPart(profile->begin(),profile->end()); + field2->setMesh(mPart); + } + int nbOfTuplesExp=field2->getNumberOfTuplesExpectedRegardingCode(code,idsPerType3); + if(nbOfTuplesExp!=arrOfVals->getNumberOfTuples()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile : The array is expected to have " << nbOfTuplesExp << " tuples ! It has " << arrOfVals->getNumberOfTuples() << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + // end of check + int start=copyTinyInfoFrom(field,arrOfVals); code2=m->getDistributionOfTypes(); // - std::vector< MEDCouplingAutoRefCountObjectPtr > idsInPflPerType2(idsInPflPerType.size()); - for(std::size_t i=0;i > idsPerType2(idsPerType.size()); - for(std::size_t i=0;iassignFieldProfile(start,profile,code,code2,idsInPflPerType,idsPerType,field,arrOfVals,m,glob,nasc); } else { + if(!profile || !profile->isAllocated() || profile->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile : input profile is null, not allocated or with number of components != 1 !"); + std::vector v(3); v[0]=-1; v[1]=profile->getNumberOfTuples(); v[2]=0; + std::vector idsPerType3(1); idsPerType3[0]=profile; + int nbOfTuplesExp=field->getNumberOfTuplesExpectedRegardingCode(v,idsPerType3); + if(nbOfTuplesExp!=arrOfVals->getNumberOfTuples()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile : For node field, the array is expected to have " << nbOfTuplesExp << " tuples ! It has " << arrOfVals->getNumberOfTuples() << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int start=copyTinyInfoFrom(field,arrOfVals); int pos=addNewEntryIfNecessary(m); _field_per_mesh[pos]->assignNodeFieldProfile(start,profile,field,arrOfVals,glob,nasc); } @@ -4494,7 +4521,7 @@ MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldAtTopLevel(Typ MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfField type, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, const DataArrayInt *cellRenum, const DataArrayInt *nodeRenum, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { static const char msg1[]="MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel : request for a renumbered field following mesh numbering whereas it is a profile field !"; - int meshId=getMeshIdFromMeshName(mesh->getName()); + int meshId=getMeshIdFromMeshName(mesh->getName().c_str()); bool isPfl=false; MEDCouplingAutoRefCountObjectPtr ret=_field_per_mesh[meshId]->getFieldOnMeshAtLevel(type,glob,mesh,isPfl,arrOut,nasc); switch(renumPol) @@ -4572,7 +4599,7 @@ MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel( DataArray *MEDFileAnyTypeField1TSWithoutSDA::getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr m=mesh->getGenMeshAtLevel(meshDimRelToMax); - int meshId=getMeshIdFromMeshName(mesh->getName()); + int meshId=getMeshIdFromMeshName(mesh->getName().c_str()); MEDCouplingAutoRefCountObjectPtr ret=_field_per_mesh[meshId]->getFieldOnMeshAtLevelWithPfl(type,m,pfl,glob,nasc); ret->setName(nasc.getName().c_str()); return ret.retn(); @@ -6197,17 +6224,18 @@ void MEDFileField1TS::setFieldNoProfileSBT(const MEDCouplingFieldDouble *field) } /*! - * Adds a MEDCouplingFieldDouble to \a this. Specified entities of a given dimension - * of a given mesh are used as the support of the given field (a real support is not used). - * Elements of the given mesh must be sorted suitable for writing to MED file. - * Order of underlying mesh entities of the given field specified by \a profile parameter - * is not prescribed; this method permutes field values to have them sorted by element - * type as required for writing to MED file. A new profile is added only if no equal - * profile is missing. + * Adds a MEDCouplingFieldDouble to \a this. As described in \ref MEDLoaderMainC a field in MED file sense + * can be an aggregation of several MEDCouplingFieldDouble instances. + * The mesh support of input parameter \a field is ignored here, it can be NULL. + * The support of field \a field is expected to be those computed with the input parameter \a mesh, \a meshDimRelToMax, + * and \a profile. + * + * This method will check that the field based on the computed support is coherent. If not an exception will be thrown. + * A new profile is added only if no equal profile is missing. * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] field - the field to add to \a this. + * \param [in] field - the field to add to \a this. The mesh support of field is ignored. * \param [in] mesh - the supporting mesh of \a field. - * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on (useless if field spatial discretization is ON_NODES). * \param [in] profile - ids of mesh entities on which corresponding field values lie. * \throw If either \a field or \a mesh or \a profile has an empty name. * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. @@ -6372,18 +6400,19 @@ void MEDFileIntField1TS::setFieldNoProfileSBT(const MEDCouplingFieldDouble *fiel } /*! - * Adds a MEDCouplingFieldDouble to \a this. Specified entities of a given dimension - * of a given mesh are used as the support of the given field (a real support is not used). - * Elements of the given mesh must be sorted suitable for writing to MED file. - * Order of underlying mesh entities of the given field specified by \a profile parameter - * is not prescribed; this method permutes field values to have them sorted by element - * type as required for writing to MED file. A new profile is added only if no equal - * profile is missing. + * Adds a MEDCouplingFieldDouble to \a this. As described in \ref MEDLoaderMainC a field in MED file sense + * can be an aggregation of several MEDCouplingFieldDouble instances. + * The mesh support of input parameter \a field is ignored here, it can be NULL. + * The support of field \a field is expected to be those computed with the input parameter \a mesh, \a meshDimRelToMax, + * and \a profile. + * + * This method will check that the field based on the computed support is coherent. If not an exception will be thrown. + * A new profile is added only if no equal profile is missing. * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] field - the field to add to \a this. The field double values are ignored. + * \param [in] field - the field to add to \a this. The field double values and mesh support are ignored. * \param [in] arrOfVals - the values of the field \a field used. * \param [in] mesh - the supporting mesh of \a field. - * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on (useless if field spatial discretization is ON_NODES). * \param [in] profile - ids of mesh entities on which corresponding field values lie. * \throw If either \a field or \a mesh or \a profile has an empty name. * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. @@ -8178,6 +8207,207 @@ MEDFileAnyTypeField1TS *MEDFileAnyTypeFieldMultiTS::getTimeStepGivenTime(double return getTimeStepAtPos(pos); } +/*! + * This method groups not null items in \a vectFMTS per time step series. Two time series are considered equal if the list of their pair of integers iteration,order are equal. + * The float64 value of time attached to the pair of integers are not considered here. + * + * \param [in] vectFMTS - vector of not null fields defined on a same global data pointer. + * \throw If there is a null pointer in \a vectFMTS. + */ +std::vector< std::vector > MEDFileAnyTypeFieldMultiTS::SplitIntoCommonTimeSeries(const std::vector& vectFMTS) throw(INTERP_KERNEL::Exception) +{ + static const char msg[]="MEDFileAnyTypeFieldMultiTS::SplitIntoCommonTimeSeries : presence of null instance in input vector !"; + std::vector< std::vector > ret; + std::list lstFMTS(vectFMTS.begin(),vectFMTS.end()); + while(!lstFMTS.empty()) + { + std::list::iterator it(lstFMTS.begin()); + MEDFileAnyTypeFieldMultiTS *curIt(*it); + if(!curIt) + throw INTERP_KERNEL::Exception(msg); + std::vector< std::pair > refIts=curIt->getIterations(); + std::vector elt; + elt.push_back(curIt); it=lstFMTS.erase(it); + while(it!=lstFMTS.end()) + { + curIt=*it; + if(!curIt) + throw INTERP_KERNEL::Exception(msg); + std::vector< std::pair > curIts=curIt->getIterations(); + if(refIts==curIts) + { elt.push_back(curIt); it=lstFMTS.erase(it); } + else + it++; + } + ret.push_back(elt); + } + return ret; +} + +/*! + * This method splits the input list \a vectFMTS considering the aspect of the geometrical support over time. + * All returned instances in a subvector can be safely loaded, rendered along time + * All items must be defined on the same time step ids ( see MEDFileAnyTypeFieldMultiTS::SplitIntoCommonTimeSeries method ). + * Each item in \a vectFMTS is expected to have one and exactly one spatial discretization along time. + * All items in \a vectFMTS must lie on the mesh (located by meshname and time step) and compatible with the input mesh \a mesh (having the same name than those in items). + * All items in \a vectFMTS whose spatial discretization is not ON_NODES will appear once. + * For items in \a vectFMTS that are ON_NODES it is possible to appear several times (more than once or once) in the returned vector. + * + * \param [in] vectFMTS - list of multi times step part all defined each on a same spatial discretization along time and pointing to a mesh whose name is equal to \c mesh->getName(). + * \param [in] mesh - the mesh shared by all items in \a vectFMTS across time. + * + * \throw If an element in \a vectFMTS has not only one spatial discretization set. + * \throw If an element in \a vectFMTS change of spatial discretization along time. + * \throw If an element in \a vectFMTS lies on a mesh with meshname different from those in \a mesh. + * \thorw If some elements in \a vectFMTS do not have the same times steps. + * \throw If mesh is null. + * \throw If an element in \a vectFMTS is null. + * \sa MEDFileAnyTypeFieldMultiTS::AreOnSameSupportAcrossTime + */ +std::vector< std::vector > MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport(const std::vector& vectFMTS, const MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception) +{ + static const char msg[]="MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport : presence of a null instance in the input vector !"; + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport : input mesh is null !"); + std::vector< std::vector > ret; + if(vectFMTS.empty()) + return ret; + std::vector::const_iterator it(vectFMTS.begin()); + MEDFileAnyTypeFieldMultiTS *frstElt(*it); + std::size_t i=0; + std::vector vectFMTSNotNodes; + std::vector vectFMTSNodes; + for(;it!=vectFMTS.end();it++,i++) + { + TypeOfField tof0,tof1; + int ret=CheckSupportAcrossTime(frstElt,*it,mesh,tof0,tof1); + if(ret>0) + { + if(tof1!=ON_NODES) + vectFMTSNotNodes.push_back(*it); + else + vectFMTSNodes.push_back(*it); + } + else + vectFMTSNotNodes.push_back(*it); + } + std::vector< MEDCouplingAutoRefCountObjectPtr > cmps; + std::vector< std::vector > retCell=SplitPerCommonSupportNotNodesAlg(vectFMTSNotNodes,mesh,cmps); + ret=retCell; + for(std::vector::const_iterator it2=vectFMTSNodes.begin();it2!=vectFMTSNodes.end();it2++) + { + i=0; + for(std::vector< std::vector >::const_iterator it0=retCell.begin();it0!=retCell.end();it0++,i++) + { + if((*it0).empty()) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport : internal error !"); + if(cmps[i]->isCompatibleWithNodesDiscr(*it2)) + ret[i].push_back(*it2); + else + { + std::vector ret0(1,*it2); + ret.push_back(ret0); + } + } + } + return ret; +} + +/*! + * WARNING no check here. The caller must be sure that all items in vectFMTS are coherent each other in time steps, only one same spatial discretization and not ON_NODES. + * \param [out] cmps - same size than the returned vector. + */ +std::vector< std::vector > MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupportNotNodesAlg(const std::vector& vectFMTS, const MEDFileMesh *mesh, std::vector< MEDCouplingAutoRefCountObjectPtr >& cmps) throw(INTERP_KERNEL::Exception) +{ + std::vector< std::vector > ret; + std::list lstFMTS(vectFMTS.begin(),vectFMTS.end()); + while(!lstFMTS.empty()) + { + std::list::iterator it(lstFMTS.begin()); + MEDFileAnyTypeFieldMultiTS *ref(*it); + std::vector elt; + elt.push_back(ref); it=lstFMTS.erase(it); + MEDCouplingAutoRefCountObjectPtr mst(MEDFileMeshStruct::New(mesh)); + MEDCouplingAutoRefCountObjectPtr cmp(MEDFileFastCellSupportComparator::New(mst,ref)); + while(it!=lstFMTS.end()) + { + MEDFileAnyTypeFieldMultiTS *curIt(*it); + if(cmp->isEqual(curIt)) + { elt.push_back(curIt); it=lstFMTS.erase(it); } + else + it++; + } + ret.push_back(elt); cmps.push_back(cmp); + } + return ret; +} + +/*! + * This method scan the two main structs along time of \a f0 and \a f1 to see if there are all lying on the same mesh along time than those in \a mesh. + * \a f0 and \a f1 must be defined each only on a same spatial discretization even if this can be different each other. + * + * \throw If \a f0 or \a f1 has not only one spatial discretization set. + * \throw If \a f0 or \a f1 change of spatial discretization along time. + * \throw If \a f0 or \a f1 on a mesh with meshname different from those in \a mesh. + * \thorw If \a f0 and \a f1 do not have the same times steps. + * \throw If mesh is null. + * \throw If \a f0 or \a f1 is null. + * \sa MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport + */ +int MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime(MEDFileAnyTypeFieldMultiTS *f0, MEDFileAnyTypeFieldMultiTS *f1, const MEDFileMesh *mesh, TypeOfField& tof0, TypeOfField& tof1) throw(INTERP_KERNEL::Exception) +{ + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : input mesh is null !"); + if(!f0 || !f1) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : presence of null instance in fields over time !"); + if(f0->getMeshName()!=mesh->getName()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : first field points to mesh \""<< f0->getMeshName() << "\" and input mesh to compare has name \"" << mesh->getName() << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(f1->getMeshName()!=mesh->getName()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : second field points to mesh \""<< f1->getMeshName() << "\" and input mesh to compare has name \"" << mesh->getName() << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int nts=f0->getNumberOfTS(); + if(nts!=f1->getNumberOfTS()) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : number of time steps are not the same !"); + if(nts==0) + return nts; + for(int i=0;i f0cur=f0->getTimeStepAtPos(i); + MEDCouplingAutoRefCountObjectPtr f1cur=f1->getTimeStepAtPos(i); + std::vector tofs0(f0cur->getTypesOfFieldAvailable()),tofs1(f1cur->getTypesOfFieldAvailable()); + if(tofs0.size()!=1 || tofs1.size()!=1) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : All time steps must be defined on only one spatial discretization !"); + if(i!=0) + { + if(tof0!=tofs0[0] || tof1!=tofs1[0]) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : Across times steps MEDFileAnyTypeFieldMultiTS instances have to keep the same unique spatial discretization !"); + } + else + { tof0=tofs0[0]; tof1=tofs1[0]; } + if(f0cur->getMeshIteration()!=mesh->getIteration() || f0cur->getMeshOrder()!=mesh->getOrder()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : first field points to mesh time step (" << f0cur->getMeshIteration() << ","<< f0cur->getMeshOrder() << ") whereas input mesh points to time step (" << mesh->getIteration() << "," << mesh->getOrder() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(f1cur->getMeshIteration()!=mesh->getIteration() || f1cur->getMeshOrder()!=mesh->getOrder()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : second field points to mesh time step (" << f1cur->getMeshIteration() << ","<< f1cur->getMeshOrder() << ") whereas input mesh points to time step (" << mesh->getIteration() << "," << mesh->getOrder() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(f0cur->getIteration()!=f1cur->getIteration() || f0cur->getOrder()!=f1cur->getOrder()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::CheckSupportAcrossTime : all the time steps must be the same ! it is not the case (" << f0cur->getIteration() << "," << f0cur->getOrder() << ")!=(" << f1cur->getIteration() << "," << f1cur->getOrder() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + return nts; +} + MEDFileAnyTypeFieldMultiTSIterator *MEDFileAnyTypeFieldMultiTS::iterator() throw(INTERP_KERNEL::Exception) { return new MEDFileAnyTypeFieldMultiTSIterator(this); @@ -8535,22 +8765,25 @@ void MEDFileFieldMultiTS::appendFieldNoProfileSBT(const MEDCouplingFieldDouble * } /*! - * Adds a MEDCouplingFieldDouble to \a this as another time step. Specified entities of - * a given dimension of a given mesh are used as the support of the given field. - * Elements of the given mesh must be sorted suitable for writing to MED file. - * Order of underlying mesh entities of the given field specified by \a profile parameter - * is not prescribed; this method permutes field values to have them sorted by element - * type as required for writing to MED file. + * Adds a MEDCouplingFieldDouble to \a this as another time step. + * The mesh support of input parameter \a field is ignored here, it can be NULL. + * The support of field \a field is expected to be those computed with the input parameter \a mesh, \a meshDimRelToMax, + * and \a profile. + * + * This method will check that the field based on the computed support is coherent. If not an exception will be thrown. + * A new profile is added only if no equal profile is missing. * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] field - the field to add to \a this. + * \param [in] field - the field to add to \a this. The mesh support of field is ignored. * \param [in] mesh - the supporting mesh of \a field. - * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on (useless if field spatial discretization is ON_NODES). * \param [in] profile - ids of mesh entities on which corresponding field values lie. * \throw If either \a field or \a mesh or \a profile has an empty name. - * \throw If existing time steps have different name or number of components than \a field. * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. * \throw If the data array of \a field is not set. + * \throw If the data array of \a this is already allocated but has different number of + * components than \a field. * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. + * \sa setFieldNoProfileSBT() */ void MEDFileFieldMultiTS::appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) { @@ -8958,22 +9191,26 @@ void MEDFileIntFieldMultiTS::appendFieldNoProfileSBT(const MEDCouplingFieldDoubl } /*! - * Adds a MEDCouplingFieldDouble to \a this as another time step. Specified entities of - * a given dimension of a given mesh are used as the support of the given field. - * Elements of the given mesh must be sorted suitable for writing to MED file. - * Order of underlying mesh entities of the given field specified by \a profile parameter - * is not prescribed; this method permutes field values to have them sorted by element - * type as required for writing to MED file. + * Adds a MEDCouplingFieldDouble to \a this as another time step. + * The mesh support of input parameter \a field is ignored here, it can be NULL. + * The support of field \a field is expected to be those computed with the input parameter \a mesh, \a meshDimRelToMax, + * and \a profile. + * + * This method will check that the field based on the computed support is coherent. If not an exception will be thrown. + * A new profile is added only if no equal profile is missing. * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] field - the field to add to \a this. + * \param [in] field - the field to add to \a this. The field double values and mesh support are ignored. + * \param [in] arrOfVals - the values of the field \a field used. * \param [in] mesh - the supporting mesh of \a field. - * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on (useless if field spatial discretization is ON_NODES). * \param [in] profile - ids of mesh entities on which corresponding field values lie. * \throw If either \a field or \a mesh or \a profile has an empty name. - * \throw If existing time steps have different name or number of components than \a field. * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. * \throw If the data array of \a field is not set. + * \throw If the data array of \a this is already allocated but has different number of + * components than \a field. * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. + * \sa setFieldNoProfileSBT() */ void MEDFileIntFieldMultiTS::appendFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) { @@ -9553,7 +9790,6 @@ MEDFileAnyTypeFieldMultiTS *MEDFileFields::getFieldWithName(const char *fieldNam MEDFileFields *MEDFileFields::partOfThisLyingOnSpecifiedMeshName(const char *meshName) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr ret=MEDFileFields::New(); - ret->shallowCpyOnlyUsedGlobs(*this); for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) { const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it); @@ -9566,6 +9802,7 @@ MEDFileFields *MEDFileFields::partOfThisLyingOnSpecifiedMeshName(const char *mes ret->_fields.push_back(cur2); } } + ret->shallowCpyOnlyUsedGlobs(*this); return ret.retn(); }