+/*!
+ * \a p1 is expected to be more refined than \a p2. \a p1 and \a p2 have to share a common ancestor. Compared to UpdateNeighborsOfOneWithTwoExt here \a p1 and \a p2 are \b not at the same level !
+ */
+void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2, bool isConservative)
+{
+ std::vector< std::pair<mcIdType,mcIdType> > p1pp,p2pp;
+ std::vector<mcIdType> factors;
+ ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,p1,p2,p1pp,p2pp,factors);
+ //
+ std::vector<mcIdType> dimsP2NotRefined(p2->computeCellGridSt());
+ std::vector<mcIdType> dimsP2Refined(dimsP2NotRefined);
+ std::transform(dimsP2NotRefined.begin(),dimsP2NotRefined.end(),factors.begin(),dimsP2Refined.begin(),std::multiplies<mcIdType>());
+ std::vector< std::pair<mcIdType,mcIdType> > p2RefinedAbs(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsP2NotRefined));
+ std::vector<mcIdType> dimsP2RefinedGhost(dimsP2Refined.size());
+ std::transform(dimsP2Refined.begin(),dimsP2Refined.end(),dimsP2RefinedGhost.begin(),std::bind(std::plus<mcIdType>(),std::placeholders::_1,2*ghostLev));
+ MCAuto<DataArrayDouble> fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents());
+ MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev);
+ if(isConservative)
+ {
+ mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(factors));
+ std::transform(fineP2->begin(),fineP2->end(),fineP2->getPointer(),std::bind(std::multiplies<double>(),std::placeholders::_1,1./((double)fact)));
+ }
+ //
+ UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1pp,p2pp,dataOnP1,fineP2);
+}
+
+/*!
+ * \a p1 is expected to be more refined than \a p2. \a p1 and \a p2 have to share a common ancestor. Compared to UpdateNeighborsOfOneWithTwoExt here \a p1 and \a p2 are \b not at the same level !
+ * This method has 3 outputs. 2 two first are the resp the position of \a p1 and \a p2 relative to \a p1. And \a factToApplyOn2 is the coeff of refinement to be applied on \a p2 to be virtually
+ * on the same level as \a p1.
+ */
+void MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<mcIdType,mcIdType> >& p1Zone, std::vector< std::pair<mcIdType,mcIdType> >& p2Zone, std::vector<mcIdType>& factToApplyOn2)
+{
+ std::vector<const MEDCouplingCartesianAMRMeshGen *> ancestorsOfThis;
+ const MEDCouplingCartesianAMRMeshGen *work(p1->getMesh()),*work2(0);
+ ancestorsOfThis.push_back(work);
+ while(work)
+ {
+ work=work->getFather();
+ if(work)
+ ancestorsOfThis.push_back(work);
+ }
+ //
+ work=p2->getMesh();
+ bool found(false);
+ std::size_t levThis(0),levOther(0);
+ while(work && !found)
+ {
+ work2=work;
+ work=work->getFather();
+ if(work)
+ {
+ levOther++;
+ std::vector<const MEDCouplingCartesianAMRMeshGen *>::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work));
+ if(it!=ancestorsOfThis.end())
+ {
+ levThis=std::distance(ancestorsOfThis.begin(),it);
+ found=true;
+ }
+ }
+ }
+ if(!found)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : no common ancestor found !");
+ if(levThis<=levOther)
+ throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : this method is not called correctly !");
+ //
+ const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]);
+ mcIdType idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2));
+ const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther));
+ std::vector<mcIdType> offset(ComputeOffsetFromTwoToOne(comAncestor,ToIdType(levOther),thisp,otherp));
+ p1Zone=thisp->getBLTRRange(); p2Zone=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset);
+ factToApplyOn2.resize(p1Zone.size()); std::fill(factToApplyOn2.begin(),factToApplyOn2.end(),1);
+ //
+ std::size_t nbOfTurn(levThis-levOther);
+ for(std::size_t i=0;i<nbOfTurn;i++)
+ {
+ std::vector< std::pair<mcIdType,mcIdType> > tmp0;
+ MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1Zone,p2Zone,tmp0,false);
+ p2Zone=tmp0;
+ const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]);
+ ApplyFactorsOnCompactFrmt(p2Zone,curAncestor->getFactors());
+ curAncestor=ancestorsOfThis[levThis-1-i];
+ const std::vector<mcIdType>& factors(curAncestor->getFactors());
+ std::transform(factToApplyOn2.begin(),factToApplyOn2.end(),factors.begin(),factToApplyOn2.begin(),std::multiplies<mcIdType>());
+ mcIdType tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i]));
+ p1Zone=curAncestor->getPatch(tmpId)->getBLTRRange();
+ }
+}
+