1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay
21 #include "MEDCouplingAMRAttribute.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingIMesh.hxx"
28 using namespace ParaMEDMEM;
30 DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair<std::string,int> >& fieldNames)
32 return new DataArrayDoubleCollection(fieldNames);
35 void DataArrayDoubleCollection::allocTuples(int nbOfTuples)
37 std::size_t sz(_arrs.size());
38 for(std::size_t i=0;i<sz;i++)
39 _arrs[i]->reAlloc(nbOfTuples);
42 void DataArrayDoubleCollection::dellocTuples()
44 std::size_t sz(_arrs.size());
45 for(std::size_t i=0;i<sz;i++)
49 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
51 std::size_t sz(_arrs.size());
52 if(sz!=compNames.size())
53 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillInfoOnComponents : first size of compNames has to be equal to the number of fields defined !");
54 for(std::size_t i=0;i<sz;i++)
56 const std::vector<std::string>& names(compNames[i]);
57 _arrs[i]->setInfoOnComponents(names);
61 std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
63 std::size_t sz(_arrs.size());
64 std::vector<DataArrayDouble *> ret(sz);
65 for(std::size_t i=0;i<sz;i++)
67 const DataArrayDouble *tmp(_arrs[i]);
68 ret[i]=const_cast<DataArrayDouble *>(tmp);
75 const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) const
77 std::vector<std::string> vec;
78 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
80 const DataArrayDouble *obj(*it);
83 if(obj->getName()==name)
86 vec.push_back(obj->getName());
89 std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
90 std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
91 throw INTERP_KERNEL::Exception(oss.str().c_str());
94 void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse)
97 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collections must be non NULL !");
98 std::size_t sz(coarse->_arrs.size());
99 if(fine->_arrs.size()!=sz)
100 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !");
101 for(std::size_t i=0;i<sz;i++)
102 fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i],coarse->_arrs[i],ghostLev);
105 void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
108 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collections must be non NULL !");
109 std::size_t sz(coarse->_arrs.size());
110 if(fine->_arrs.size()!=sz)
111 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !");
112 for(std::size_t i=0;i<sz;i++)
113 fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
116 void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector<const MEDCouplingCartesianAMRMeshGen *>& children, const std::vector<DataArrayDoubleCollection *>& fieldsOnFine)
118 if(!fatherOfFineMesh)
119 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : father is NULL !");
120 std::size_t sz(children.size());
121 if(fieldsOnFine.size()!=sz)
122 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : sizes of vectors mismatch !");
125 std::size_t nbOfCall(fieldsOnFine[0]->_arrs.size());
126 for(std::size_t i=0;i<sz;i++)
127 if(fatherOfFineMesh->getPatchIdFromChildMesh(children[i])!=(int)i)
128 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : internal error !");
129 for(std::size_t i=1;i<sz;i++)
130 if(nbOfCall!=fieldsOnFine[i]->_arrs.size())
131 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : the collection of DataArrayDouble must have all the same size !");
132 for(std::size_t i=0;i<nbOfCall;i++)
134 std::vector<const DataArrayDouble *> arrs(sz);
135 for(std::size_t j=0;j<sz;j++)
136 arrs[j]=fieldsOnFine[j]->_arrs[i];
137 fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs);
142 * This method updates \a p1dac ghost zone parts using \a p2dac (which is really const). \a p2 is in the neighborhood of \a p1 (which size is defined by \a ghostLev).
144 void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const DataArrayDoubleCollection *p1dac, const MEDCouplingCartesianAMRPatch *p2, const DataArrayDoubleCollection *p2dac)
146 if(!p1 || !p1dac || !p2 || !p2dac)
147 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : input pointer must be not NULL !");
148 std::size_t sz(p1dac->_arrs.size());
149 if(p2dac->_arrs.size()!=sz)
150 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : size of DataArrayDouble Collection must be the same !");
151 for(std::size_t i=0;i<sz;i++)
153 const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i]);
154 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i]);
158 void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
161 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collections must be non NULL !");
162 std::size_t sz(coarse->_arrs.size());
163 if(fine->_arrs.size()!=sz)
164 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !");
165 for(std::size_t i=0;i<sz;i++)
166 fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
169 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
171 DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
172 std::size_t sz(_arrs.size());
173 if(other._arrs.size()!=sz)
174 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
175 for(std::size_t i=0;i<sz;i++)
176 father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
179 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
181 DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
182 std::size_t sz(_arrs.size());
183 if(other._arrs.size()!=sz)
184 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
185 for(std::size_t i=0;i<sz;i++)
186 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
189 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
191 std::size_t sz(fieldNames.size());
192 std::vector<std::string> names(sz);
193 for(std::size_t i=0;i<sz;i++)
195 const std::pair<std::string,int>& info(fieldNames[i]);
196 _arrs[i]=DataArrayDouble::New();
197 _arrs[i]->alloc(0,info.second);
198 _arrs[i]->setName(info.first);
199 names[i]=info.second;
201 CheckDiscriminantNames(names);
204 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
206 std::size_t ret(sizeof(DataArrayDoubleCollection));
207 ret+=_arrs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>);
211 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
213 std::vector<const BigMemoryObject *> ret;
214 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
216 const DataArrayDouble *pt(*it);
223 void DataArrayDoubleCollection::updateTime() const
225 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
227 const DataArrayDouble *pt(*it);
233 void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::string>& names)
235 std::set<std::string> s(names.begin(),names.end());
236 if(s.size()!=names.size())
237 throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
240 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
242 return new MEDCouplingGridCollection(ms,fieldNames);
245 void MEDCouplingGridCollection::alloc(int ghostLev)
247 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
249 int nbTuples((*it).first->getNumberOfCellsAtCurrentLevelGhost(ghostLev));
250 DataArrayDoubleCollection *dadc((*it).second);
252 dadc->allocTuples(nbTuples);
254 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::alloc : internal error !");
258 void MEDCouplingGridCollection::dealloc()
260 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
262 DataArrayDoubleCollection *dadc((*it).second);
264 dadc->dellocTuples();
266 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::dealloc : internal error !");
270 void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
272 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
273 (*it).second->spillInfoOnComponents(compNames);
276 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
279 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++)
290 const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) const
292 if(pos<0 || pos>(int)_map_of_dadc.size())
293 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt : invalid pos given in input ! Must be in [0,size) !");
294 return *_map_of_dadc[pos].second;
297 void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
300 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !");
301 const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
302 const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
303 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
305 const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
306 const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
308 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
310 if((*it0).first==fatherOfFineMesh)
313 int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
314 const DataArrayDoubleCollection *coarseDaCol((*it0).second);
315 DataArrayDoubleCollection *coarseModified(const_cast<DataArrayDoubleCollection *>(coarseDaCol));//coarse values in DataArrayDouble will be altered
316 DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified);
320 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !");
324 void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
327 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !");
328 const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
329 const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
330 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
332 const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
333 const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
335 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
337 if((*it0).first==fatherOfFineMesh)
340 int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
341 const DataArrayDoubleCollection *fineDaCol((*it).second);
342 DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
343 DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
347 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !");
352 * All the pairs in \a ps must share the same father. If not call synchronizeFineEachOtherExt instead.
354 * \sa synchronizeFineEachOtherExt
356 void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
358 for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
361 if(!presenceOf((*it).first->getMesh(),p1))
362 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #1 !");
363 if(!presenceOf((*it).second->getMesh(),p2))
364 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #2 !");
365 const DataArrayDoubleCollection& col1(getFieldsAt(p1));
366 const DataArrayDoubleCollection& col2(getFieldsAt(p2));
367 col1.synchronizeMyGhostZoneUsing(ghostLev,col2,(*it).first,(*it).second,(*it).first->getMesh()->getFather());
372 * This method is a generalization of synchronizeFineEachOther because elements in pairs are \b not sharing the same father but are neighbors nevertheless.
374 * \sa synchronizeFineEachOther
376 void MEDCouplingGridCollection::synchronizeFineEachOtherExt(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
378 for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
381 if(!presenceOf((*it).first->getMesh(),p1))
382 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #1 !");
383 if(!presenceOf((*it).second->getMesh(),p2))
384 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #2 !");
385 const DataArrayDoubleCollection& col1(getFieldsAt(p1));
386 const DataArrayDoubleCollection& col2(getFieldsAt(p2));
387 col1.synchronizeMyGhostZoneUsingExt(ghostLev,col2,(*it).first,(*it).second);
392 * The pairs returned share the same direct father. The number of returned elements must be even.
394 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > MEDCouplingGridCollection::findNeighbors(int ghostLev) const
396 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > ret;
397 std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > > m;
398 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
400 const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
401 const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
402 m[fatherOfFineMesh].push_back(fineMesh);
404 for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > >::const_iterator it0=m.begin();it0!=m.end();it0++)
406 for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
408 int patchId((*it0).first->getPatchIdFromChildMesh(*it1));
409 std::vector<int> neighs((*it0).first->getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
410 const MEDCouplingCartesianAMRPatch *pRef((*it0).first->getPatch(patchId));
411 for(std::vector<int>::const_iterator it2=neighs.begin();it2!=neighs.end();it2++)
413 const MEDCouplingCartesianAMRPatch *pLoc((*it0).first->getPatch(*it2));
414 ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(pRef,pLoc));
419 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::findNeighbors : something is wrong ! The number of neighbor pairs must be %2 ==0 !");
423 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
426 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !");
427 const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mf(fine->_map_of_dadc);
428 const std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >& mc(coarse->_map_of_dadc);
429 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=mf.begin();it!=mf.end();it++)
431 const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
432 const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
434 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++)
436 if((*it0).first==fatherOfFineMesh)
439 int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh));
440 const DataArrayDoubleCollection *fineDaCol((*it).second);
441 DataArrayDoubleCollection *fineModified(const_cast<DataArrayDoubleCollection *>(fineDaCol));//fine values in DataArrayDouble will be altered
442 DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified);
446 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !");
450 void MEDCouplingGridCollection::fillIfInTheProgenyOf(const std::string& fieldName, const MEDCouplingCartesianAMRMeshGen *head, std::vector<const DataArrayDouble *>& recurseArrs) const
452 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
454 const MEDCouplingCartesianAMRMeshGen *a((*it).first);
455 if(head==a || head->isObjectInTheProgeny(a))
457 const DataArrayDoubleCollection *gc((*it).second);
458 recurseArrs.push_back(gc->getFieldWithName(fieldName));
463 MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames):_map_of_dadc(ms.size())
465 std::size_t sz(ms.size());
466 for(std::size_t i=0;i<sz;i++)
469 throw INTERP_KERNEL::Exception("MEDCouplingGridCollection constructor : presence of NULL MEDCouplingCartesianAMRMeshGen instance !");
470 _map_of_dadc[i].first=ms[i];
471 _map_of_dadc[i].second=DataArrayDoubleCollection::New(fieldNames);
475 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
477 std::size_t ret(sizeof(MEDCouplingGridCollection));
478 ret+=_map_of_dadc.capacity()*sizeof(std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> >);
482 std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildren() const
484 std::vector<const BigMemoryObject *> ret;
485 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
487 const DataArrayDoubleCollection *col((*it).second);
494 void MEDCouplingGridCollection::updateTime() const
496 for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
498 const MEDCouplingCartesianAMRMeshGen *a((*it).first);
501 const DataArrayDoubleCollection *b((*it).second);
508 * This method creates, attach to a main AMR mesh \a gf ( called god father :-) ) and returns a data linked to \a gf ready for the computation.
510 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
512 return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
515 MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
517 std::size_t sz(fieldNames.size());
518 std::vector< std::pair<std::string,int> > fieldNames2(sz);
519 std::vector< std::vector<std::string> > compNames(sz);
520 for(std::size_t i=0;i<sz;i++)
522 fieldNames2[i].first=fieldNames[i].first;
523 fieldNames2[i].second=(int)fieldNames[i].second.size();
524 compNames[i]=fieldNames[i].second;
526 MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
527 ret->spillInfoOnComponents(compNames);
532 * Assign the info on components for all DataArrayDouble instance recursively stored in \a this.
533 * The first dim of input \a compNames is the field id in the same order than those implicitely specified in \a fieldNames parameter of MEDCouplingAMRAttribute::New.
534 * The second dim of \a compNames represent the component names component per component corresponding to the field. The size of this 2nd dimension has
535 * to perfectly fit with those specified in MEDCouplingAMRAttribute::New.
537 void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
540 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
541 (*it)->spillInfoOnComponents(compNames);
545 * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
546 * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
548 * \return std::vector<DataArrayDouble *> - DataArrayDouble instances to be deallocated by the caller (using decrRef).
549 * \sa retrieveFieldOn
551 std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const
553 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
556 if((*it)->presenceOf(mesh,tmp))
558 const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
559 return ddc.retrieveFields();
562 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !");
566 * \sa retrieveFieldsOn
568 const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
570 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
573 if((*it)->presenceOf(mesh,tmp))
575 const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
576 return ddc.getFieldWithName(fieldName);
579 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
583 * This method returns a field on an unstructured mesh the most refined as possible without overlap.
584 * Ghost part are not visible here.
586 * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
588 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
590 std::vector<const DataArrayDouble *> recurseArrs;
592 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++,lev++)
595 if((*it)->presenceOf(mesh,tmp))
597 const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
598 recurseArrs.push_back(ddc.getFieldWithName(fieldName));
603 for(std::size_t i=lev;i<_levs.size();i++)
605 const MEDCouplingGridCollection *gc(_levs[i]);
606 gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
608 return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
612 * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
613 * The output field also displays ghost cells.
615 * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
617 * \sa buildCellFieldOnWithoutGhost
619 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
621 const DataArrayDouble *arr(0);
622 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
625 if((*it)->presenceOf(mesh,tmp))
627 const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
628 arr=ddc.getFieldWithName(fieldName);
632 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
633 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
636 ret->setArray(const_cast<DataArrayDouble *>(arr));
637 ret->setName(arr->getName());
642 * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
643 * The output field does not display ghost cells.
645 * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
647 * \sa buildCellFieldOnWithGhost
649 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
652 const DataArrayDouble *arr(0);
653 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
656 if((*it)->presenceOf(mesh,tmp))
658 const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
659 arr=ddc.getFieldWithName(fieldName);
663 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost : the mesh specified is not in the progeny of this !");
665 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
666 std::vector<int> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
667 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(DataArrayDouble::New());
668 arr2->alloc(mesh->getImageMesh()->getNumberOfCells(),arr->getNumberOfComponents());
669 std::vector< std::pair<int,int> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
670 MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
671 std::vector<int> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
672 MEDCouplingIMesh::SpreadCoarseToFine(arr,cgsWG,arr2,cgs2,fakeFactors);
673 arr2->copyStringInfoFrom(*arr);
675 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
676 ret->setMesh(mesh->getImageMesh());
678 ret->setName(arr->getName());
683 * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
684 * MEDCouplingAMRAttribute::alloc method.
686 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
689 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
690 std::size_t sz(_levs.size());
695 const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
696 MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
701 * This method synchronizes from coarse to fine arrays and fine to fine each other (if _ghost_lev is >0). This method makes the hypothesis that \a this has been allocated before using
702 * MEDCouplingAMRAttribute::alloc method.
704 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
707 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
708 std::size_t sz(_levs.size());
710 for(std::size_t i=1;i<sz;i++)
712 const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
713 MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
718 * This method synchronizes the ghost zone of all patches (excepted the god father one).
719 * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
721 * - firstly coarse to fine with no interactions between brother patches.
722 * - secondly connected brother patches in a same master patch are updated.
723 * - thirdly connected nephew patches are updated each other.
724 * - forthly nth generation cousin patches are updated each other.
726 * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
727 * So if \a _ghost_lev == 0 this method has no effect.
729 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
732 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
733 // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
734 std::size_t sz(_levs.size());
735 for(std::size_t i=1;i<sz;i++)
737 const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
738 MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
740 // 2nd - classical direct sublevel inside common patch
741 for(std::size_t i=1;i<sz;i++)
743 const MEDCouplingGridCollection *fine(_levs[i]);
745 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
746 fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
749 for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
751 const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
752 DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
754 // 4th - same level but with far ancestor.
755 for(std::size_t i=1;i<sz;i++)
757 const MEDCouplingGridCollection *fine(_levs[i]);
758 fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
763 * This method allocates all DataArrayDouble instances stored recursively in \a this.
767 void MEDCouplingAMRAttribute::alloc()
770 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
772 MEDCouplingGridCollection *elt(*it);
774 elt->alloc(_ghost_lev);
776 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
781 * This method deallocates all DataArrayDouble instances stored recursively in \a this.
784 void MEDCouplingAMRAttribute::dealloc()
787 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
789 MEDCouplingGridCollection *elt(*it);
793 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::dealloc : internal error !");
797 bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
799 bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
803 std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
805 std::size_t ret(sizeof(MEDCouplingAMRAttribute));
806 ret+=_levs.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection>);
810 std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
812 std::vector<const BigMemoryObject *> ret;
813 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
815 const MEDCouplingGridCollection *elt(*it);
822 void MEDCouplingAMRAttribute::updateTime() const
826 MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
828 //gf non empty, checked by constructor
829 int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
830 _levs.resize(maxLev);
831 for(int i=0;i<maxLev;i++)
833 std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
834 std::size_t sz(patches.size());
835 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(patches.size());
836 for(std::size_t j=0;j<sz;j++)
837 patchesSafe[j]=patches[j];
838 std::vector<const MEDCouplingCartesianAMRMeshGen *> ms(sz);
839 for(std::size_t j=0;j<sz;j++)
841 ms[j]=patches[j]->getMesh();
843 _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
845 // updates cross levels neighbors
846 _neighbors.resize(_levs.size());
847 _cross_lev_neighbors.resize(_levs.size());
849 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
850 std::size_t sz(_levs.size());
851 for(std::size_t i=1;i<sz;i++)
853 const MEDCouplingGridCollection *fine(_levs[i]);
855 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
856 _neighbors[i]=fine->findNeighbors(_ghost_lev);
859 for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
861 MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
862 std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
863 std::size_t fullLev(i+neighs2.size());
865 throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
867 for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
868 _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
874 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
876 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
878 const MEDCouplingGridCollection *elt(*it);
882 if(elt->presenceOf(m,tmp))
884 return elt->getFieldsAt(tmp);
888 throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");