Ignore:
Timestamp:
09/15/15 17:30:55 (9 years ago)
Author:
mhnguyen
Message:

Implementing auto-generate rectilinear domain

+) Add a new special transformation to generate (complete) rectilinear domain

Test
+) On Curie
+) test_new_feature passed

File:
1 edited

Legend:

Unmodified
Added
Removed
  • XIOS/trunk/src/node/domain.cpp

    r679 r687  
    2020#include "zoom_domain.hpp" 
    2121#include "interpolate_from_file_domain.hpp" 
     22#include "generate_rectilinear_domain.hpp" 
    2223 
    2324#include <algorithm> 
     
    3435      , isClientAfterTransformationChecked(false), hasLonLat(false) 
    3536      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client() 
     37      , srcObject_(0) 
    3638   { /* Ne rien faire de plus */ } 
    3739 
     
    4345      , isClientAfterTransformationChecked(false), hasLonLat(false) 
    4446      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client() 
     47      , srcObject_(0) 
    4548   { /* Ne rien faire de plus */ } 
    4649 
     
    158161 
    159162   //---------------------------------------------------------------- 
     163 
     164   /*! 
     165     Redistribute RECTILINEAR domain with a number of local domains. 
     166   All attributes ni,nj,ibegin,jbegin (if defined) will be rewritten 
     167   The optional attributes lonvalue, latvalue will be added. Because this function only serves (for now) 
     168   for interpolation from unstructured domain to rectilinear one, range of latvalue is 0-360 and lonvalue is -90 - +90 
     169    \param [in] nbLocalDomain number of local domain on the domain destination 
     170   */ 
     171   void CDomain::redistribute(int nbLocalDomain) 
     172   { 
     173     if (type_attr::rectilinear == type) 
     174     { 
     175        CContext* context = CContext::getCurrent(); 
     176        CContextClient* client = context->client; 
     177        int rankClient = client->clientRank; 
     178        int rankOnDomain = rankClient%nbLocalDomain; 
     179 
     180        if (ni_glo.isEmpty() || ni_glo <= 0 ) 
     181        { 
     182           ERROR("CDomain::redistribute(int nbLocalDomain)", 
     183              << "[ Id = " << this->getId() << " ] " 
     184              << "The global domain is badly defined," 
     185              << " check the \'ni_glo\'  value !") 
     186        } 
     187 
     188        if (nj_glo.isEmpty() || nj_glo <= 0 ) 
     189        { 
     190           ERROR("CDomain::redistribute(int nbLocalDomain)", 
     191              << "[ Id = " << this->getId() << " ] " 
     192              << "The global domain is badly defined," 
     193              << " check the \'nj_glo\'  value !") 
     194        } 
     195 
     196        int globalDomainSize = ni_glo * nj_glo; 
     197        if (globalDomainSize <= nbLocalDomain) 
     198        { 
     199          for (int idx = 0; idx < nbLocalDomain; ++idx) 
     200          { 
     201            if (rankOnDomain < globalDomainSize) 
     202            { 
     203              int iIdx = rankOnDomain % ni_glo; 
     204              int jIdx = rankOnDomain / ni_glo; 
     205              ibegin.setValue(iIdx); jbegin.setValue(jIdx); 
     206              ni.setValue(1); nj.setValue(1); 
     207            } 
     208            else 
     209            { 
     210              ibegin.setValue(0); jbegin.setValue(0); 
     211              ni.setValue(0); nj.setValue(0); 
     212            } 
     213          } 
     214        } 
     215        else 
     216        { 
     217          // Compute (approximately) number of segment on x and y axis 
     218          float yOverXRatio = (nj_glo.getValue())/(ni_glo.getValue()); 
     219          int nbProcOnX, nbProcOnY, range; 
     220          nbProcOnX = std::ceil(std::sqrt(nbLocalDomain/yOverXRatio)); 
     221          nbProcOnY = std::ceil(((float)nbLocalDomain)/nbProcOnX); 
     222 
     223          // Simple distribution: Sweep from top to bottom, left to right 
     224          // Calculate local begin on x 
     225          std::vector<int> ibeginVec(nbProcOnX,0), jbeginVec(nbProcOnY,0); 
     226          std::vector<int> niVec(nbProcOnX), njVec(nbProcOnY); 
     227          for (int i = 1; i < nbProcOnX; ++i) 
     228          { 
     229            range = ni_glo / nbProcOnX; 
     230            if (i < (ni_glo%nbProcOnX)) ++range; 
     231            niVec[i-1] = range; 
     232            ibeginVec[i] = ibeginVec[i-1] + niVec[i-1]; 
     233          } 
     234          niVec[nbProcOnX-1] = ni_glo - ibeginVec[nbProcOnX-1]; 
     235 
     236          // Calculate local begin on y 
     237          for (int j = 1; j < nbProcOnY; ++j) 
     238          { 
     239            range = nj_glo / nbProcOnY; 
     240            if (j < (nj_glo%nbProcOnY)) ++range; 
     241            njVec[j-1] = range; 
     242            jbeginVec[j] = jbeginVec[j-1] + njVec[j-1]; 
     243          } 
     244          njVec[nbProcOnY-1] = nj_glo - jbeginVec[nbProcOnY-1]; 
     245 
     246          // Now assign value to ni, ibegin, nj, jbegin 
     247          int iIdx = rankOnDomain % nbProcOnX; 
     248          int jIdx = rankOnDomain / nbProcOnX; 
     249 
     250          if (rankOnDomain != (nbLocalDomain-1)) 
     251          { 
     252            ibegin.setValue(ibeginVec[iIdx]); 
     253            jbegin.setValue(jbeginVec[jIdx]); 
     254            nj.setValue(njVec[jIdx]); 
     255            ni.setValue(niVec[iIdx]); 
     256          } 
     257          else // just merge all the remaining rectangle into the last one 
     258          { 
     259            ibegin.setValue(ibeginVec[iIdx]); 
     260            jbegin.setValue(jbeginVec[jIdx]); 
     261            nj.setValue(njVec[jIdx]); 
     262            ni.setValue(ni_glo - ibeginVec[iIdx]); 
     263          } 
     264        } 
     265 
     266        // Now fill other attributes 
     267        fillInRectilinearLonLat(); 
     268     } 
     269   } 
     270 
     271   /*! 
     272     Fill in the values for lonvalue_1d and latvalue_1d of rectilinear domain 
     273     Range of longitude value from 0 - 360 
     274     Range of latitude value from -90 - +90 
     275   */ 
     276   void CDomain::fillInRectilinearLonLat() 
     277   { 
     278     if (!lonvalue_2d.isEmpty()) lonvalue_2d.free(); 
     279     if (!latvalue_2d.isEmpty()) latvalue_1d.free(); 
     280     lonvalue_1d.resize(ni); 
     281     latvalue_1d.resize(nj); 
     282     double lonStep = double(360/ni_glo.getValue()); 
     283     double latStep = double(180/nj_glo.getValue()); 
     284 
     285     // Assign lon value 
     286     for (int i = 0; i < ni; ++i) 
     287     { 
     288       lonvalue_1d(i) = static_cast<double>(ibegin + i) * lonStep; 
     289     } 
     290 
     291     for (int j = 0; j < nj; ++j) 
     292     { 
     293       latvalue_1d(j) = static_cast<double>(jbegin + j) * latStep - 90; 
     294     } 
     295   } 
    160296 
    161297   void CDomain::checkDomain(void) 
     
    702838       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty()) 
    703839       { 
    704          if (lonvalue_1d.numElements() != i_index.numElements()) 
     840         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements())) 
    705841           ERROR("CDomain::completeLonLatClient(void)", 
    706842                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] " 
     
    728864       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty()) 
    729865       { 
    730          if (latvalue_1d.numElements() != i_index.numElements()) 
     866         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements())) 
    731867           ERROR("CDomain::completeLonLatClient(void)", 
    732868                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] " 
     
    15801716  } 
    15811717 
     1718  void CDomain::solveSrcInheritance() 
     1719  { 
     1720    if (!domain_src.isEmpty()) 
     1721    { 
     1722       if (!CDomain::has(this->domain_src.getValue()))                                   \ 
     1723          ERROR("CDomain::solveSrcInheritance()",                                \ 
     1724             << "[ src_name = " << this->domain_src.getValue() << "]"                 \ 
     1725             << " invalid domain name !"); 
     1726 
     1727       srcObject_ = CDomain::get(this->domain_src.getValue()); 
     1728    } 
     1729  } 
     1730 
     1731  CDomain* CDomain::getDomainSrc() 
     1732  { 
     1733    return srcObject_; 
     1734  } 
     1735 
    15821736  /*! 
    15831737    Parse children nodes of a domain in xml file. 
     
    15951749      StdString interpFromFileDomainDefRoot("interpolate_from_file_domain_definition"); 
    15961750      StdString interpFromFile("interpolate_from_file_domain"); 
     1751      StdString generateRectilinearDefRoot("generate_rectilinear_domain_definition"); 
     1752      StdString generateRectilinear("generate_rectilinear_domain"); 
    15971753      do 
    15981754      { 
     
    16081764          transformationMap_.push_back(std::make_pair(TRANS_INTERPOLATE_DOMAIN_FROM_FILE,tmp)); 
    16091765        } 
     1766        else if (node.getElementName() == generateRectilinear) 
     1767        { 
     1768          CGenerateRectilinearDomain* tmp = (CGenerateRectilinearDomainGroup::get(generateRectilinearDefRoot))->createChild(); 
     1769          tmp->parse(node); 
     1770          transformationMap_.push_back(std::make_pair(TRANS_GENERATE_RECTILINEAR_DOMAIN,tmp)); 
     1771        } 
    16101772      } while (node.goToNextElement()) ; 
    16111773      node.goToParentElement(); 
Note: See TracChangeset for help on using the changeset viewer.