/*! \file axis_algorithm_interpolate.cpp \author Ha NGUYEN \since 23 June 2015 \date 02 Jul 2015 \brief Algorithm for interpolation on an axis. */ #include "axis_algorithm_interpolate_coordinate.hpp" #include "axis.hpp" #include "interpolate_axis.hpp" #include #include #include "context.hpp" #include "context_client.hpp" #include "utils.hpp" #include "grid.hpp" #include "grid_transformation_factory_impl.hpp" #include "distribution_client.hpp" #include "transform_filter.hpp" #include "timer.hpp" namespace xios { shared_ptr CAxisAlgorithmInterpolateCoordinate::create(bool isSource, CGrid* gridDst, CGrid* gridSrc, CTransformation* transformation, int elementPositionInGrid, std::map& elementPositionInGridSrc2ScalarPosition, std::map& elementPositionInGridSrc2AxisPosition, std::map& elementPositionInGridSrc2DomainPosition, std::map& elementPositionInGridDst2ScalarPosition, std::map& elementPositionInGridDst2AxisPosition, std::map& elementPositionInGridDst2DomainPosition) TRY { std::vector axisListDestP = gridDst->getAxis(); std::vector axisListSrcP = gridSrc->getAxis(); CInterpolateAxis* interpolateAxis = dynamic_cast (transformation); int axisDstIndex = elementPositionInGridDst2AxisPosition[elementPositionInGrid]; int axisSrcIndex = elementPositionInGridSrc2AxisPosition[elementPositionInGrid]; return make_shared(isSource, axisListDestP[axisDstIndex], axisListSrcP[axisSrcIndex], interpolateAxis); } CATCH bool CAxisAlgorithmInterpolateCoordinate::dummyRegistered_ = CAxisAlgorithmInterpolateCoordinate::registerTrans(); bool CAxisAlgorithmInterpolateCoordinate::registerTrans() TRY { return CGridTransformationFactory::registerTransformation(TRANS_INTERPOLATE_AXIS, create); } CATCH vector CAxisAlgorithmInterpolateCoordinate::getAuxFieldId(void) { if (hasCoordinateSrc_ && hasCoordinateDest_) return {coordinateSrc_,coordinateDest_} ; else if (hasCoordinateSrc_) return {coordinateSrc_} ; else if (hasCoordinateDest_) return {coordinateDest_} ; else return vector() ; } bool CAxisAlgorithmInterpolateCoordinate::transformAuxField(int pos) { if (pos==0) { if (hasCoordinateSrc_) return true ; else if(hasCoordinateDest_) return false ; } if (pos==1) return false ; MISSING_RETURN( "bool CAxisAlgorithmInterpolateCoordinate::transformAuxField(int pos)" ); return false; } CAxisAlgorithmInterpolateCoordinate::CAxisAlgorithmInterpolateCoordinate(bool isSource, CAxis* axisDestination, CAxis* axisSource, CInterpolateAxis* interpAxis) : CAlgorithmTransformationTransfer(isSource), axisSrc_(axisSource), axisDest_(axisDestination) TRY { interpAxis->checkValid(axisSource); axisDestination->checkAttributes() ; order_ = interpAxis->order.getValue(); if (!interpAxis->coordinate.isEmpty()) { coordinateSrc_ = interpAxis->coordinate.getValue(); hasCoordinate_=true ; hasCoordinateSrc_=true ; } if (!interpAxis->coordinate_src.isEmpty()) { coordinateSrc_ = interpAxis->coordinate_src.getValue(); hasCoordinate_=true ; hasCoordinateSrc_=true ; } if (!interpAxis->coordinate_dst.isEmpty()) { coordinateDest_ = interpAxis->coordinate_dst.getValue(); hasCoordinate_=true ; hasCoordinateDest_=true ; } ngloSrc_=axisSource->n_glo ; nDest_ = axisDest_-> getLocalView(CElementView::WORKFLOW)->getSize() ; if (!hasCoordinateDest_) { CArray coord ; auto destConnector = make_shared(axisDest_->getLocalView(CElementView::FULL), axisDest_->getLocalView(CElementView::WORKFLOW)) ; destConnector->computeConnector() ; destConnector->transfer(axisDest_->value, coord) ; destCoordinate_ = vector(coord.dataFirst(), coord.dataFirst()+nDest_) ; } CArray globalIndex(ngloSrc_) ; for(int i=0;i axisSourceGlo = make_shared(CContext::getCurrent()->getIntraCommRank(), ngloSrc_, globalIndex) ; axisSourceGlo->addFullView() ; this->computeAlgorithm(axisSource->getLocalView(CElementView::WORKFLOW), axisSourceGlo->getView(CElementView::FULL)) ; if (!hasCoordinateSrc_) { CArray coord ; CArray coordGlo ; auto srcConnector = make_shared(axisSrc_->getLocalView(CElementView::FULL), axisSrc_->getLocalView(CElementView::WORKFLOW)) ; srcConnector->computeConnector() ; srcConnector->transfer(axisSrc_->value, coord) ; // full view value -> workflow value transferTransformConnector_ -> transfer(coord, coordGlo) ; // workflow view -> full global view srcCoordinate_ = vector(coordGlo.dataFirst(), coordGlo.dataFirst()+ngloSrc_) ; } } CATCH CTransformFilter* CAxisAlgorithmInterpolateCoordinate::createTransformFilter(CGarbageCollector& gc, shared_ptr algo, bool detectMissingValues, double defaultValue) { if (hasCoordinateSrc_ && hasCoordinateDest_) return new CTransformFilter(gc, 3, algo, detectMissingValues, defaultValue) ; else return new CTransformFilter(gc, 2, algo, detectMissingValues, defaultValue) ; } void CAxisAlgorithmInterpolateCoordinate::apply(int dimBefore, int dimAfter, const CArray& dataIn, const vector>& auxDataIn, CArray& dataOut) { CArray dataInTmp; CArray auxDataInSrc ; transferTransformConnector_ -> transfer(dimBefore, dimAfter, dataIn, dataInTmp) ; if (hasCoordinateSrc_) transferTransformConnector_ -> transfer(dimBefore, dimAfter, auxDataIn[0], auxDataInSrc) ; dataOut.resize(dimBefore*dimAfter*nDest_) ; const double* pressureSrc ; const double* pressureDest ; if (hasCoordinateSrc_) pressureSrc = auxDataInSrc.dataFirst() ; if (hasCoordinateDest_ && hasCoordinateSrc_) pressureDest = auxDataIn[1].dataFirst() ; else if (hasCoordinateDest_ && !hasCoordinateSrc_ ) pressureDest = auxDataIn[0].dataFirst() ; const double* in = dataInTmp.dataFirst() ; double* out = dataOut.dataFirst() ; size_t sliceSrc = dimAfter*ngloSrc_ ; size_t sliceDest = dimAfter*nDest_ ; vector srcCoordinate(ngloSrc_) ; vector destCoordinate(nDest_) ; std::vector srcIndex(ngloSrc_); vector srcValue(ngloSrc_) ; vector destValue(nDest_) ; std::vector destIndex(nDest_); size_t nsrc, nDest ; for(size_t j=0, posJsrc=0, posJdest=0 ; j::quiet_NaN() ; } } else { nDest=0 ; for(size_t i=0, posIdest=posKdest ; i::quiet_NaN() ; } } } } void CAxisAlgorithmInterpolateCoordinate::computeInterp(int nsrc, vector& srcCoordinate, vector& srcValue, vector& srcIndex, int ndst, vector& dstCoordinate, vector& dstValue, vector& dstIndex) { double x,y ; double d ; iota(srcIndex.data(), srcIndex.data()+nsrc, 0); // sort array and retrive sorted index stable_sort(srcIndex.data(), srcIndex.data()+nsrc, [&srcCoordinate](size_t i1, size_t i2) {return srcCoordinate[i1] < srcCoordinate[i2];}); iota(dstIndex.data(), dstIndex.data()+ndst, 0); stable_sort(dstIndex.data(), dstIndex.data()+ndst, [&dstCoordinate](size_t i1, size_t i2) {return dstCoordinate[i1] < dstCoordinate[i2];}); if (order_==1 || nsrc<=2) { if (nsrc<=1) dstValue.assign(ndst,std::numeric_limits::quiet_NaN()); else { double x0,x1 ; double y0,y1 ; int lastj=0; for(int i=0; i < ndst;i++) { x=dstCoordinate[dstIndex[i]] ; if ( x<=srcCoordinate[srcIndex[0]]) lastj=0 ; else if (x>=srcCoordinate[srcIndex[nsrc-1]]) lastj=nsrc-2 ; else { for(int j=lastj; j= srcCoordinate[srcIndex[j]] && x=srcCoordinate[srcIndex[nsrc-1]]) lastj=nsrc-2 ; else { for(int j=lastj; j= srcCoordinate[srcIndex[j]] && x=nsrc-2) cj=nsrc-2 ; else { if ( (x-srcCoordinate[srcIndex[lastj-1]]) > (srcCoordinate[srcIndex[lastj+2]]-x) ) cj=lastj ; else cj=lastj+1 ; } x0=srcCoordinate[srcIndex[cj-1]] ; x1=srcCoordinate[srcIndex[cj]] ; x2=srcCoordinate[srcIndex[cj+1]] ; y0=srcValue[srcIndex[cj-1]] ; y1=srcValue[srcIndex[cj]] ; y2=srcValue[srcIndex[cj+1]] ; y=y0*(x-x1)*(x-x2)/((x0-x1)*(x0-x2)) + y1*(x-x0)*(x-x2)/((x1-x0)*(x1-x2)) + y2*(x-x0)*(x-x1)/((x2-x0)*(x2-x1)) ; dstValue[dstIndex[i]]=y ; } } } }