Changeset 978


Ignore:
Timestamp:
10/21/16 13:40:33 (5 years ago)
Author:
mhnguyen
Message:

Correcting various bugs relating to transformation

+) Fix the order of transformation selection
+) Correct domain transformation selection
+) Reorganize test_remap

Test
+) On Curie
+) All tests pass

Location:
XIOS/trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • XIOS/trunk/inputs/REMAP/iodef.xml

    r873 r978  
    55   <calendar type="Gregorian" start_date="2012-03-01 15:00:00" time_origin="2012-02-28 15:00:00 + 1d" /> 
    66   <field_definition level="1" > 
    7      <field id="src_field" operation="instant" domain_ref="src_domain_clone"/> 
    8      <field id="src_field_3D" operation="instant" domain_ref="src_domain" axis_ref="src_axis"/> 
    9      <field id="src_field_3D_interp" operation="instant" field_ref="src_field_3D" axis_ref="dst_axis"/> 
    10      <field id="src_field_3D_pression" operation="instant" grid_ref="src_grid_3D"/> 
    11      <field id="src_field_clone" operation="instant" field_ref="src_field" domain_ref="src_domain_clone"/> 
    12      <field id="dst_field" operation="instant" field_ref="src_field" domain_ref="dst_domain"/> 
    13      <field id="dst_field_regular_pole" operation="instant" field_ref="src_field" domain_ref="dst_domain_regular_pole"/> 
    14 <!--     <field id="tmp_field" operation="instant" domain_ref="src_domain_regular_tmp"/>--> 
    15 <!--     <field id="tmp_field_clone" field_ref="tmp_field"/>--> 
    16 <!--     <field id="tmp_field_1" operation="instant" grid_ref="src_grid_curvilinear" />--> 
    17 <!--     <field id="tmp_field_2" operation="instant" grid_ref="src_grid_unstructured" />--> 
    18 <!--     <field id="dst_field_regular" operation="instant" field_ref="tmp_field_2" grid_ref="dst_grid_regular" read_access="true"/>--> 
    19 <!--     <field id="dst_field_3D" operation="instant" field_ref="src_field_3D" grid_ref="dst_grid_3D"/>--> 
    20 <!--     <field id="dst_field_regular_pole_1" operation="instant" field_ref="tmp_field" domain_ref="dst_domain_regular_pole"/>--> 
    21 <!--     <field id="dst_field_regular_pole_2" operation="instant" field_ref="tmp_field_clone" domain_ref="dst_domain_regular_pole"/>--> 
     7    <field_group id="fields_src" operation="instant"> 
     8       <field id="src_field_2D" domain_ref="src_domain"/> 
     9       <field id="src_field_2D_clone" domain_ref="src_domain_clone"/> 
     10       <field id="src_field_3D" domain_ref="src_domain" axis_ref="src_axis"/>        
     11       <field id="src_field_3D_pression" grid_ref="src_grid_3D"/> 
     12       <field id="src_field_4D" grid_ref="grid_4D"/>        
     13    </field_group> 
     14    <field_group  id="fields_dst"> 
     15      <field id="dst_field_2D" field_ref="src_field_2D" domain_ref="dst_domain"/> 
     16      <field id="dst_field_2D_regular_pole" field_ref="src_field_2D" domain_ref="dst_domain_regular_pole"/> 
     17      <field id="dst_field_3D" field_ref="src_field_3D" grid_ref="dst_grid_3D"/> 
     18      <field id="dst_field_3D_interp" field_ref="src_field_3D" axis_ref="dst_axis"/>        
     19      <field id="dst_field_4D_extract" field_ref="src_field_4D" grid_ref="grid_4D_extract"/>       
     20      <field id="dst_field_2D_clone" field_ref="src_field_2D_clone" domain_ref="dst_domain"/> 
     21    </field_group> 
     22    <field_group id="read_fields" operation="instant"> 
     23<!--       <field id="tmp_field_0" domain_ref="src_domain_regular_read"/> 
     24      <field id="tmp_field_clone" field_ref="tmp_field_0"/> 
     25      <field id="tmp_field_1" grid_ref="src_grid_curvilinear_read" /> 
     26      <field id="tmp_field_2" grid_ref="src_grid_unstructured_read" /> 
     27      <field id="dst_field_regular" field_ref="tmp_field_2" grid_ref="dst_grid_regular"/>       
     28      <field id="dst_field_regular_pole_0" field_ref="tmp_field_0" domain_ref="dst_domain_regular_pole"/> 
     29      <field id="dst_field_regular_pole_1" field_ref="tmp_field_clone" domain_ref="dst_domain_regular_pole"/> --> 
     30    </field_group>  
    2231   </field_definition> 
    2332 
    2433   <file_definition type="one_file" par_access="collective" output_freq="1ts" output_level="10" enabled=".TRUE."> 
    25      <file id="output" name="output"> 
    26         <field field_ref="src_field" name="field" /> 
    27      </file> 
    28      <file id="output_2D" name="output_2D"> 
    29         <field field_ref="src_field" name="field"  domain_ref="dst_domain_regular_pole" default_value="10.e+5"/> 
    30      </file> 
    31     <file id="output_3D_pression" name="output_3D_pression"> 
    32         <field field_ref="src_field_3D_pression" name="field" /> 
    33      </file> 
    34      <file id="output_clone" name="output_clone"> 
    35 <!--        <field field_ref="src_field_clone" name="field" />--> 
    36      </file> 
    37      <file id="output_dst" name="output_dst" type="one_file"> 
    38 <!--        <field field_ref="dst_field" name="field" />--> 
    39      </file> 
    40      <file id="out_dst_regular_pole" name="out_dst_regular_pole" type="one_file"> 
    41 <!--        <field field_ref="dst_field_regular_pole" name="field" />--> 
    42      </file> 
    43      <file id="regular_field_3D" name="regular_field_3D" type="one_file"> 
    44         <field field_ref="src_field_3D_interp" name="field" domain_ref="dst_domain_regular_pole" /> 
    45      </file> 
    46     <file id="regular_field_3D_interp" name="regular_field_3D_interp" type="one_file"> 
    47         <field field_ref="src_field_3D_interp" name="field" /> 
    48      </file> 
    49 <!--     <file id="out_dst_regular_pole_1" name="out_dst_regular_pole_1" type="one_file">--> 
    50 <!--        <field field_ref="dst_field_regular_pole_1" name="field" />--> 
    51 <!--     </file>--> 
    52 <!--     <file id="out_dst_regular_pole_2" name="out_dst_regular_pole_2" type="one_file">--> 
    53 <!--        <field field_ref="dst_field_regular_pole_2" name="field" />--> 
    54 <!--     </file>--> 
    55 <!--     <file id="output_dst_regular" name="output_dst_regular" type="one_file">--> 
    56 <!--        <field field_ref="dst_field_regular" name="field" />--> 
    57 <!--     </file>--> 
    58 <!--     <file id="output_dst_curvilinear" name="output_dst_curvilinear" type="one_file">--> 
    59 <!--        <field field_ref="tmp_field_1" operation="instant"/>--> 
    60 <!--     </file>--> 
    61 <!--     <file id="output_dst_unstructured" name="output_dst_unstructured" type="one_file">--> 
    62 <!--        <field field_ref="tmp_field_2" operation="instant"/>--> 
    63 <!--     </file>--> 
    64 <!--     <file id="output_src_regular_tmp" name="output_src_regular_tmp" mode="read" type="one_file">--> 
    65 <!--        <field id="src_field_regular_tmp" name="field" domain_ref="src_domain_regular_tmp" operation="instant"/>--> 
    66 <!--     </file>--> 
    67 <!--     <file id="output_src_curvilinear" name="output_src_curvilinear" mode="read" type="one_file">--> 
    68 <!--        <field id="src_field_curvilinear" name="field_A" grid_ref="src_grid_curvilinear" operation="instant"/>--> 
    69 <!--     </file>--> 
    70 <!--     <file id="output_unstructured" name="output_unstructured" mode="read" type="one_file">--> 
    71 <!--        <field id="field_src_unstructred" name="field" grid_ref="src_grid_unstructured" operation="instant"/>--> 
    72 <!--     </file>--> 
     34      <file_group id="write_files" > 
     35        <file id="output_2D" name="output_2D" > 
     36          <field field_ref="src_field_2D" name="field_src" /> 
     37          <field field_ref="src_field_2D" name="field_dst_regular_0"  domain_ref="dst_domain_regular_pole" default_value="10.e+5"/> 
     38          <field field_ref="dst_field_2D" name="field_dst_regular_1" /> 
     39          <field field_ref="dst_field_2D_regular_pole" name="field_dst_regular_2" /> 
     40          <field field_ref="dst_field_2D_clone" name="field_dst_regular_3" /> 
     41        </file>  
     42       <file id="output_3D" name="output_3D" > 
     43          <field field_ref="src_field_3D" name="field_src" /> 
     44          <field field_ref="src_field_3D_pression" name="field" /> 
     45          <field field_ref="dst_field_3D_interp" name="field_dst_interp_domain" /> 
     46          <field field_ref="dst_field_3D_interp" name="field_dst_interp_domain_axis" domain_ref="dst_domain_regular_pole"/>   
     47       </file> 
     48       <file id="output_4D" name="output_4D" > 
     49          <field field_ref="src_field_4D" name="field_4D" /> 
     50          <field field_ref="dst_field_4D_extract" name="field_4D_extract" /> 
     51        </file> 
     52     </file_group> 
     53     <file_group id="read_files" > 
     54<!--        <file id="output_src_regular" name="output_src_regular" mode="read" > 
     55          <field id="src_field_regular" name="field" grid_ref="src_grid_regular_read" operation="instant"/> 
     56       </file> 
     57       <file id="output_src_curvilinear" name="output_src_curvilinear" mode="read" > 
     58          <field id="src_field_curvilinear" name="field_A" grid_ref="src_grid_curvilinear_read" operation="instant"/> 
     59       </file> 
     60       <file id="output_src_unstructured" name="output_src_unstructured" mode="read" > 
     61          <field id="src_field_unstructured" name="field" grid_ref="src_grid_unstructured_read" operation="instant"/> 
     62       </file> --> 
     63      </file_group> 
     64     <file_group id="read_then_write_files" enabled=".FALSE."> 
     65<!--        <file id="output_regular_pole" name="output_dst_regular" > 
     66          <field field_ref="dst_field_regular" name="field_regular" /> 
     67          <field field_ref="dst_field_regular_pole_0" name="field_regular_pole_0" /> 
     68          <field field_ref="dst_field_regular_pole_1" name="field_regular_pole_1" /> 
     69       </file> 
     70       <file id="output_dst_curvilinear" name="output_dst_curvilinear"> 
     71          <field field_ref="tmp_field_1" operation="instant"/> 
     72       </file> 
     73       <file id="output_dst_unstructured" name="output_dst_unstructured" > 
     74          <field field_ref="tmp_field_2" operation="instant"/> 
     75       </file> --> 
     76     </file_group> 
    7377   </file_definition> 
    7478 
    75  
    7679   <axis_definition> 
     80    <axis_group id="axis_src"> 
     81      <axis id="src_axis" positive="down" /> 
     82      <axis id="nq" positive="down" /> 
     83      <axis id="src_axis_curvilinear_read" /> 
     84    </axis_group> 
     85    <axis_group id="axis_dst"> 
    7786     <axis id="dst_axis" positive="down" n_glo="2" value="(0,1)[120 220]"> 
    78         <interpolate_axis type="polynomial" order="1" coordinate="src_field_3D_pression"/> 
    79 <!--        <interpolate_axis type="polynomial" order="1" />--> 
     87       <interpolate_axis type="polynomial" order="1" coordinate="src_field_3D_pression"/> 
     88       <!-- <interpolate_axis type="polynomial" order="1" />         --> 
    8089     </axis> 
    81      <axis id="src_axis" positive="down" /> 
    82      <axis id="src_axis_curvilinear" /> 
     90    </axis_group> 
    8391   </axis_definition> 
    8492 
    8593   <domain_definition> 
    86      <domain id="src_domain" /> 
    87      <domain id="src_domain_clone"/> 
     94    <domain_group id="read_domains"> 
     95      <domain id="src_domain_regular_read" type="rectilinear"> 
     96        <generate_rectilinear_domain /> 
     97      </domain> 
     98      <domain id="src_domain_curvilinear_read" type="curvilinear"> 
     99        <generate_rectilinear_domain /> 
     100      </domain> 
     101      <domain id="src_domain_unstructured_read" type="unstructured"> 
     102      </domain> 
     103    </domain_group> 
     104    <domain_group id="domain_src"> 
     105      <domain id="src_domain" /> 
     106      <domain id="src_domain_clone"/> 
     107    </domain_group> 
     108 
     109    <domain_group id="domain_dst"> 
    88110     <domain id="dst_domain"> 
    89111       <interpolate_domain/> 
     
    91113     <domain id="dst_domain_regular_pole" ni_glo="90" nj_glo="45" type="rectilinear"> 
    92114       <generate_rectilinear_domain id="domain_regular_pole"/> 
    93        <interpolate_domain/> 
     115       <interpolate_domain/>        
     116       <zoom_domain ibegin="0" ni="45" jbegin="0" nj="45" /> 
    94117     </domain> 
    95118     <domain id="dst_domain_regular" ni_glo="90" nj_glo="45" type="rectilinear"> 
    96119       <generate_rectilinear_domain /> 
    97        <interpolate_domain/> 
     120       <interpolate_domain/>        
    98121     </domain> 
    99      <domain id="src_domain_regular_tmp" type="rectilinear"> 
    100        <generate_rectilinear_domain /> 
    101      </domain> 
    102      <domain id="src_domain_curvilinear" type="curvilinear"> 
    103        <generate_rectilinear_domain /> 
    104      </domain> 
    105      <domain id="src_domain_unstructured" type="unstructured"> 
    106        <generate_rectilinear_domain /> 
    107      </domain> 
     122    </domain_group> 
    108123   </domain_definition> 
    109124 
    110125  <grid_definition> 
    111     <grid id="src_grid_curvilinear"> 
    112       <domain domain_ref="src_domain_curvilinear"/> 
    113       <axis axis_ref="src_axis_curvilinear" /> 
    114     </grid> 
    115     <grid id="src_grid_unstructured"> 
    116       <domain domain_ref="src_domain_unstructured"/> 
    117     </grid> 
    118     <grid id="dst_grid_regular"> 
    119       <domain domain_ref="dst_domain_regular"/> 
    120     </grid> 
    121     <grid id="src_grid_3D"> 
    122       <domain domain_ref="src_domain"/> 
    123       <axis axis_ref="src_axis"/> 
    124     </grid> 
    125     <grid id="dst_grid_3D"> 
    126 <!--      <domain domain_ref="src_domain"/>--> 
    127       <domain domain_ref="dst_domain_regular_pole"/> 
    128 <!--      <axis axis_ref="src_axis"/>--> 
    129       <axis axis_ref="dst_axis"/> 
    130     </grid> 
     126    <grid_group id="read_grids"> 
     127      <grid id="src_grid_regular_read"> 
     128        <domain domain_ref="src_domain_regular_read"/> 
     129      </grid> 
     130      <grid id="src_grid_curvilinear_read"> 
     131        <domain domain_ref="src_domain_curvilinear_read"/> 
     132        <axis axis_ref="src_axis_curvilinear_read" /> 
     133      </grid> 
     134      <grid id="src_grid_unstructured_read"> 
     135        <domain domain_ref="src_domain_unstructured_read"/> 
     136      </grid> 
     137    </grid_group> 
     138 
     139    <grid_group id="grid_src"> 
     140      <grid id="src_grid_3D"> 
     141        <domain domain_ref="src_domain"/> 
     142        <axis axis_ref="src_axis"/> 
     143      </grid> 
     144      <grid id="grid_4D"> 
     145        <domain domain_ref="src_domain"/> 
     146        <axis axis_ref="src_axis"/> 
     147        <axis axis_ref="nq"/> 
     148      </grid> 
     149    </grid_group> 
     150 
     151    <grid_group id="grid_dst"> 
     152      <grid id="dst_grid_regular"> 
     153        <domain domain_ref="dst_domain_regular"/> 
     154      </grid> 
     155      <grid id="dst_grid_3D"> 
     156        <domain domain_ref="src_domain"/> 
     157        <axis axis_ref="dst_axis"/> 
     158      </grid> 
     159      <grid id="grid_4D_extract"> 
     160        <domain domain_ref="dst_domain_regular_pole"/>       
     161        <axis axis_ref="src_axis"/>         
     162        <scalar > 
     163          <extract_axis position="1"/> 
     164        </scalar>       
     165      </grid> 
     166    </grid_group> 
    131167  </grid_definition> 
    132168  </context> 
  • XIOS/trunk/src/test/test_remap.f90

    r903 r978  
    2020  DOUBLE PRECISION,ALLOCATABLE :: src_boundslon(:,:), dst_boundslon(:,:) 
    2121  DOUBLE PRECISION,ALLOCATABLE :: src_boundslat(:,:), dst_boundslat(:,:) 
    22   DOUBLE PRECISION,ALLOCATABLE :: src_field(:) 
    23   DOUBLE PRECISION,ALLOCATABLE :: tmp_field(:), tmp_field_1(:), tmp_field_2(:) 
    24   DOUBLE PRECISION,ALLOCATABLE :: src_field_3D(:,:), lval(:), lval1(:), src_field_pression(:,:) 
     22  DOUBLE PRECISION,ALLOCATABLE :: src_field_2D(:) 
     23  DOUBLE PRECISION,ALLOCATABLE :: tmp_field_0(:), tmp_field_1(:), tmp_field_2(:) 
     24  DOUBLE PRECISION,ALLOCATABLE :: src_field_3D(:,:), src_field_4D(:,:,:), lval(:), lval1(:), lval2(:), src_field_pression(:,:) 
    2525  LOGICAL,ALLOCATABLE :: src_mask_2D(:) 
    2626  INTEGER :: src_ni_glo, dst_ni_glo; 
     
    3737  INTEGER :: ts 
    3838  INTEGER :: i 
    39   INTEGER,PARAMETER :: llm=5, interpolatedLlm = 4 
     39  INTEGER,PARAMETER :: llm=5, interpolatedLlm = 4, llm2 = 6 
    4040 
    4141  CALL MPI_INIT(ierr) 
     
    6868  ALLOCATE(src_boundslon(src_nvertex,src_ni)) 
    6969  ALLOCATE(src_boundslat(src_nvertex,src_ni)) 
    70   ALLOCATE(src_field(src_ni)) 
     70  ALLOCATE(src_field_2D(src_ni)) 
    7171  ALLOCATE(src_field_3D(src_ni,llm)) 
     72  ALLOCATE(src_field_4D(src_ni,llm,llm2)) 
    7273  ALLOCATE(src_mask_2D(src_ni)) 
    7374  ALLOCATE(src_field_pression(src_ni,llm)) 
    7475  ALLOCATE(lval(llm)) 
    7576  ALLOCATE(lval1(interpolatedLlm)) 
     77  ALLOCATE(lval2(llm2)) 
    7678 
    7779  ierr=NF90_INQ_VARID(ncid,"lon",varid) 
     
    8486  ierr=NF90_GET_VAR(ncid,varid, src_boundslat, start=(/1,src_ibegin+1/),count=(/src_nvertex,src_ni/)) 
    8587  ierr=NF90_INQ_VARID(ncid,"val",varid) 
    86   ierr=NF90_GET_VAR(ncid,varid, src_field, start=(/src_ibegin+1/),count=(/src_ni/)) 
     88  ierr=NF90_GET_VAR(ncid,varid, src_field_2D, start=(/src_ibegin+1/),count=(/src_ni/)) 
    8789  DO i=1,src_ni 
    88     src_field_3D(i,:) = src_field(i) 
     90    src_field_3D(i,:) = src_field_2D(i) 
    8991    IF (MOD(i,10)==0) THEN 
    9092      src_mask_2D(i)=.FALSE. 
     
    9799    lval(i) = i*100 
    98100    src_field_pression(:,i) = i * 100 
    99     src_field_3D(:,i) = src_field_3D(:,i) + i * 10 
     101    src_field_3D(:,i) = src_field_3D(:,i) + i * 10     
     102  ENDDO 
     103 
     104  DO i=1,llm2 
     105    src_field_4D(:,:,i) = src_field_3D(:,:) 
    100106  ENDDO 
    101107 
    102108  DO i=1,interpolatedLlm 
     109    lval2(i) = i*10 
    103110    lval1(i) = i*10 + 2 
    104111  ENDDO 
     
    149156 
    150157  CALL xios_set_axis_attr("src_axis", n_glo=llm, value=lval) 
     158  CALL xios_set_axis_attr("nq", n_glo=llm2, value=lval2) 
    151159 
    152160  CALL xios_set_domain_attr("dst_domain", ni_glo=dst_ni_glo, ibegin=dst_ibegin, ni=dst_ni, type="unstructured") 
     
    158166 
    159167  CALL xios_close_context_definition() 
    160 !  CALL xios_get_domain_attr("src_domain_regular_tmp", ni=src_tmp_ni, nj=src_tmp_nj) 
    161 !  ALLOCATE(tmp_field(src_tmp_ni*src_tmp_nj)) 
    162 ! 
    163 !  CALL xios_get_axis_attr("src_axis_curvilinear", n=src_tmp_n) 
    164 !  CALL xios_get_domain_attr("src_domain_curvilinear", ni=src_tmp_ni, nj=src_tmp_nj) 
    165 ! ALLOCATE(tmp_field_1(src_tmp_ni*src_tmp_nj*src_tmp_n)) 
    166  
    167 !  CALL xios_get_domain_attr("src_domain_unstructured", ni=src_tmp_ni, nj=src_tmp_nj) 
    168 ! ALLOCATE(tmp_field_2(src_tmp_ni*src_tmp_nj)) 
     168  ! CALL xios_get_domain_attr("src_domain_regular_read", ni=src_tmp_ni, nj=src_tmp_nj) 
     169  ! ALLOCATE(tmp_field_0(src_tmp_ni*src_tmp_nj)) 
     170 
     171  ! CALL xios_get_axis_attr("src_axis_curvilinear_read", n=src_tmp_n) 
     172  ! CALL xios_get_domain_attr("src_domain_curvilinear_read", ni=src_tmp_ni, nj=src_tmp_nj) 
     173  ! ALLOCATE(tmp_field_1(src_tmp_ni*src_tmp_nj*src_tmp_n)) 
     174 
     175  ! CALL xios_get_domain_attr("src_domain_unstructured_read", ni=src_tmp_ni, nj=src_tmp_nj) 
     176  ! ALLOCATE(tmp_field_2(src_tmp_ni*src_tmp_nj)) 
    169177 
    170178  DO ts=1,5 
    171  
    172 !    CALL xios_recv_field("src_field_regular_tmp", tmp_field) 
    173 !    CALL xios_recv_field("src_field_curvilinear", tmp_field_1) 
    174 !    CALL xios_recv_field("field_src_unstructred", tmp_field_2) 
     179    ! CALL xios_recv_field("src_field_regular", tmp_field_0) 
     180    ! CALL xios_recv_field("src_field_curvilinear", tmp_field_1) 
     181    ! CALL xios_recv_field("src_field_unstructured", tmp_field_2) 
    175182    CALL xios_update_calendar(ts) 
    176     CALL xios_send_field("src_field",src_field) 
     183    CALL xios_send_field("src_field_2D",src_field_2D) 
     184    CALL xios_send_field("src_field_2D_clone",src_field_2D) 
    177185    CALL xios_send_field("src_field_3D",src_field_3D) 
     186    CALL xios_send_field("src_field_4D",src_field_4D) 
    178187    CALL xios_send_field("src_field_3D_pression",src_field_pression) 
    179 !    CALL xios_send_field("tmp_field",tmp_field) 
    180 !    CALL xios_send_field("tmp_field_1",tmp_field_1) 
    181 !    CALL xios_send_field("tmp_field_2",tmp_field_2) 
     188    ! CALL xios_send_field("tmp_field_0",tmp_field_0) 
     189    ! CALL xios_send_field("tmp_field_1",tmp_field_1) 
     190    ! CALL xios_send_field("tmp_field_2",tmp_field_2) 
    182191    CALL wait_us(5000) ; 
    183   ENDDO 
     192   ENDDO 
    184193 
    185194  CALL xios_context_finalize() 
    186195 
    187   DEALLOCATE(src_lon, src_lat, src_boundslon,src_boundslat, src_field) 
     196  DEALLOCATE(src_lon, src_lat, src_boundslon,src_boundslat, src_field_2D) 
    188197  DEALLOCATE(dst_lon, dst_lat, dst_boundslon,dst_boundslat) 
    189 !  DEALLOCATE(tmp_field, tmp_field_1, tmp_field_2) 
     198  ! DEALLOCATE(tmp_field_0, tmp_field_1, tmp_field_2) 
    190199 
    191200  CALL MPI_COMM_FREE(comm, ierr) 
  • XIOS/trunk/src/transformation/domain_algorithm_compute_connectivity.cpp

    r944 r978  
    2929 
    3030  CComputeConnectivityDomain* compute_connectivityDomain = dynamic_cast<CComputeConnectivityDomain*> (transformation); 
    31   int domainDstIndex = elementPositionInGridDst2AxisPosition[elementPositionInGrid]; 
    32   int domainSrcIndex = elementPositionInGridSrc2AxisPosition[elementPositionInGrid]; 
     31  int domainDstIndex = elementPositionInGridDst2DomainPosition[elementPositionInGrid]; 
     32  int domainSrcIndex = elementPositionInGridSrc2DomainPosition[elementPositionInGrid]; 
    3333 
    3434  return (new CDomainAlgorithmComputeConnectivity(domainListDestP[domainDstIndex], domainListSrcP[domainSrcIndex], compute_connectivityDomain)); 
  • XIOS/trunk/src/transformation/domain_algorithm_expand.cpp

    r943 r978  
    3131 
    3232  CExpandDomain* expandDomain = dynamic_cast<CExpandDomain*> (transformation); 
    33   int domainDstIndex = elementPositionInGridDst2AxisPosition[elementPositionInGrid]; 
    34   int domainSrcIndex = elementPositionInGridSrc2AxisPosition[elementPositionInGrid]; 
     33  int domainDstIndex = elementPositionInGridDst2DomainPosition[elementPositionInGrid]; 
     34  int domainSrcIndex = elementPositionInGridSrc2DomainPosition[elementPositionInGrid]; 
    3535 
    3636  return (new CDomainAlgorithmExpand(domainListDestP[domainDstIndex], domainListSrcP[domainSrcIndex], expandDomain)); 
  • XIOS/trunk/src/transformation/domain_algorithm_interpolate.cpp

    r953 r978  
    3636 
    3737  CInterpolateDomain* interpolateDomain = dynamic_cast<CInterpolateDomain*> (transformation); 
    38   int domainDstIndex = elementPositionInGridDst2AxisPosition[elementPositionInGrid]; 
    39   int domainSrcIndex = elementPositionInGridSrc2AxisPosition[elementPositionInGrid]; 
     38  int domainDstIndex = elementPositionInGridDst2DomainPosition[elementPositionInGrid]; 
     39  int domainSrcIndex = elementPositionInGridSrc2DomainPosition[elementPositionInGrid]; 
    4040 
    4141  return (new CDomainAlgorithmInterpolate(domainListDestP[domainDstIndex], domainListSrcP[domainSrcIndex], interpolateDomain)); 
  • XIOS/trunk/src/transformation/grid_generate.cpp

    r889 r978  
    103103    int elementPositionInGrid = it->first; 
    104104    ETranformationType transType = (it->second).first; 
    105     int transformationOrder = (it->second).second; 
     105    int transformationOrder = (it->second).second.first; 
     106    int algoType = (it->second).second.second; 
    106107 
    107108    // First of all, select an algorithm 
    108     selectAlgo(elementPositionInGrid, transType, transformationOrder, algoTypes_[std::distance(itb, it)]); 
     109    selectAlgo(elementPositionInGrid, transType, transformationOrder, algoType); 
    109110  } 
    110111} 
  • XIOS/trunk/src/transformation/grid_transformation.cpp

    r941 r978  
    100100  CDomain::TransMapTypes trans = domainListDestP[domainIndex]->getAllTransformations(); 
    101101  CDomain::TransMapTypes::const_iterator it = trans.begin(); 
    102   for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation 
     102  for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation   
    103103 
    104104  CGenericAlgorithmTransformation* algo = 0; 
     
    118118 
    119119/*! 
     120  Find position of element in a grid as well as its type (domain, axis, scalar) and position in its own element list 
     121  \return element position: map<int,<int,int> > corresponds to <element position in grid, <element type, element position in element list> > 
     122*/ 
     123std::map<int,std::pair<int,int> > CGridTransformation::getElementPosition(CGrid* grid) 
     124{ 
     125  std::vector<CScalar*> scalarListP = grid->getScalars();  
     126  std::vector<CAxis*> axisListP = grid->getAxis(); 
     127  std::vector<CDomain*> domListP = grid->getDomains();   
     128  CArray<int,1> axisDomainOrder = grid->axis_domain_order; 
     129  int scalarIndex = 0, axisIndex = 0, domainIndex = 0; 
     130  int nbElement = axisDomainOrder.numElements(), elementDim; 
     131  std::map<int,std::pair<int,int> > elementPosition; 
     132  for (int idx = 0; idx < nbElement; ++idx) 
     133  { 
     134    elementDim = axisDomainOrder(idx); 
     135    switch (elementDim) 
     136    { 
     137      case 2: 
     138        elementPosition[idx] = std::make_pair(elementDim, domainIndex); 
     139        ++domainIndex; 
     140        break; 
     141      case 1: 
     142        elementPosition[idx] = std::make_pair(elementDim, axisIndex); 
     143        ++axisIndex; 
     144        break; 
     145      case 0: 
     146        elementPosition[idx] = std::make_pair(elementDim, scalarIndex); 
     147        ++scalarIndex; 
     148        break; 
     149      default: 
     150        break;         
     151    } 
     152  } 
     153 
     154  return elementPosition;   
     155} 
     156 
     157/*! 
    120158  If there are more than one transformation, a new temporary grid will be created and it will play the role of grid destination. 
    121159This new created one keeps a pointer to the real transformed element of grid destination and generate new copies of other elements from grid source. 
     
    123161  \param [in] transType transformation type 
    124162*/ 
    125 void CGridTransformation::setUpGridDestination(int elementPositionInGrid, ETranformationType transType, AlgoType algoType) 
     163void CGridTransformation::setUpGridDestination(int elementPositionInGrid, ETranformationType transType) 
    126164{ 
    127165  if (isSpecialTransformation(transType)) return; 
     
    130168  { 
    131169    tempGridDests_.resize(0); 
     170  } 
     171 
     172  if (1 == getNbAlgo())  
     173  { 
     174    tmpGridDestination_ = gridDestination_; 
     175    return; 
    132176  } 
    133177 
     
    144188  CArray<int,1> axisDomainOrderDst = gridDestination_->axis_domain_order; 
    145189 
    146   int scalarIndex = -1, axisIndex = -1, domainIndex = -1; 
    147   switch (algoType) 
    148   { 
    149     case domainType: 
    150       domainIndex = elementPositionInGridDst2DomainPosition_[elementPositionInGrid]; 
    151       break; 
    152     case axisType: 
    153       axisIndex =  elementPositionInGridDst2AxisPosition_[elementPositionInGrid]; 
    154       break; 
    155     case scalarType: 
    156       scalarIndex = elementPositionInGridDst2ScalarPosition_[elementPositionInGrid]; 
    157       break; 
    158     default: 
    159       break; 
    160   } 
    161  
     190  std::map<int,std::pair<int,int> > elementPositionSrc = getElementPosition(gridSource_); 
     191  std::map<int,std::pair<int,int> > elementPositionDst = getElementPosition(gridDestination_); 
     192 
     193  CArray<int,1> elementOrder(axisDomainOrderDst.numElements()); 
    162194  for (int idx = 0; idx < axisDomainOrderDst.numElements(); ++idx) 
    163195  { 
    164     int dimElementDst = axisDomainOrderDst(idx); 
    165     if (2 == dimElementDst) 
    166     { 
    167       if (elementPositionInGrid == idx) 
    168         domainDst.push_back(domListDestP[domainIndex]); 
    169       else 
    170         domainDst.push_back(domListSrcP[elementPositionInGridSrc2DomainPosition_[elementPositionInGrid]]); 
    171     } 
    172     else if (1 == dimElementDst) 
    173     { 
    174       if (elementPositionInGrid == idx) 
    175         axisDst.push_back(axisListDestP[axisIndex]); 
    176       else 
    177         axisDst.push_back(axisListSrcP[elementPositionInGridSrc2AxisPosition_[elementPositionInGrid]]); 
     196    if (elementPositionInGrid == idx) 
     197    { 
     198      int dimElementDst = elementPositionDst[idx].first; 
     199      int elementIndex  = elementPositionDst[idx].second; 
     200      switch (dimElementDst)  
     201      { 
     202        case 2: 
     203          domainDst.push_back(domListDestP[elementIndex]); 
     204          break; 
     205        case 1: 
     206          axisDst.push_back(axisListDestP[elementIndex]); 
     207          break; 
     208        case 0: 
     209          scalarDst.push_back(scalarListDestP[elementIndex]); 
     210          break; 
     211        default: 
     212          break; 
     213      } 
     214      elementOrder(idx) = dimElementDst; 
    178215    } 
    179216    else 
    180     { 
    181       if (elementPositionInGrid == idx) 
    182         scalarDst.push_back(scalarListDestP[scalarIndex]); 
    183       else 
    184         scalarDst.push_back(scalarListSrcP[elementPositionInGridSrc2ScalarPosition_[elementPositionInGrid]]); 
    185     } 
    186   } 
    187  
    188   tmpGridDestination_ = CGrid::createGrid(domainDst, axisDst, scalarDst, gridDestination_->axis_domain_order); 
    189   tmpGridDestination_->computeGridGlobalDimension(domainDst, axisDst, scalarDst, gridDestination_->axis_domain_order); 
     217    {       
     218      int dimElementSrc = elementPositionSrc[idx].first; 
     219      int elementIndex  = elementPositionSrc[idx].second; 
     220      switch (dimElementSrc) 
     221      { 
     222        case 2: 
     223          domainDst.push_back(domListSrcP[elementIndex]); 
     224          break; 
     225        case 1: 
     226          axisDst.push_back(axisListSrcP[elementIndex]); 
     227          break; 
     228        case 0: 
     229          scalarDst.push_back(scalarListSrcP[elementIndex]); 
     230          break; 
     231        default: 
     232          break; 
     233      } 
     234      elementOrder(idx) = dimElementSrc; 
     235    } 
     236  } 
     237 
     238  tmpGridDestination_ = CGrid::createGrid(domainDst, axisDst, scalarDst, elementOrder); 
     239  tmpGridDestination_->computeGridGlobalDimension(domainDst, axisDst, scalarDst, elementOrder); 
    190240  tempGridDests_.push_back(tmpGridDestination_); 
    191241} 
     
    198248  \param [in] transType transformation type 
    199249*/ 
    200 void CGridTransformation::setUpGridSource(int elementPositionInGrid, AlgoType algoType) 
     250void CGridTransformation::setUpGridSource(int elementPositionInGrid) 
    201251{ 
    202252  if (!tempGridSrcs_.empty() && (getNbAlgo()-1) == tempGridSrcs_.size()) 
     
    214264  std::vector<CDomain*> domListSrcP = gridSource_->getDomains(), domainSrc; 
    215265 
    216   CArray<int,1> axisDomainOrderDst = gridDestination_->axis_domain_order; 
    217  
    218   int axisIndex = -1, domainIndex = -1, scalarIndex = -1; 
    219   int axisListIndex = 0, domainListIndex = 0, scalarListIndex = 0; 
    220   switch (algoType) 
    221   { 
    222     case domainType: 
    223       domainIndex = elementPositionInGridDst2DomainPosition_[elementPositionInGrid]; 
    224       break; 
    225     case axisType: 
    226       axisIndex =  elementPositionInGridDst2AxisPosition_[elementPositionInGrid]; 
    227       break; 
    228     case scalarType: 
    229       scalarIndex = elementPositionInGridDst2ScalarPosition_[elementPositionInGrid]; 
    230       break; 
    231     default: 
    232       break; 
    233   } 
     266  CArray<int,1> axisDomainOrderSrc = gridSource_->axis_domain_order; 
     267  CArray<int,1> axisDomainOrderDst = tmpGridDestination_->axis_domain_order; 
     268 
     269  std::map<int,std::pair<int,int> > elementPositionSrc = getElementPosition(gridSource_); 
     270  std::map<int,std::pair<int,int> > elementPositionDst = getElementPosition(tmpGridDestination_); 
    234271 
    235272  for (int idx = 0; idx < axisDomainOrderDst.numElements(); ++idx) 
    236   { 
    237     int dimElementDst = axisDomainOrderDst(idx); 
    238     if (2 == dimElementDst) 
    239     { 
    240       if (elementPositionInGrid == idx) 
    241         domainSrc.push_back(domListDestP[domainIndex]); 
    242       else 
     273  {    
     274    if (elementPositionInGrid == idx) 
     275    { 
     276      int dimElementDst = elementPositionDst[idx].first; 
     277      int elementIndex  = elementPositionDst[idx].second; 
     278      if (2 == dimElementDst) 
    243279      { 
    244280        CDomain* domain = CDomain::createDomain(); 
    245         domain->domain_ref.setValue(domListDestP[domainListIndex]->getId()); 
     281        domain->domain_ref.setValue(domListDestP[elementIndex]->getId()); 
    246282        domain->solveRefInheritance(true); 
    247283        domain->checkAttributesOnClient(); 
    248284        domainSrc.push_back(domain); 
    249285      } 
    250       ++domainListIndex; 
    251     } 
    252     else if (1 == dimElementDst) 
    253     { 
    254       if (elementPositionInGrid == idx) 
    255         axisSrc.push_back(axisListDestP[axisIndex]); 
    256       else 
     286      else if (1 == dimElementDst) 
    257287      { 
    258288        CAxis* axis = CAxis::createAxis(); 
    259         axis->axis_ref.setValue(axisListDestP[axisListIndex]->getId()); 
     289        axis->axis_ref.setValue(axisListDestP[elementIndex]->getId()); 
    260290        axis->solveRefInheritance(true); 
    261291        axis->checkAttributesOnClient(); 
    262         axisSrc.push_back(axis); 
    263       } 
    264       ++axisListIndex; 
    265     } 
    266     else 
    267     { 
    268       if (elementPositionInGrid == idx) 
    269         scalarSrc.push_back(scalarListDestP[scalarIndex]); 
     292        axisSrc.push_back(axis);  
     293      } 
    270294      else 
    271295      { 
    272296        CScalar* scalar = CScalar::createScalar(); 
    273         scalar->scalar_ref.setValue(scalarListDestP[scalarListIndex]->getId()); 
     297        scalar->scalar_ref.setValue(scalarListDestP[elementIndex]->getId()); 
    274298        scalar->solveRefInheritance(true); 
    275299        scalar->checkAttributesOnClient(); 
    276300        scalarSrc.push_back(scalar); 
    277301      } 
    278       ++scalarListIndex; 
     302    } 
     303    else 
     304    {       
     305      int dimElementDst = elementPositionDst[idx].first; 
     306      int elementIndex  = elementPositionDst[idx].second; 
     307      switch (dimElementDst) 
     308      { 
     309        case 2: 
     310          domainSrc.push_back(domListDestP[elementIndex]); 
     311          break; 
     312        case 1: 
     313          axisSrc.push_back(axisListDestP[elementIndex]); 
     314          break; 
     315        case 0: 
     316          scalarSrc.push_back(scalarListDestP[elementIndex]); 
     317          break; 
     318        default: 
     319          break; 
     320      } 
    279321    } 
    280322  } 
     
    323365    int elementPositionInGrid = it->first; 
    324366    ETranformationType transType = (it->second).first; 
    325     int transformationOrder = (it->second).second; 
     367    int transformationOrder = (it->second).second.first; 
     368    int algoType = ((it->second).second.second); //algoTypes_[std::distance(itb, it)]; 
    326369    SourceDestinationIndexMap globaIndexWeightFromSrcToDst; 
    327     AlgoType algoType = algoTypes_[std::distance(itb, it)]; 
     370     
    328371 
    329372    // Create a temporary grid destination which contains transformed element of grid destination and 
    330373    // non-transformed elements to grid source 
    331     setUpGridDestination(elementPositionInGrid, transType, algoType); 
     374    setUpGridDestination(elementPositionInGrid, transType); 
    332375 
    333376    // First of all, select an algorithm 
     
    359402      { 
    360403        // Now grid destination becomes grid source in a new transformation 
    361         if (nbAgloTransformation != (nbNormalAlgos_-1)) setUpGridSource(elementPositionInGrid, algoType); 
     404        if (nbAgloTransformation != (nbNormalAlgos_-1)) setUpGridSource(elementPositionInGrid); 
    362405      } 
    363406      ++nbAgloTransformation; 
  • XIOS/trunk/src/transformation/grid_transformation.hpp

    r933 r978  
    6161  virtual void selectDomainAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder); 
    6262 
    63   void setUpGridSource(int elementPositionInGrid, AlgoType); 
    64   void setUpGridDestination(int elementPositionInGrid, ETranformationType, AlgoType); 
     63  void setUpGridSource(int elementPositionInGrid); 
     64  void setUpGridDestination(int elementPositionInGrid, ETranformationType); 
    6565  void computeTransformationMapping(const SourceDestinationIndexMap& globalIndexWeightFromSrcToDest); 
     66  std::map<int,std::pair<int,int> > getElementPosition(CGrid* grid); 
    6667 
    6768protected: 
  • XIOS/trunk/src/transformation/grid_transformation_selector.cpp

    r976 r978  
    102102 
    103103/*! 
    104   Initialize the algorithms (transformations) 
    105 */ 
    106 void CGridTransformationSelector::initializeAlgorithms() 
     104  Update position of elements in grid source and grid destination as well as their positions in element list 
     105*/ 
     106void CGridTransformationSelector::updateElementPosition() 
    107107{ 
    108108  int idxScalar = 0, idxAxis = 0, idxDomain = 0; 
    109109  CArray<int,1> axisDomainOrderDst = gridDestination_->axis_domain_order; 
     110  std::map<int, int>().swap(elementPositionInGridDst2DomainPosition_); 
     111  std::map<int, int>().swap(elementPositionInGridDst2AxisPosition_); 
     112  std::map<int, int>().swap(elementPositionInGridDst2ScalarPosition_); 
    110113  for (int i = 0; i < axisDomainOrderDst.numElements(); ++i) 
    111114  { 
     
    130133  idxScalar = idxAxis = idxDomain = 0; 
    131134  CArray<int,1> axisDomainOrderSrc = gridSource_->axis_domain_order; 
     135  std::map<int, int>().swap(elementPositionInGridSrc2DomainPosition_); 
     136  std::map<int, int>().swap(elementPositionInGridSrc2AxisPosition_); 
     137  std::map<int, int>().swap(elementPositionInGridSrc2ScalarPosition_); 
    132138  for (int i = 0; i < axisDomainOrderSrc.numElements(); ++i) 
    133139  { 
     
    149155    } 
    150156  } 
    151  
     157} 
     158 
     159/*! 
     160  Initialize the algorithms (transformations) 
     161*/ 
     162void CGridTransformationSelector::initializeAlgorithms() 
     163{ 
     164  updateElementPosition(); 
     165  CArray<int,1> axisDomainOrderDst = gridDestination_->axis_domain_order; 
    152166  for (int i = 0; i < axisDomainOrderDst.numElements(); ++i) 
    153167  { 
     
    183197    int scalarDstPos = -1, scalarSrcPos = -1; 
    184198    if (0 < elementPositionInGridDst2ScalarPosition_.count(scalarPositionInGrid)) 
    185       scalarDstPos = elementPositionInGridDst2AxisPosition_[scalarPositionInGrid]; 
     199      scalarDstPos = elementPositionInGridDst2ScalarPosition_[scalarPositionInGrid]; 
    186200    if (0 < elementPositionInGridSrc2ScalarPosition_.count(scalarPositionInGrid)) 
    187       scalarSrcPos = elementPositionInGridSrc2AxisPosition_[scalarPositionInGrid]; 
     201      scalarSrcPos = elementPositionInGridSrc2ScalarPosition_[scalarPositionInGrid]; 
    188202 
    189203    // If source and destination grid share the same scalar 
     
    199213      for (it = itb; it != ite; ++it) 
    200214      { 
    201         listAlgos_.push_back(std::make_pair(scalarPositionInGrid, std::make_pair(it->first, transformationOrder))); 
    202         algoTypes_.push_back(scalarType); 
     215        listAlgos_.push_back(std::make_pair(scalarPositionInGrid, std::make_pair(it->first, std::make_pair(transformationOrder,0))));         
    203216        ++transformationOrder; 
    204217        std::vector<StdString> auxInput = (it->second)->checkAuxInputs(); 
     
    240253      for (it = itb; it != ite; ++it) 
    241254      { 
    242         listAlgos_.push_back(std::make_pair(axisPositionInGrid, std::make_pair(it->first, transformationOrder))); 
    243         algoTypes_.push_back(axisType); 
     255        listAlgos_.push_back(std::make_pair(axisPositionInGrid, std::make_pair(it->first, std::make_pair(transformationOrder,1))));         
    244256        ++transformationOrder; 
    245257        std::vector<StdString> auxInput = (it->second)->checkAuxInputs(); 
     
    264276    int domDstPos = -1, domSrcPos = -1; 
    265277    if (0 < elementPositionInGridDst2DomainPosition_.count(domPositionInGrid)) 
    266       domDstPos = elementPositionInGridDst2AxisPosition_[domPositionInGrid]; 
     278      domDstPos = elementPositionInGridDst2DomainPosition_[domPositionInGrid]; 
    267279    if (0 < elementPositionInGridSrc2DomainPosition_.count(domPositionInGrid)) 
    268       domSrcPos = elementPositionInGridSrc2AxisPosition_[domPositionInGrid]; 
     280      domSrcPos = elementPositionInGridSrc2DomainPosition_[domPositionInGrid]; 
    269281 
    270282    // If source and destination grid share the same domain 
     
    280292      for (it = itb; it != ite; ++it) 
    281293      { 
    282         listAlgos_.push_back(std::make_pair(domPositionInGrid, std::make_pair(it->first, transformationOrder))); 
    283         algoTypes_.push_back(domainType); 
     294        listAlgos_.push_back(std::make_pair(domPositionInGrid, std::make_pair(it->first, std::make_pair(transformationOrder,2))));         
    284295        ++transformationOrder; 
    285296        std::vector<StdString> auxInput = (it->second)->checkAuxInputs(); 
     
    297308  \param [in] transType transformation type, for now we have Zoom_axis, inverse_axis 
    298309  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation) 
    299   \param [in] isDomainAlgo flag to specify type of algorithm (for domain or axis) 
    300 */ 
    301 void CGridTransformationSelector::selectAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder, AlgoType algoType) 
    302 { 
     310  \param [in] algoType flag to specify type of algorithm (2 for domain, 1 for axis and 0 for scalar)  
     311*/ 
     312void CGridTransformationSelector::selectAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder, int algoType) 
     313{ 
     314  updateElementPosition(); 
    303315  switch (algoType) 
    304316  { 
    305   case scalarType: 
     317  case 0: 
    306318    selectScalarAlgo(elementPositionInGrid, transType, transformationOrder); 
    307319    break; 
    308   case axisType: 
     320  case 1: 
    309321    selectAxisAlgo(elementPositionInGrid, transType, transformationOrder); 
    310322    break; 
    311   case domainType: 
     323  case 2: 
    312324    selectDomainAlgo(elementPositionInGrid, transType, transformationOrder); 
    313325    break; 
  • XIOS/trunk/src/transformation/grid_transformation_selector.hpp

    r933 r978  
    2828{ 
    2929public: 
    30   typedef std::list<std::pair<int,std::pair<ETranformationType,int> > > ListAlgoType; 
     30  // Stupid C++98, should be replaced with tuple. 
     31  // List of algorithm to process. Order of element in this list 
     32  // <Position of element in grid, <transformationType, <transformation order, alogrithm type> > > 
     33  typedef std::list<std::pair<int,std::pair<ETranformationType,std::pair<int,int> > > > ListAlgoType; 
    3134protected: 
    3235  enum AlgoType { 
     
    5053 
    5154protected: 
     55  void updateElementPosition(); 
    5256  void initializeAlgorithms(); 
    5357  void initializeDomainAlgorithms(int domPositionInGrid); 
     
    5559  void initializeScalarAlgorithms(int scalarPositionInGrid); 
    5660  void initializeTransformations(TransformationType type); 
    57   void selectAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder, AlgoType algo); 
     61  void selectAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder, int algo); 
    5862  bool isSpecialTransformation(ETranformationType transType); 
    5963  void registerTransformations(); 
Note: See TracChangeset for help on using the changeset viewer.