MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "moab/MOABConfig.h" 00002 00003 #ifdef MOAB_HAVE_MPI 00004 #include "moab_mpi.h" 00005 #endif 00006 #include "moab/iMOAB.h" 00007 #include "TestUtil.hpp" 00008 #include "moab/CpuTimer.hpp" 00009 #include "moab/ProgOptions.hpp" 00010 00011 // for malloc, free: 00012 #include <iostream> 00013 #include <iomanip> 00014 00015 #define CHECKIERR( ierr, message ) \ 00016 if( 0 != ( ierr ) ) \ 00017 { \ 00018 printf( "%s", message ); \ 00019 return 1; \ 00020 } 00021 00022 #define ENABLE_ATMLND_COUPLING 00023 // this test will be run in serial only 00024 int main( int argc, char* argv[] ) 00025 { 00026 ErrCode ierr; 00027 std::string atmFilename, ocnFilename, lndFilename, mapFilename; 00028 00029 atmFilename = TestDir + "unittest/wholeATM_T.h5m"; 00030 ocnFilename = TestDir + "unittest/recMeshOcn.h5m"; 00031 #ifdef ENABLE_ATMLND_COUPLING 00032 lndFilename = TestDir + "unittest/wholeLnd.h5m"; 00033 #endif 00034 // mapFilename = TestDir + "unittest/outCS5ICOD5_map.nc"; 00035 00036 ProgOptions opts; 00037 opts.addOpt< std::string >( "atmosphere,t", "atm mesh filename (source)", &atmFilename ); 00038 opts.addOpt< std::string >( "ocean,m", "ocean mesh filename (target)", &ocnFilename ); 00039 #ifdef ENABLE_ATMLND_COUPLING 00040 opts.addOpt< std::string >( "land,l", "land mesh filename (target)", &lndFilename ); 00041 #endif 00042 bool gen_baseline = false; 00043 opts.addOpt< void >( "genbase,g", "generate baseline 1", &gen_baseline ); 00044 00045 bool no_test_against_baseline = false; 00046 opts.addOpt< void >( "no_testbase,t", "do not test against baseline 1", &no_test_against_baseline ); 00047 std::string baseline = TestDir + "unittest/baseline1.txt"; 00048 00049 opts.parseCommandLine( argc, argv ); 00050 00051 { 00052 std::cout << " atm file: " << atmFilename << "\n ocn file: " << ocnFilename 00053 #ifdef ENABLE_ATMLND_COUPLING 00054 << "\n lnd file: " << lndFilename 00055 #endif 00056 << "\n"; 00057 } 00058 00059 #ifdef MOAB_HAVE_MPI 00060 MPI_Init( &argc, &argv ); 00061 MPI_Comm comm = MPI_COMM_WORLD; 00062 #endif 00063 /* 00064 * MOAB needs to be initialized; A MOAB instance will be created, and will be used by each 00065 * application in this framework. There is no parallel context yet. 00066 */ 00067 ierr = iMOAB_Initialize( argc, argv ); 00068 CHECKIERR( ierr, "failed to initialize MOAB" ); 00069 00070 int atmAppID, ocnAppID, lndAppID, atmocnAppID, atmlndAppID, lndatmAppID; 00071 iMOAB_AppID atmPID = &atmAppID; 00072 iMOAB_AppID ocnPID = &ocnAppID; 00073 iMOAB_AppID lndPID = &lndAppID; 00074 iMOAB_AppID atmocnPID = &atmocnAppID; 00075 iMOAB_AppID atmlndPID = &atmlndAppID; 00076 iMOAB_AppID lndatmPID = &lndatmAppID; 00077 00078 /* 00079 * Each application has to be registered once. A mesh set and a parallel communicator will be 00080 * associated with each application. A unique application id will be returned, and will be used 00081 * for all future mesh operations/queries. 00082 */ 00083 int atmCompID = 10, ocnCompID = 20, lndCompID = 30, atmocnCompID = 100, atmlndCompID = 102, lndatmCompID = 103; 00084 ierr = iMOAB_RegisterApplication( "ATM-APP", 00085 #ifdef MOAB_HAVE_MPI 00086 &comm, 00087 #endif 00088 &atmCompID, atmPID ); 00089 CHECKIERR( ierr, "failed to register application1" ); 00090 00091 ierr = iMOAB_RegisterApplication( "OCN-APP", 00092 #ifdef MOAB_HAVE_MPI 00093 &comm, 00094 #endif 00095 &ocnCompID, ocnPID ); 00096 CHECKIERR( ierr, "failed to register application2" ); 00097 #ifdef ENABLE_ATMLND_COUPLING 00098 ierr = iMOAB_RegisterApplication( "LND-APP", 00099 #ifdef MOAB_HAVE_MPI 00100 &comm, 00101 #endif 00102 &lndCompID, lndPID ); 00103 CHECKIERR( ierr, "failed to register application3" ); 00104 #endif 00105 ierr = iMOAB_RegisterApplication( "ATM-OCN-CPL", 00106 #ifdef MOAB_HAVE_MPI 00107 &comm, 00108 #endif 00109 &atmocnCompID, atmocnPID ); 00110 CHECKIERR( ierr, "failed to register application4" ); 00111 #ifdef ENABLE_ATMLND_COUPLING 00112 ierr = iMOAB_RegisterApplication( "ATM-LND-CPL", 00113 #ifdef MOAB_HAVE_MPI 00114 &comm, 00115 #endif 00116 &atmlndCompID, atmlndPID ); 00117 CHECKIERR( ierr, "failed to register application5" ); 00118 00119 ierr = iMOAB_RegisterApplication( "LND-ATM-CPL", 00120 #ifdef MOAB_HAVE_MPI 00121 &comm, 00122 #endif 00123 &lndatmCompID, lndatmPID ); 00124 CHECKIERR( ierr, "failed to register application5" ); 00125 #endif 00126 const char* read_opts = ""; 00127 int num_ghost_layers = 0; 00128 /* 00129 * Loading the mesh is a parallel IO operation. Ghost layers can be exchanged too, and default 00130 * MOAB sets are augmented with ghost elements. By convention, blocks correspond to MATERIAL_SET 00131 * sets, side sets with NEUMANN_SET sets, node sets with DIRICHLET_SET sets. Each element and 00132 * vertex entity should have a GLOBAL ID tag in the file, which will be available for visible 00133 * entities 00134 */ 00135 ierr = iMOAB_LoadMesh( atmPID, atmFilename.c_str(), read_opts, &num_ghost_layers ); 00136 CHECKIERR( ierr, "failed to load mesh" ); 00137 ierr = iMOAB_LoadMesh( ocnPID, ocnFilename.c_str(), read_opts, &num_ghost_layers ); 00138 CHECKIERR( ierr, "failed to load mesh" ); 00139 #ifdef ENABLE_ATMLND_COUPLING 00140 ierr = iMOAB_LoadMesh( lndPID, lndFilename.c_str(), read_opts, &num_ghost_layers ); 00141 CHECKIERR( ierr, "failed to load mesh" ); 00142 #endif 00143 00144 int nverts[3], nelem[3]; 00145 /* 00146 * Each process in the communicator will have access to a local mesh instance, which will 00147 * contain the original cells in the local partition and ghost entities. Number of vertices, 00148 * primary cells, visible blocks, number of sidesets and nodesets boundary conditions will be 00149 * returned in size 3 arrays, for local, ghost and total numbers. 00150 */ 00151 ierr = iMOAB_GetMeshInfo( atmPID, nverts, nelem, 0, 0, 0 ); 00152 CHECKIERR( ierr, "failed to get mesh info" ); 00153 printf( "Atmosphere Component Mesh: %d vertices and %d elements\n", nverts[0], nelem[0] ); 00154 00155 ierr = iMOAB_GetMeshInfo( ocnPID, nverts, nelem, 0, 0, 0 ); 00156 CHECKIERR( ierr, "failed to get mesh info" ); 00157 printf( "Ocean Component Mesh: %d vertices and %d elements\n", nverts[0], nelem[0] ); 00158 #ifdef ENABLE_ATMLND_COUPLING 00159 ierr = iMOAB_GetMeshInfo( lndPID, nverts, nelem, 0, 0, 0 ); 00160 CHECKIERR( ierr, "failed to get mesh info" ); 00161 printf( "Land Component Mesh: %d vertices and %d elements\n", nverts[0], nelem[0] ); 00162 #endif 00163 /* 00164 * The 2 tags used in this example exist in the file, already. 00165 * If a user needs a new tag, it can be defined with the same call as this one 00166 * this method, iMOAB_DefineTagStorage, will return a local index for the tag. 00167 * The name of the tag is case sensitive. 00168 * This method is collective. 00169 */ 00170 // int disc_orders[2] = {1, 1}; 00171 // const char* disc_methods[2] = {"fv", "fv"}; 00172 // const char* dof_tag_names[2] = {"GLOBAL_ID", "GLOBAL_ID"}; 00173 int disc_orders[3] = { 4, 1, 1 }; 00174 int fMonotoneTypeID = 0, fVolumetric = 0, fValidate = 1, fNoConserve = 0, fNoBubble = 1, fInverseDistanceMap = 0; 00175 00176 const std::string disc_methods[3] = { "cgll", "fv", "pcloud" }; 00177 const std::string dof_tag_names[3] = { "GLOBAL_DOFS", "GLOBAL_ID", "GLOBAL_ID" }; 00178 const std::string weights_identifiers[3] = { "scalar", "scalar_pointcloud", "scalar_conservative" }; 00179 00180 const std::string bottomTempField = "a2oTbot"; 00181 const std::string bottomTempFieldATM = "a2oTbotATM"; 00182 const std::string bottomTempProjectedField = "a2oTbot_proj"; 00183 const std::string bottomTempProjectedNCField = "a2oTbot_projnocons"; 00184 00185 // Attributes for tag data storage 00186 int tagIndex[4]; 00187 // int entTypes[2] = {1, 1}; /* both on elements; */ 00188 int tagTypes[2] = { DENSE_DOUBLE, DENSE_DOUBLE }; 00189 int atmCompNDoFs = disc_orders[0] * disc_orders[0], ocnCompNDoFs = 1 /*FV*/; 00190 00191 ierr = iMOAB_DefineTagStorage( atmPID, bottomTempField.c_str(), &tagTypes[0], &atmCompNDoFs, &tagIndex[0] ); 00192 CHECKIERR( ierr, "failed to define the field tag on ATM" ); 00193 00194 ierr = iMOAB_DefineTagStorage( atmPID, bottomTempFieldATM.c_str(), &tagTypes[0], &atmCompNDoFs, &tagIndex[0] ); 00195 CHECKIERR( ierr, "failed to define the field tag on ATM" ); 00196 00197 ierr = 00198 iMOAB_DefineTagStorage( ocnPID, bottomTempProjectedField.c_str(), &tagTypes[1], &ocnCompNDoFs, &tagIndex[1] ); 00199 CHECKIERR( ierr, "failed to define the field tag on OCN" ); 00200 00201 ierr = 00202 iMOAB_DefineTagStorage( ocnPID, bottomTempProjectedNCField.c_str(), &tagTypes[1], &ocnCompNDoFs, &tagIndex[2] ); 00203 CHECKIERR( ierr, "failed to define the field tag on OCN" ); 00204 00205 #ifdef ENABLE_ATMLND_COUPLING 00206 ierr = 00207 iMOAB_DefineTagStorage( lndPID, bottomTempProjectedField.c_str(), &tagTypes[1], &ocnCompNDoFs, &tagIndex[3] ); 00208 CHECKIERR( ierr, "failed to define the field tag on LND" ); 00209 #endif 00210 00211 /* Next compute the mesh intersection on the sphere between the source (ATM) and target (OCN) 00212 * meshes */ 00213 ierr = iMOAB_ComputeMeshIntersectionOnSphere( atmPID, ocnPID, atmocnPID ); 00214 CHECKIERR( ierr, "failed to compute mesh intersection between ATM and OCN" ); 00215 00216 #ifdef ENABLE_ATMLND_COUPLING 00217 /* Next compute the mesh intersection on the sphere between the source (ATM) and target (LND) 00218 * meshes */ 00219 ierr = iMOAB_ComputePointDoFIntersection( atmPID, lndPID, atmlndPID ); 00220 CHECKIERR( ierr, "failed to compute point-cloud mapping ATM-LND" ); 00221 00222 /* Next compute the mesh intersection on the sphere between the source (LND) and target (ATM) 00223 * meshes */ 00224 ierr = iMOAB_ComputePointDoFIntersection( lndPID, atmPID, lndatmPID ); 00225 CHECKIERR( ierr, "failed to compute point-cloud mapping LND-ATM" ); 00226 #endif 00227 00228 /* We have the mesh intersection now. Let us compute the remapping weights */ 00229 fNoConserve = 0; 00230 00231 /* Compute the weights to preoject the solution from ATM component to OCN compoenent */ 00232 ierr = iMOAB_ComputeScalarProjectionWeights( atmocnPID, weights_identifiers[0].c_str(), disc_methods[0].c_str(), 00233 &disc_orders[0], disc_methods[1].c_str(), &disc_orders[1], &fNoBubble, 00234 &fMonotoneTypeID, &fVolumetric, &fInverseDistanceMap, &fNoConserve, 00235 &fValidate, dof_tag_names[0].c_str(), dof_tag_names[1].c_str() ); 00236 CHECKIERR( ierr, "failed to compute remapping projection weights for ATM-OCN scalar " 00237 "non-conservative field" ); 00238 00239 // Let us now write the map file to disk and then read it back to test the I/O API in iMOAB 00240 #ifdef MOAB_HAVE_NETCDF 00241 { 00242 const std::string atmocn_map_file_name = "atm_ocn_map.nc"; 00243 ierr = 00244 iMOAB_WriteMappingWeightsToFile( atmocnPID, weights_identifiers[0].c_str(), atmocn_map_file_name.c_str() ); 00245 CHECKIERR( ierr, "failed to write map file to disk" ); 00246 00247 const std::string intx_from_file_identifier = "map-from-file"; 00248 // use old reader, coupler PID is -1 00249 int dummyCpl = -1; 00250 int dummy_rowcol = -1; 00251 int dummyType = 0; 00252 ierr = iMOAB_LoadMappingWeightsFromFile( atmocnPID, &dummyCpl, &dummy_rowcol, &dummyType, 00253 intx_from_file_identifier.c_str(), atmocn_map_file_name.c_str() ); 00254 CHECKIERR( ierr, "failed to load map file from disk" ); 00255 } 00256 #endif 00257 #ifdef ENABLE_ATMLND_COUPLING 00258 fValidate = 0; 00259 /* Compute the weights to preoject the solution from ATM component to LND compoenent */ 00260 ierr = iMOAB_ComputeScalarProjectionWeights( atmlndPID, weights_identifiers[1].c_str(), disc_methods[0].c_str(), 00261 &disc_orders[0], disc_methods[2].c_str(), &disc_orders[2], &fNoBubble, 00262 &fMonotoneTypeID, &fVolumetric, &fInverseDistanceMap, &fNoConserve, 00263 &fValidate, dof_tag_names[0].c_str(), dof_tag_names[2].c_str() ); 00264 CHECKIERR( ierr, "failed to compute remapping projection weights for ATM-LND scalar " 00265 "non-conservative field" ); 00266 00267 /* Compute the weights to preoject the solution from ATM component to LND compoenent */ 00268 ierr = iMOAB_ComputeScalarProjectionWeights( lndatmPID, weights_identifiers[1].c_str(), disc_methods[2].c_str(), 00269 &disc_orders[2], disc_methods[0].c_str(), &disc_orders[0], &fNoBubble, 00270 &fMonotoneTypeID, &fVolumetric, &fInverseDistanceMap, &fNoConserve, 00271 &fValidate, dof_tag_names[2].c_str(), dof_tag_names[0].c_str() ); 00272 CHECKIERR( ierr, "failed to compute remapping projection weights for LND-ATM scalar " 00273 "non-conservative field" ); 00274 #endif 00275 /* We have the mesh intersection now. Let us compute the remapping weights */ 00276 fNoConserve = 0; 00277 ierr = iMOAB_ComputeScalarProjectionWeights( atmocnPID, weights_identifiers[2].c_str(), disc_methods[0].c_str(), 00278 &disc_orders[0], disc_methods[1].c_str(), &disc_orders[1], &fNoBubble, 00279 &fMonotoneTypeID, &fVolumetric, &fInverseDistanceMap, &fNoConserve, 00280 &fValidate, dof_tag_names[0].c_str(), dof_tag_names[1].c_str() ); 00281 CHECKIERR( ierr, "failed to compute remapping projection weights for scalar conservative field" ); 00282 00283 /* We have the remapping weights now. Let us apply the weights onto the tag we defined 00284 on the srouce mesh and get the projection on the target mesh */ 00285 ierr = iMOAB_ApplyScalarProjectionWeights( atmocnPID, weights_identifiers[0].c_str(), bottomTempField.c_str(), 00286 bottomTempProjectedNCField.c_str() ); 00287 CHECKIERR( ierr, "failed to apply projection weights for scalar non-conservative field" ); 00288 00289 /* We have the remapping weights now. Let us apply the weights onto the tag we defined 00290 on the srouce mesh and get the projection on the target mesh */ 00291 ierr = iMOAB_ApplyScalarProjectionWeights( atmocnPID, weights_identifiers[2].c_str(), bottomTempField.c_str(), 00292 bottomTempProjectedField.c_str() ); 00293 CHECKIERR( ierr, "failed to apply projection weights for scalar conservative field" ); 00294 00295 if( gen_baseline ) 00296 { 00297 // get temp field on ocean, from conservative, the global ids, and dump to the baseline file 00298 // first get GlobalIds from ocn, and fields: 00299 ierr = iMOAB_GetMeshInfo( ocnPID, nverts, nelem, 0, 0, 0 ); 00300 CHECKIERR( ierr, "failed to get ocn mesh info" ); 00301 std::vector< int > gidElems; 00302 gidElems.resize( nelem[2] ); 00303 std::vector< double > tempElems; 00304 tempElems.resize( nelem[2] ); 00305 // get global id storage 00306 const std::string GidStr = "GLOBAL_ID"; // hard coded too 00307 00308 int tag_type = DENSE_INTEGER, ncomp = 1, tagInd = 0; 00309 // we should not have to define global id tag, it is always defined 00310 ierr = iMOAB_DefineTagStorage( ocnPID, GidStr.c_str(), &tag_type, &ncomp, &tagInd ); 00311 CHECKIERR( ierr, "failed to define global id tag" ); 00312 int ent_type = 1; 00313 ierr = iMOAB_GetIntTagStorage( ocnPID, GidStr.c_str(), &nelem[2], &ent_type, &gidElems[0] ); 00314 CHECKIERR( ierr, "failed to get global ids" ); 00315 ierr = 00316 iMOAB_GetDoubleTagStorage( ocnPID, bottomTempProjectedField.c_str(), &nelem[2], &ent_type, &tempElems[0] ); 00317 CHECKIERR( ierr, "failed to get temperature field" ); 00318 std::fstream fs; 00319 fs.open( baseline.c_str(), std::fstream::out ); 00320 fs << std::setprecision( 15 ); // maximum precision for doubles 00321 for( int i = 0; i < nelem[2]; i++ ) 00322 fs << gidElems[i] << " " << tempElems[i] << "\n"; 00323 fs.close(); 00324 } 00325 if( !no_test_against_baseline ) 00326 { 00327 // get temp field on ocean, from conservative, the global ids, and dump to the baseline file 00328 // first get GlobalIds from ocn, and fields: 00329 ierr = iMOAB_GetMeshInfo( ocnPID, nverts, nelem, 0, 0, 0 ); 00330 CHECKIERR( ierr, "failed to get ocn mesh info" ); 00331 std::vector< int > gidElems; 00332 gidElems.resize( nelem[2] ); 00333 std::vector< double > tempElems; 00334 tempElems.resize( nelem[2] ); 00335 // get global id storage 00336 const std::string GidStr = "GLOBAL_ID"; // hard coded too 00337 00338 int tag_type = DENSE_INTEGER, ncomp = 1, tagInd = 0; 00339 ierr = iMOAB_DefineTagStorage( ocnPID, GidStr.c_str(), &tag_type, &ncomp, &tagInd ); 00340 CHECKIERR( ierr, "failed to define global id tag" ); 00341 00342 int ent_type = 1; 00343 ierr = iMOAB_GetIntTagStorage( ocnPID, GidStr.c_str(), &nelem[2], &ent_type, &gidElems[0] ); 00344 CHECKIERR( ierr, "failed to get global ids" ); 00345 ierr = 00346 iMOAB_GetDoubleTagStorage( ocnPID, bottomTempProjectedField.c_str(), &nelem[2], &ent_type, &tempElems[0] ); 00347 CHECKIERR( ierr, "failed to get temperature field" ); 00348 int err_code = 1; 00349 check_baseline_file( baseline, gidElems, tempElems, 1.e-9, err_code ); 00350 if( 0 == err_code ) std::cout << " passed baseline test 1\n"; 00351 } 00352 #ifdef ENABLE_ATMLND_COUPLING 00353 /* We have the remapping weights now. Let us apply the weights onto the tag we defined 00354 on the srouce mesh and get the projection on the target mesh */ 00355 ierr = iMOAB_ApplyScalarProjectionWeights( atmlndPID, weights_identifiers[1].c_str(), bottomTempField.c_str(), 00356 bottomTempProjectedField.c_str() ); 00357 CHECKIERR( ierr, "failed to apply projection weights for ATM-LND scalar field" ); 00358 00359 /* We have the remapping weights now. Let us apply the weights onto the tag we defined 00360 on the srouce mesh and get the projection on the target mesh */ 00361 ierr = iMOAB_ApplyScalarProjectionWeights( lndatmPID, weights_identifiers[1].c_str(), 00362 bottomTempProjectedField.c_str(), bottomTempFieldATM.c_str() ); 00363 CHECKIERR( ierr, "failed to apply projection weights for LND-ATM scalar field" ); 00364 #endif 00365 /* 00366 * the file can be written in parallel, and it will contain additional tags defined by the user 00367 * we may extend the method to write only desired tags to the file 00368 */ 00369 { 00370 // free allocated data 00371 #ifdef ENABLE_ATMLND_COUPLING 00372 char outputFileAtmTgt[] = "fIntxAtmTarget.h5m"; 00373 #endif 00374 char outputFileOcnTgt[] = "fIntxOcnTarget.h5m"; 00375 #ifdef ENABLE_ATMLND_COUPLING 00376 char outputFileLndTgt[] = "fIntxLndTarget.h5m"; 00377 #endif 00378 char writeOptions[] = ""; 00379 00380 // Write out all the component meshes to disk for verification 00381 ierr = iMOAB_WriteMesh( ocnPID, outputFileOcnTgt, writeOptions ); 00382 CHECKIERR( ierr, "failed to write OCN mesh and data" ); 00383 #ifdef ENABLE_ATMLND_COUPLING 00384 ierr = iMOAB_WriteMesh( lndPID, outputFileLndTgt, writeOptions ); 00385 CHECKIERR( ierr, "failed to write LND mesh and data" ); 00386 ierr = iMOAB_WriteMesh( atmPID, outputFileAtmTgt, writeOptions ); 00387 CHECKIERR( ierr, "failed to write ATM mesh and data" ); 00388 #endif 00389 } 00390 00391 /* 00392 * deregistering application will delete all mesh entities associated with the application and 00393 * will free allocated tag storage. 00394 */ 00395 #ifdef ENABLE_ATMLND_COUPLING 00396 ierr = iMOAB_DeregisterApplication( lndPID ); 00397 CHECKIERR( ierr, "failed to de-register application3" ); 00398 #endif 00399 ierr = iMOAB_DeregisterApplication( ocnPID ); 00400 CHECKIERR( ierr, "failed to de-register application2" ); 00401 ierr = iMOAB_DeregisterApplication( atmPID ); 00402 CHECKIERR( ierr, "failed to de-register application1" ); 00403 00404 /* 00405 * this method will delete MOAB instance 00406 */ 00407 ierr = iMOAB_Finalize(); 00408 CHECKIERR( ierr, "failed to finalize MOAB" ); 00409 00410 #ifdef MOAB_HAVE_MPI 00411 MPI_Finalize(); 00412 #endif 00413 00414 return 0; 00415 }