1 // Copyright (C) 2007-2020 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 (CEA/DEN)
21 #include "MEDCouplingGaussLocalization.hxx"
22 #include "InterpKernelGaussCoords.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingUMesh.hxx"
25 #include "CellModel.hxx"
33 using namespace MEDCoupling;
35 MEDCouplingGaussLocalization::MEDCouplingGaussLocalization(INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
36 const std::vector<double>& gsCoo, const std::vector<double>& w)
37 :_type(type),_ref_coord(refCoo),_gauss_coord(gsCoo),_weight(w)
39 // Will potentially throw (and then release memory for above objects _ref_coord etc ...)
40 checkConsistencyLight();
43 MEDCouplingGaussLocalization::MEDCouplingGaussLocalization(INTERP_KERNEL::NormalizedCellType typ)
46 // Will potentially throw
47 INTERP_KERNEL::CellModel::GetCellModel(_type);
50 void MEDCouplingGaussLocalization::setType(INTERP_KERNEL::NormalizedCellType typ)
52 INTERP_KERNEL::CellModel::GetCellModel(typ);//throws if not found. This is a check
56 void MEDCouplingGaussLocalization::checkConsistencyLight() const
58 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(_type);
59 int nbNodes=cm.getNumberOfNodes();
60 int dim=cm.getDimension();
63 if(ToIdType(_ref_coord.size())!=nbNodes*dim)
65 std::ostringstream oss; oss << "Invalid size of refCoo : expecting to be : " << nbNodes << " (nbNodePerCell) * " << dim << " (dim) !";
66 throw INTERP_KERNEL::Exception(oss.str().c_str());
69 if(_gauss_coord.size()!=dim*_weight.size())
71 std::ostringstream oss; oss << "Invalid gsCoo size and weight size : gsCoo.size() must be equal to _weight.size() * " << dim << " (dim) !";
72 throw INTERP_KERNEL::Exception(oss.str().c_str());
76 int MEDCouplingGaussLocalization::getDimension() const
80 return (int)_gauss_coord.size()/(int)_weight.size();
83 int MEDCouplingGaussLocalization::getNumberOfPtsInRefCell() const
85 int dim=getDimension();
88 return (int)_ref_coord.size()/dim;
91 std::string MEDCouplingGaussLocalization::getStringRepr() const
93 std::ostringstream oss;
94 oss << "CellType : " << INTERP_KERNEL::CellModel::GetCellModel(_type).getRepr() << std::endl;
95 oss << "Ref coords : "; std::copy(_ref_coord.begin(),_ref_coord.end(),std::ostream_iterator<double>(oss,", ")); oss << std::endl;
96 oss << "Localization coords : "; std::copy(_gauss_coord.begin(),_gauss_coord.end(),std::ostream_iterator<double>(oss,", ")); oss << std::endl;
97 oss << "Weight : "; std::copy(_weight.begin(),_weight.end(),std::ostream_iterator<double>(oss,", ")); oss << std::endl;
101 std::size_t MEDCouplingGaussLocalization::getMemorySize() const
104 ret+=_ref_coord.capacity()*sizeof(double);
105 ret+=_gauss_coord.capacity()*sizeof(double);
106 ret+=_weight.capacity()*sizeof(double);
110 bool MEDCouplingGaussLocalization::isEqual(const MEDCouplingGaussLocalization& other, double eps) const
112 if(_type!=other._type)
114 if(!AreAlmostEqual(_ref_coord,other._ref_coord,eps))
116 if(!AreAlmostEqual(_gauss_coord,other._gauss_coord,eps))
118 if(!AreAlmostEqual(_weight,other._weight,eps))
123 double MEDCouplingGaussLocalization::getRefCoord(int ptIdInCell, int comp) const
125 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(_type);
126 int nbNodes=cm.getNumberOfNodes();
127 int dim=cm.getDimension();
128 if(ptIdInCell<0 || ptIdInCell>=nbNodes)
129 throw INTERP_KERNEL::Exception("ptIdInCell specified is invalid : must be in [0;nbNodesPerCell) !");
130 if(comp<0 || comp>=dim)
131 throw INTERP_KERNEL::Exception("comp specified is invalid : must be in [0:dimOfCell) !");
132 return _ref_coord[ptIdInCell*dim+comp];
135 double MEDCouplingGaussLocalization::getGaussCoord(int gaussPtIdInCell, int comp) const
137 int dim=checkCoherencyOfRequest(gaussPtIdInCell,comp);
138 return _gauss_coord[gaussPtIdInCell*dim+comp];
141 double MEDCouplingGaussLocalization::getWeight(int gaussPtIdInCell, double newVal) const
143 checkCoherencyOfRequest(gaussPtIdInCell,0);
144 return _weight[gaussPtIdInCell];
148 * Completely useless method for end user. Only for CORBA MPI serialization/unserialization.
149 * push at the end of tinyInfo its basic serialization info. The size of pushed data is always the same.
150 * @param tinyInfo inout parameter.
152 void MEDCouplingGaussLocalization::pushTinySerializationIntInfo(std::vector<mcIdType>& tinyInfo) const
154 tinyInfo.push_back(ToIdType(_type));
155 tinyInfo.push_back(getNumberOfPtsInRefCell());
156 tinyInfo.push_back(getNumberOfGaussPt());
160 * Completely useless method for end user. Only for CORBA MPI serialization/unserialization.
161 * push at the end of tinyInfo its basic serialization info. The size of pushed data is \b NOT always the same contrary to pushTinySerializationIntInfo.
162 * @param tinyInfo inout parameter.
164 void MEDCouplingGaussLocalization::pushTinySerializationDblInfo(std::vector<double>& tinyInfo) const
166 tinyInfo.insert(tinyInfo.end(),_ref_coord.begin(),_ref_coord.end());
167 tinyInfo.insert(tinyInfo.end(),_gauss_coord.begin(),_gauss_coord.end());
168 tinyInfo.insert(tinyInfo.end(),_weight.begin(),_weight.end());
172 * This method operates the exact inverse operation than MEDCouplingGaussLocalization::pushTinySerializationDblInfo method. This is one of the last step of unserialization process.
173 * This method should be called on an object resized by buildNewInstanceFromTinyInfo static method.
174 * This method takes in argument a pointer 'vals' that point to the begin of double data pushed remotely by pushTinySerializationDblInfo method.
175 * This method returns the pointer 'vals' with an offset of size what it has been read in this method.
177 const double *MEDCouplingGaussLocalization::fillWithValues(const double *vals)
179 const double *work=vals;
180 std::copy(work,work+_ref_coord.size(),_ref_coord.begin());
181 work+=_ref_coord.size();
182 std::copy(work,work+_gauss_coord.size(),_gauss_coord.begin());
183 work+=_gauss_coord.size();
184 std::copy(work,work+_weight.size(),_weight.begin());
185 work+=_weight.size();
190 * Given points in \a ptsInRefCoo in the reference coordinates of \a this (in _ref_coord attribute)
191 * this method computes their coordinates in real world for each cells in \a mesh.
192 * So the returned array will contain nbCells* \a ptsInRefCoo->getNumberOfTuples() tuples and the number of component
193 * will be equal to the dimension of \a this.
195 * This method ignores Gauss points in \a this and only those in \a ptsInRefCoo are considered here.
197 MCAuto<DataArrayDouble> MEDCouplingGaussLocalization::localizePtsInRefCooForEachCell(const DataArrayDouble *ptsInRefCoo, const MEDCouplingUMesh *mesh) const
199 if(!ptsInRefCoo || !mesh)
200 throw INTERP_KERNEL::Exception("MEDCouplingGaussLocalization::localizePtsInRefCooForEachCell : null pointer !");
201 ptsInRefCoo->checkAllocated();
202 mesh->checkConsistencyLight();
204 mcIdType nbCells=mesh->getNumberOfCells();
205 const double *coords(mesh->getCoords()->begin());
206 const mcIdType *connI(mesh->getNodalConnectivityIndex()->begin()),*conn(mesh->getNodalConnectivity()->begin());
208 mcIdType nbPts(ptsInRefCoo->getNumberOfTuples());
209 INTERP_KERNEL::NormalizedCellType typ(getType());
210 int dim(INTERP_KERNEL::CellModel::GetCellModel(typ).getDimension()),outDim(mesh->getSpaceDimension());
211 MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
212 ret->alloc(nbPts*nbCells,outDim);
213 double *retPtr(ret->getPointer());
214 if(dim!=ToIdType(ptsInRefCoo->getNumberOfComponents()))
215 throw INTERP_KERNEL::Exception("MEDCouplingGaussLocalization::localizePtsInRefCooForEachCell : number of components of input coo is not equal to dim of element !");
216 INTERP_KERNEL::GaussCoords calculator;
217 calculator.addGaussInfo(typ,dim, ptsInRefCoo->begin(),nbPts,&_ref_coord[0],getNumberOfPtsInRefCell());
219 for(mcIdType i=0;i<nbCells;i++,retPtr+=nbPts*outDim)
220 calculator.calculateCoords(getType(),coords,outDim,conn+connI[i]+1,retPtr);
225 * This method returns an unstructured mesh that represents the reference cell.
227 MCAuto<MEDCouplingUMesh> MEDCouplingGaussLocalization::buildRefCell() const
229 MCAuto<DataArrayDouble> coo(DataArrayDouble::New());
230 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(getType()));
231 if(getDimension()!=ToIdType(cm.getDimension()))
232 throw INTERP_KERNEL::Exception("BuildRefCell : dimension mistmatch !");
233 coo->alloc(cm.getNumberOfNodes(),getDimension());
234 std::copy(_ref_coord.begin(),_ref_coord.end(),coo->getPointer());
235 MCAuto<MEDCoupling1SGTUMesh> ret(MEDCoupling1SGTUMesh::New("",getType()));
237 MCAuto<DataArrayIdType> conn(DataArrayIdType::New());
238 conn->alloc(cm.getNumberOfNodes(),1);
240 ret->setNodalConnectivity(conn);
241 return MCAuto<MEDCouplingUMesh>(ret->buildUnstructured());
245 * This method sets the comp_th component of ptIdInCell_th point coordinate of reference element of type this->_type.
246 * @throw if not 0<=ptIdInCell<nbOfNodePerCell or if not 0<=comp<dim
248 void MEDCouplingGaussLocalization::setRefCoord(int ptIdInCell, int comp, double newVal)
250 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(_type);
251 int nbNodes=cm.getNumberOfNodes();
252 int dim=cm.getDimension();
253 if(ptIdInCell<0 || ptIdInCell>=nbNodes)
254 throw INTERP_KERNEL::Exception("ptIdInCell specified is invalid : must be in [0;nbNodesPerCell) !");
255 if(comp<0 || comp>=dim)
256 throw INTERP_KERNEL::Exception("comp specified is invalid : must be in [0:dimOfCell) !");
257 _ref_coord[ptIdInCell*dim+comp]=newVal;
260 void MEDCouplingGaussLocalization::setGaussCoord(int gaussPtIdInCell, int comp, double newVal)
262 int dim=checkCoherencyOfRequest(gaussPtIdInCell,comp);
263 _gauss_coord[gaussPtIdInCell*dim+comp]=newVal;
266 void MEDCouplingGaussLocalization::setWeight(int gaussPtIdInCell, double newVal)
268 checkCoherencyOfRequest(gaussPtIdInCell,0);
269 _weight[gaussPtIdInCell]=newVal;
272 void MEDCouplingGaussLocalization::setRefCoords(const std::vector<double>& refCoo)
277 void MEDCouplingGaussLocalization::setGaussCoords(const std::vector<double>& gsCoo)
282 void MEDCouplingGaussLocalization::setWeights(const std::vector<double>& w)
288 * The format of 'tinyData' parameter is the same than pushed in method MEDCouplingGaussLocalization::pushTinySerializationIntInfo.
290 MEDCouplingGaussLocalization MEDCouplingGaussLocalization::BuildNewInstanceFromTinyInfo(mcIdType dim, const std::vector<mcIdType>& tinyData)
292 std::vector<double> v1(dim*tinyData[1]),v2(dim*tinyData[2]),v3(tinyData[2]);
293 return MEDCouplingGaussLocalization((INTERP_KERNEL::NormalizedCellType)tinyData[0],v1,v2,v3);
296 int MEDCouplingGaussLocalization::checkCoherencyOfRequest(mcIdType gaussPtIdInCell, int comp) const
298 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(_type);
299 int dim=cm.getDimension();
300 mcIdType nbGsPts=getNumberOfGaussPt();
301 if(gaussPtIdInCell<0 || gaussPtIdInCell>=nbGsPts)
302 throw INTERP_KERNEL::Exception("gaussPtIdInCell specified is invalid : must be in [0:nbGsPts) !");
303 if(comp<0 || comp>=dim)
304 throw INTERP_KERNEL::Exception("comp specified is invalid : must be in [0:dimOfCell) !");
308 bool MEDCouplingGaussLocalization::AreAlmostEqual(const std::vector<double>& v1, const std::vector<double>& v2, double eps)
310 std::size_t sz=v1.size();
313 std::vector<double> tmp(sz);
314 std::transform(v1.begin(),v1.end(),v2.begin(),tmp.begin(),std::minus<double>());
315 std::transform(tmp.begin(),tmp.end(),tmp.begin(),[](double c){return fabs(c);});
316 return *std::max_element(tmp.begin(),tmp.end())<eps;