MeshKit  1.0
PostBL.cpp
Go to the documentation of this file.
00001 #include "meshkit/PostBL.hpp"
00002 
00003 namespace MeshKit
00004 {
00005 
00006 // static registration of this mesh scheme
00007 moab::EntityType PostBL_tps[] = {moab::MBHEX,
00008                                  moab::MBMAXTYPE};
00009 const moab::EntityType* PostBL::output_types()
00010 { return PostBL_tps; }
00011 
00012 PostBL::PostBL( MKCore *mk, const MEntVector &me_vec)
00013     : MeshScheme( mk, me_vec),
00014       igeom(mk->igeom_instance()), imesh(mk->imesh_instance()),
00015       mb (mk->moab_instance())
00016     // ---------------------------------------------------------------------------
00020     // ---------------------------------------------------------------------------
00021 {
00022     tri_sch = 2;
00023     m_Conn = 0;
00024     m_BElemNodes = 0;
00025     m_SurfId = -1;
00026     check_bl_edge_length = false;
00027     debug = false;
00028     hybrid = false;
00029     m_NeumannSet = -1;
00030     m_Material = 999;
00031     m_nLineNumber = 0;
00032     szComment = "!";
00033     MAXCHARS = 300;
00034     m_JacCalls = 0;
00035     m_JLo = 0.0;
00036     m_JHi = 0.0;
00037     err = 0;
00038     fixmat = -1;
00039 }
00040 
00041 PostBL::~PostBL()
00042 // ---------------------------------------------------------------------------
00046 // ---------------------------------------------------------------------------
00047 {}
00048 
00049 bool PostBL::add_modelent(ModelEnt *model_ent)
00050 // ---------------------------------------------------------------------------
00054 // ---------------------------------------------------------------------------
00055 {
00056     return MeshOp::add_modelent(model_ent);
00057 }
00058 
00059 void PostBL::setup_this()
00060 // ---------------------------------------------------------------------------
00064 // ---------------------------------------------------------------------------
00065 {
00066     if (debug) {
00067         m_LogFile <<  "\nIn setup this : " <<  std::endl;
00068     }
00069 
00070 }
00071 
00072 void PostBL::execute_this()
00073 // ---------------------------------------------------------------------------
00077 // ---------------------------------------------------------------------------
00078 {
00079 
00082     int algo_no = 2;
00083     if(algo_no == 1){
00084         m_LogFile << "\nIn execute this : creating boundary layer elements.." <<  std::endl;
00085         // start the timer
00086         CClock Timer;
00087         clock_t sTime = clock();
00088         std::string szDateTime;
00089         Timer.GetDateTime (szDateTime);
00090 
00091         m_LogFile <<  "\nStarting out at : " << szDateTime << std::endl;
00092         m_LogFile <<  "\n Loading meshfile: " << m_MeshFile << ".." << std::endl;
00093 
00094         // load specified mesh file
00095         IBERRCHK(imesh->load(0, m_MeshFile.c_str(),0), *imesh);
00096         // m_GD = imesh->getGeometricDimension(); Doesn't work !
00097         moab::Range all_elems, all_verts;
00098         MBERRCHK(mb->get_entities_by_dimension(0, 3, all_elems,true),mb);
00099         if (all_elems.size() == 0)
00100             m_GD = 2;
00101         else if (all_elems.size() > 0)
00102             m_GD = 3;
00103         else
00104             exit(0);
00105         all_elems.clear();
00106         m_LogFile << "Geometric dimension of meshfile = "<< m_GD <<std::endl;
00107 
00108         // obtain existing tag handles
00109         moab::Tag GDTag, GIDTag, NTag, MTag; //, STag, FTag, MNTag
00110         MBERRCHK(mb->tag_get_handle("GEOM_DIMENSION", 1, moab::MB_TYPE_INTEGER, GDTag),mb);
00111         MBERRCHK(mb->tag_get_handle("NEUMANN_SET", 1, moab::MB_TYPE_INTEGER, NTag),mb);
00112         MBERRCHK(mb->tag_get_handle("MATERIAL_SET", 1, moab::MB_TYPE_INTEGER, MTag),mb);
00113         MBERRCHK(mb->tag_get_handle("GLOBAL_ID", 1, moab::MB_TYPE_INTEGER, GIDTag),mb);
00114         // create smoothset and fixed tag for mesquite
00115         //        MBERRCHK(mb->tag_get_handle("SMOOTHSET", 1, moab::MB_TYPE_INTEGER, STag,
00116         //                                    moab::MB_TAG_SPARSE|moab::MB_TAG_CREAT),mb);
00117         //        MBERRCHK(mb->tag_get_handle("fixed", 1, moab::MB_TYPE_INTEGER, FTag,
00118         //                                    moab::MB_TAG_SPARSE|moab::MB_TAG_CREAT),mb);
00119         //        MBERRCHK(mb->tag_get_handle("mnode", 1, moab::MB_TYPE_INTEGER, MNTag,
00120         //                                    moab::MB_TAG_SPARSE|moab::MB_TAG_CREAT),mb);
00121 
00122         // get all the entity sets with boundary layer geom dimension, neumann sets and material sets
00123         moab::Range sets, n_sets, m_sets;
00124         m_BLDim = m_GD - 1;
00125 
00126         const void* gdim[] = {&m_BLDim};
00127 
00128         MBERRCHK(mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &GDTag,
00129                                                   gdim, 1 , sets, moab::Interface::INTERSECT, false), mb);
00130         MBERRCHK(mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &NTag, 0, 1 , n_sets),mb);
00131         MBERRCHK(mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &MTag, 0, 1 , m_sets),mb);
00132 
00133         // Handling NeumannSets (if BL surf in input via NS)
00134         moab::Range::iterator set_it;
00135         moab::EntityHandle this_set = 0;
00136         for (set_it = n_sets.begin(); set_it != n_sets.end(); set_it++)  {
00137 
00138             this_set = *set_it;
00139 
00140             // get entity handle of NS specified in the input file
00141             int set_id;
00142             MBERRCHK(mb->tag_get_data(NTag, &this_set, 1, &set_id), mb);
00143             if(set_id == m_NeumannSet)
00144                 break;
00145             this_set = 0;
00146         }
00147         if (debug && m_NeumannSet != -1 && this_set != 0){
00148             m_LogFile <<  "Looking for NS with id " << m_NeumannSet <<
00149                           ". Total NS found are: "<< n_sets.size() << std::endl;
00150         }
00151 
00152         // For specified surface: get the  all the quads and nodes in a range
00153         moab::EntityHandle s1;
00154         moab::Range quads, nodes, fixmat_ents;
00155         int dims; // variable to store global id of boundary layer specified in the input file
00156 
00157         // Method 1: INPUT by NeumannSet
00158         if(m_NeumannSet != -1 && this_set != 0){
00159             MBERRCHK(mb->get_entities_by_dimension(this_set, m_BLDim, quads,true),mb);
00160             if (quads.size() <=0){
00161                 m_LogFile <<  " No quads found, aborting.. " << std::endl;
00162                 exit(0);
00163             }
00164 
00165             if(mb->type_from_handle(*quads.rbegin()) != MBQUAD){
00166                 m_Conn = 4;
00167                 m_BElemNodes = 3;
00168             }
00169 
00170             MBERRCHK(mb->get_adjacencies(quads, 0, false, nodes, moab::Interface::UNION),mb);
00171             if (debug) {
00172                 m_LogFile <<  "Found NeumannSet with id : " << m_NeumannSet <<  std::endl;
00173                 m_LogFile <<  "#Quads in this surface: " << quads.size() << std::endl;
00174                 m_LogFile <<  "#Nodes in this surface: " << nodes.size() << std::endl;
00175                 m_LogFile << "#New nodes to be created:" << m_Intervals*nodes.size() << std::endl;
00176             }
00177         }
00178         // Method 2: INPUT by surface id (geom dimension)
00179         else if (m_SurfId !=-1){
00180             for(moab::Range::iterator rit=sets.begin(); rit != sets.end(); ++rit){
00181                 s1 = *rit;
00182                 MBERRCHK(mb->tag_get_data(GIDTag, &s1, 1, &dims),mb);
00183 
00184                 if(dims == m_SurfId && m_SurfId != -1){
00185                     MBERRCHK(mb->get_entities_by_dimension(s1, m_BLDim, quads,true),mb);
00186                     if (quads.size() <=0){
00187                         m_LogFile <<  " No quads found, aborting.. " << std::endl;
00188                         exit(0);
00189                     }
00190 
00191                     MBERRCHK(mb->get_adjacencies(quads, 0, false, nodes, moab::Interface::UNION),mb);
00192                     if (debug) {
00193                         m_LogFile <<  "Found surface with id : " << m_SurfId <<  std::endl;
00194                         m_LogFile <<  "#Quads in this surface: " << quads.size() << std::endl;
00195                         m_LogFile <<  "#Nodes in this surface: " << nodes.size() << std::endl;
00196                         m_LogFile << "#New nodes to be created:" << m_Intervals*nodes.size() << std::endl;
00197                     }
00198                 }
00199             }
00200         }
00201 
00202         if (quads.size() == 0 || nodes.size() == 0) {
00203             m_LogFile <<  "Invalid boundary layer specification, aborting.." <<  std::endl;
00204             exit(0);
00205         }
00206 
00207         // set fixed tag on all the BL nodes
00208         //        MBERRCHK(mb->get_entities_by_dimension(0, 0, all_verts, true),mb);
00209         //        std::vector<int> all_node_data(all_verts.size(), 0);
00210         //        MBERRCHK(mb->tag_set_data(FTag, all_verts, &all_node_data[0]), mb);
00211 
00212         // Handling MaterialSet
00213         moab::Range::iterator mset_it;
00214         moab::EntityHandle mthis_set;
00215         int mset_id = 0, found = 0;
00216         for (mset_it = m_sets.begin(); mset_it != m_sets.end(); mset_it++)  {
00217 
00218             mthis_set = *mset_it;
00219 
00220             // get entity handle of MS specified in the input file
00221             MBERRCHK(mb->tag_get_data(MTag, &mthis_set, 1, &mset_id), mb);
00222             if(mset_id == m_Material){
00223                 found = 1;
00224                 break;
00225             }
00226             else if(mset_id == fixmat){
00227                 MBERRCHK(mb->get_entities_by_dimension(mthis_set, m_GD, fixmat_ents ,true),mb);
00228             }
00229 
00230 
00231             //            // get all the nodes in the material and tag bl nodes
00232             //            moab::Range mat_nodes, mat_hexes;
00233             //            if(m_GD == 3)
00234             //              MBERRCHK(mb->get_entities_by_type(mthis_set, moab::MBHEX, mat_hexes, true), mb);
00235             //            MBERRCHK(mb->get_adjacencies(mat_hexes, 0, false, mat_nodes, Interface::UNION), mb);
00236 
00237             //            moab::Range mat_b_nodes = intersect(nodes, mat_nodes);
00238             //            std::cout << "MAT NO:" << mset_id << " has " << mat_hexes.size() << "HEXES " <<  mat_nodes.size() << "NODES AND "
00239             //                      << mat_b_nodes.size() << " NODES ON BOUNDARY" << std::endl;
00240 
00241             //            std::vector<int> bl_node_data(mat_b_nodes.size(), 0);
00242             //            std::vector<int> node_tag_data(mat_b_nodes.size(),-1);
00243             //            // don't error check, as it is supposed to give error when multiple material case is encountered
00244             //            mb->tag_get_data(MNTag, mat_b_nodes, &node_tag_data[0]);
00245             //            for(int i=0; i<mat_b_nodes.size(); i++){
00246             //                std::cout << node_tag_data[i] << std::endl;
00247             //                // already a part of some material
00248             //                if(node_tag_data[i] != -1){
00249             //                    bl_node_data[i] = node_tag_data[i]+1;
00250             //                  }
00251             //              }
00252             //            MBERRCHK(mb->tag_set_data(MNTag, mat_b_nodes, &bl_node_data[0]), mb);
00253             //            mat_hexes.clear();
00254             //            mat_b_nodes.clear();
00255             //            mat_nodes.clear();
00256             mthis_set = 0;
00257         }
00258         // get tag data and print
00259         //        std::vector<int> all_bl(nodes.size(),-100);
00260         //        mb->tag_get_data(MNTag, nodes, &all_bl[0]);
00261         //        for(int i=0; i<nodes.size(); i++){
00262         //            std::cout << " Node " << i << " tag value " << all_bl[i] << std::endl;
00263         //          }
00264         if(found == 1 && m_Material !=999){
00265             m_LogFile << "Found material set with id " << m_Material << std::endl;
00266         }
00267         else{
00268             // No material set found, creating material set 999 for BL elements
00269             m_LogFile << "Creating material set with id " << m_Material << std::endl;
00270             MBERRCHK(mb->create_meshset(moab::MESHSET_SET, mthis_set, 1), mb);
00271             MBERRCHK(mb->tag_set_data(MTag, &mthis_set, 1, &m_Material), mb);
00272         }
00273 
00274         //        // placeholder for storing smoothing entities
00275         //        moab::EntityHandle smooth_set;
00276         //        int s_id = 100;
00277         //        MBERRCHK(mb->create_meshset(moab::MESHSET_SET, smooth_set, 1), mb);
00278         //        MBERRCHK(mb->tag_set_data(STag, &smooth_set, 1, &s_id), mb);
00279 
00280         // placeholder for storing gd on new entities
00281         moab::EntityHandle geom_set;
00282         MBERRCHK(mb->create_meshset(moab::MESHSET_SET, geom_set, 1), mb);
00283         MBERRCHK(mb->tag_set_data(GDTag, &geom_set, 1, &m_GD), mb);
00284 
00285         // declare variables before starting BL creation
00286         std::vector <bool> node_status(false); // size of verts of bl surface
00287         node_status.resize(nodes.size());
00288         moab::Range edges, hexes, hex_edge, quad_verts;
00289         double coords_bl_quad[3], coords_new_quad[3], xdisp = 0.0, ydisp = 0.0, zdisp = 0.0;
00290         moab::EntityHandle hex, hex1;
00291         int qcount = 0;
00292 
00293         //size of the following is based on element type
00294         std::vector<moab::EntityHandle> conn, qconn, adj_qconn, tri_conn,
00295                 new_vert(m_Intervals*nodes.size()), old_hex_conn, adj_hexes, adj_quads, adj_hex_nodes1;
00296         moab::CartVect surf_normal(3);
00297 
00298         // Now start creating New elements
00299         for (Range::iterator kter = quads.begin(); kter != quads.end(); ++kter){
00300             qcount++;
00301 
00302             if (debug){
00303                 m_LogFile <<  "\n\n*** QUAD: " << qcount << std::endl;
00304             }
00305 
00306             std::vector<moab::EntityHandle> old_hex;
00307             MBERRCHK(mb->get_adjacencies(&(*kter), 1, m_GD, false, old_hex),mb);
00308             if((int) old_hex.size() == 0){
00309                 m_LogFile << "unable to find adjacent hex for BL quad, aborting...";
00310                 exit(0);
00311             }
00312 
00313             // if fixmat specified, filter old hex, we don't have to correct both sides of the boundary
00314             if (fixmat !=0 && (int) old_hex.size() > 1){
00315                 moab::EntityHandle old_hex_set;
00316                 MBERRCHK(mb->create_meshset(moab::MESHSET_SET, old_hex_set, 1), mb);
00317                 MBERRCHK(mb->add_entities(old_hex_set,&old_hex[0], (int) old_hex.size()), mb);
00318                 // TODO: Find a faster way of doing this
00319                 MBERRCHK(mb->remove_entities(old_hex_set, fixmat_ents), mb);
00320                 old_hex.clear();
00321                 old_hex.empty();
00322                 MBERRCHK(mb->get_entities_by_dimension(old_hex_set, m_GD, old_hex), mb);
00323             }
00324             // allocate space for connectivity/adjacency during the first pass of this loop
00325             if(qcount ==1){
00326                 if(mb->type_from_handle(old_hex[0]) == MBHEX){
00327                     m_Conn = 8;
00328                     m_BElemNodes = 4;
00329                     m_HConn = 8;
00330                     //allocating based on element type
00331                     conn.resize(m_Intervals*m_Conn), qconn.resize(m_BElemNodes), adj_qconn.resize(m_BElemNodes),
00332                             old_hex_conn.resize(m_Conn), adj_hex_nodes1.resize(m_Conn);
00333                 }
00334                 else if(mb->type_from_handle(old_hex[0]) == MBTET){
00335                     m_Conn = 4;
00336                     m_HConn = 6;
00337                     m_BElemNodes = 3;
00338                     //allocating based on element type - thrice the number of elements
00339                     if(hybrid)
00340                         conn.resize(m_Intervals*6);
00341                     else
00342                         conn.resize(2*m_Intervals*m_Conn);
00343                     qconn.resize(m_BElemNodes), adj_qconn.resize(m_BElemNodes),
00344                             old_hex_conn.resize(m_Conn), adj_hex_nodes1.resize(m_Conn);
00345                 }
00346                 else if(mb->type_from_handle(old_hex[0]) == MBQUAD){
00347                     m_Conn = 4;
00348                     m_HConn = 4;
00349                     m_BElemNodes = 2;
00350                     //allocating based on element type
00351                     conn.resize(m_Intervals*m_Conn), qconn.resize(m_BElemNodes), adj_qconn.resize(m_BElemNodes),
00352                             old_hex_conn.resize(m_Conn), adj_hex_nodes1.resize(m_Conn);
00353                 }
00354                 else if(mb->type_from_handle(old_hex[0]) == MBTRI){
00355                     m_Conn = 3;
00356                     m_HConn = 4;
00357                     m_BElemNodes = 2;
00358                     //allocating based on element type - twice the number of elements
00359                     if(hybrid){
00360                         m_HConn = 4;
00361                         conn.resize(m_Intervals*m_HConn);
00362                     }
00363                     else{
00364                         tri_conn.resize(2*m_Intervals*m_Conn);
00365                         conn.resize(2*m_Intervals*m_Conn);
00366                     }
00367                     qconn.resize(m_BElemNodes), adj_qconn.resize(m_BElemNodes),
00368                             old_hex_conn.resize(m_Conn), adj_hex_nodes1.resize(m_Conn);
00369                 }
00370                 else if(m_Conn == 0 || m_BElemNodes == 0){
00371                     m_LogFile << "MeshType is not supported by this tool" << std::endl;
00372                     exit(0);
00373                 }
00374             }
00375             qconn.clear();
00376             old_hex_conn.clear();
00377             MBERRCHK(mb->get_connectivity(&(*kter), 1, qconn),mb);
00378             MBERRCHK(mb->get_connectivity(&old_hex[0], 1, old_hex_conn),mb);
00379 
00380             // get the normal to the plane of the 2D mesh
00381             if(m_GD==2 && qcount == 1)
00382                 get_normal_quad (old_hex_conn, surf_normal);
00383             for (int i=0; i<m_BElemNodes; i++){
00384                 MBERRCHK(mb->get_coords(&qconn[i], 1, coords_bl_quad),mb);
00385 
00386                 // check to see if this node is already dealt with
00387                 int blNodeId = 0;
00388                 for(int n=0; n< (int) nodes.size(); n++){
00389                     if(nodes[n] == qconn[i]){
00390                         blNodeId = n;
00391                         break;
00392                     }
00393                     else if(n == (int) nodes.size()){
00394                         m_LogFile << "QUAD doesn't have a node in BL NODES, aborting.." << std::endl;
00395                         exit(0);
00396                     }
00397                 }
00398                 if (debug){
00399                     m_LogFile <<  "\n*Working on Node: " << blNodeId << " coords: " << coords_bl_quad[0]
00400                                << ", " << coords_bl_quad[1] << ", " << coords_bl_quad[2]  << std::endl;
00401                 }
00402                 double temp;
00403                 //create new nodes
00404                 if(node_status[blNodeId] == false){
00405                     adj_hexes.clear();
00406                     MBERRCHK(mb->get_adjacencies(&qconn[i], 1, m_GD, false, adj_hexes, moab::Interface::UNION), mb);
00407                     MBERRCHK(mb->get_adjacencies(&qconn[i], 1, m_BLDim, false, adj_quads, moab::Interface::UNION), mb);
00408 
00409                     // if fixmat specified, filter old hex, we don't have to correct both sides of the boundary
00410                     if (fixmat !=0 && (int) adj_hexes.size() > 1){
00411                         moab::EntityHandle adj_hex_set;
00412                         MBERRCHK(mb->create_meshset(moab::MESHSET_SET, adj_hex_set, 1), mb);
00413                         MBERRCHK(mb->add_entities(adj_hex_set,&adj_hexes[0], (int) adj_hexes.size()), mb);
00414                         MBERRCHK(mb->remove_entities(adj_hex_set, fixmat_ents), mb);
00415                         adj_hexes.clear();
00416                         adj_hexes.empty();
00417                         MBERRCHK(mb->get_entities_by_dimension(adj_hex_set, m_GD, adj_hexes), mb);
00418                     }
00419 
00420                     int side_number = 0, sense = 1, offset = 0;
00421                     MBERRCHK(mb->side_number(old_hex[0], (*kter), side_number, sense, offset), mb);
00422 
00423                     moab::CartVect rt(0.0, 0.0, 0.0), v(3);
00424                     moab::Range adj_qconn_r;
00425                     // TODO: Add feature to add element on both sides of the boundary layer
00426                     // find the normal direction where new nodes are to be created - xdisp, ydisp and zdisp
00427                     for (int q=0; q < (int) quads.size(); q++){
00428                         for(int r=0; r < (int) adj_quads.size(); r++){
00429                             if (adj_quads[r] == quads[q]){
00430                                 // it's a BL quad, get the normal and prepare to compute average
00431                                 MBERRCHK(mb->get_connectivity(&adj_quads[r], 1, adj_qconn),mb);
00432                                 if(m_GD==3){
00433                                     get_normal_quad (adj_qconn, v);
00434                                     if (sense == -1)
00435                                         v=-v;
00436                                 }
00437                                 else if(m_GD==2){
00438                                     if(sense == 1)
00439                                         get_normal_edge(adj_qconn, surf_normal, v);
00440                                     else
00441                                         get_normal_edge(adj_qconn, -surf_normal, v);
00442                                 }
00443                                 //TODO: Check to make sure that normal is inwards
00444                                 rt = rt + v;
00445                                 xdisp=rt[0]/rt.length();
00446                                 ydisp=rt[1]/rt.length();
00447                                 zdisp=rt[2]/rt.length();
00448                             }
00449                             else{
00450                                 // it's not a BL quad, instead of shooting the normal find the max. BL distance allowable
00451                                 if(check_bl_edge_length){
00452                                     MBERRCHK(mb->get_connectivity(&adj_quads[r],1,adj_qconn_r), mb);
00453                                     find_min_edge_length(adj_qconn_r, qconn[i], nodes, m_MinEdgeLength);
00454                                 }
00455                             }
00456                             adj_qconn_r.clear();
00457                         }
00458                     }
00459                     // TODO: shoot normal in direction xdisp, yd.. from point coords_bl_quad
00460                     // and find the point of intersection and distance with existing mesh
00461                     // range nodes, coords_bl_quad and the nodes of the hex of interest here is old_hex_conn
00462 
00463                     // Half check of thickness validity
00464                     if(m_Thickness > m_MinEdgeLength && m_MinEdgeLength > 0){
00465                         // This BL creation might fail
00466                         m_LogFile << "Specified thickess is " << m_Thickness
00467                                   << " and BL elements edge length is " << m_MinEdgeLength
00468                                   << "  BL creation might fail, "
00469                                   << "\n Set check_bl_edge_length to false to avoid this check, aborting.. " << std::endl;
00470                         exit(0);
00471                     }
00472 
00473 
00474                     adj_quads.clear();
00475                     double num = m_Thickness*(m_Bias-1)*(pow(m_Bias, m_Intervals -1));
00476                     double deno = pow(m_Bias, m_Intervals) - 1;
00477                     if (deno !=0)
00478                         temp = num/deno;
00479                     else
00480                         temp = m_Thickness/m_Intervals;
00481 
00482                     // created BL nodes
00483                     double move = 0.0;
00484                     for(int j=0; j< m_Intervals; j++){
00485 
00486                         move+= temp/pow(m_Bias,j);
00487                         if (debug){
00488                             m_LogFile <<  " move:" << move;
00489                         }
00490                         // now compute the coords of the new vertex
00491                         coords_new_quad[0] = coords_bl_quad[0]-move*xdisp;
00492                         coords_new_quad[1] = coords_bl_quad[1]-move*ydisp;
00493                         coords_new_quad[2] = coords_bl_quad[2]-move*zdisp;
00494 
00495                         int nid = blNodeId*m_Intervals+j;
00496                         // Possible TODO's
00497                         //TODO: Check if this vertex is possible (detect possible collision with geometry)
00498                         // TODO: See posibility of using ray tracing
00499                         // TODO: Parallize: Profile T-junction model and try to device an algorithm
00500                         // TODO: Modularize node creation part and use doxygen for all code and design of code, python design and test cases - current functions in code:
00501                         // Setup this, Execute this -- break info sub functions and classes,
00502                         // prepareIO --make this optional when using python,
00503                         // get normal (2d and 3d) -- can be combined to one function
00504                         // get det jacobian (hex elements) --needs check for other elements
00505                         //
00506                         MBERRCHK(mb->create_vertex(coords_new_quad, new_vert[nid]), mb);
00507                         if (debug){
00508                             m_LogFile << std::setprecision (3) << std::scientific << " : created node:" << (nid + 1)
00509                                       << " of " << new_vert.size() << " new nodes:- coords: " << coords_new_quad[0]
00510                                       << ", " << coords_new_quad[1] << ", " << coords_new_quad[2]  << std::endl;
00511                         }
00512                     }
00513                     node_status[blNodeId] = true;
00514                 }
00515 
00516                 //populate the connectivity after creating nodes for this BL node
00517                 for(int j=0; j< m_Intervals; j++){
00518                     if(m_Conn == 8 && m_BElemNodes == 4){
00519                         int nid = blNodeId*m_Intervals+j;
00520                         if(j==0) // set connectivity of boundary layer hex
00521                             conn[m_Conn*j + i+m_BElemNodes] = qconn[i];
00522                         else
00523                             conn[m_Conn*j + i+m_BElemNodes] = new_vert[nid-1];
00524                         conn[m_Conn*j +i] = new_vert[nid];
00525                     }
00526                     else if(m_Conn == 4 && m_BElemNodes == 2){
00527                         int nid = blNodeId*m_Intervals+j;
00528                         if(j==0) // set connectivity of boundary layer hex
00529                             conn[m_Conn*j + i+m_BElemNodes] = qconn[m_BElemNodes-i-1];
00530                         else
00531                             conn[m_Conn*j + m_BElemNodes + 1 - i] = new_vert[nid-1];
00532                         conn[m_Conn*j +i] = new_vert[nid];
00533                     }
00534                     else if(m_Conn == 4 && m_BElemNodes == 3 && hybrid == true){ // make wedges aka prisms for tet mesh
00535                         int nid = blNodeId*m_Intervals+j;
00536                         if(j==0) // set connectivity of boundary layer hex
00537                             conn[m_HConn*j + i+m_BElemNodes] = qconn[i];
00538                         else
00539                             conn[m_HConn*j + i+m_BElemNodes] = new_vert[nid-1];
00540                         conn[m_HConn*j +i] = new_vert[nid];
00541                     }
00542                     else if(m_Conn == 3 && m_BElemNodes == 2){ // make quads for tri mesh
00543                         int nid = blNodeId*m_Intervals+j;
00544                         if(j==0) // set connectivity of boundary layer hex
00545                             conn[m_HConn*j + i+m_BElemNodes] = qconn[m_BElemNodes-i-1];
00546                         else
00547                             conn[m_HConn*j + m_BElemNodes + 1 - i] = new_vert[nid-1];
00548                         conn[m_HConn*j +i] = new_vert[nid];
00549                     }
00550 
00551                     // Another block for setting up fixed tag for smoothing using Mesquite
00552                     //                    int fix0 = 0;
00553                     //                    int nid = blNodeId*m_Intervals+j;
00554                     //  MBERRCHK(mb->tag_set_data(FTag, &new_vert[nid], 1, &fix0), mb);
00555                 }
00556 
00557                 // if a hex does have a quad on BL, but, has a node or edge on the boundary layer
00558                 for(int k=0; k < (int) adj_hexes.size(); k++){
00559                     adj_hex_nodes1.clear();
00560                     MBERRCHK(mb->get_connectivity(&adj_hexes[k], 1, adj_hex_nodes1), mb);
00561                     std::vector<EntityHandle> inodes;
00562                     int var = 0;
00563                     for(int n = 0; n < (int) nodes.size(); n++){
00564                         for(int m = 0; m < m_Conn; m++){
00565                             if(nodes[n] == adj_hex_nodes1[m]){
00566                                 inodes.push_back(adj_hex_nodes1[m]);
00567                                 var++;
00568                             }
00569                         }
00570                     }
00571                     // doesn't have a quad or when inodes is 0 it mean this is a newly created hex
00572                     if((int) inodes.size() != m_BElemNodes && (int) inodes.size() != 0){
00573                         if(debug){
00574                             m_LogFile << "Hex on BL surface is connected by a node or edge" <<
00575                                          "\n nodes on BL - " << inodes.size() << std::endl;
00576                         }
00577                         // mark this hex and set it's connectivity later
00578                         for(int p = 0; p < m_Conn; p++){
00579                             if(qconn[i] == adj_hex_nodes1[p]){
00580                                 adj_hex_nodes1[p] = conn[m_HConn*(m_Intervals-1)+i];
00581                             }
00582                         }
00583                         // check to see if this node position change also changes lower dimension entities
00584                         std::vector<EntityHandle> adj1, adj2;
00585                         EntityHandle one = qconn[i];
00586                         EntityHandle two = adj_hexes[k];
00587                         std::vector<EntityHandle> from_entities;
00588                         from_entities.push_back(one);
00589                         from_entities.push_back(two);
00590                         if(m_BLDim == 2){
00591                             MBERRCHK(mb->get_adjacencies(&from_entities[0], 2, 1, false, adj1), mb);
00592                             MBERRCHK(mb->delete_entities(&adj1[0], (int) adj1.size()), mb);
00593                         }
00594                         MBERRCHK(mb->get_adjacencies(&from_entities[0], 2, m_BLDim, false, adj2), mb);
00595                         MBERRCHK(mb->delete_entities(&adj2[0], (int) adj2.size()), mb);
00596                         MBERRCHK(mb->set_connectivity(adj_hexes[k], &adj_hex_nodes1[0], m_Conn), mb);
00597                     }
00598                     double j_ahex = 0.0;
00599                     get_det_jacobian(adj_hex_nodes1, 0, j_ahex);
00600                     // mark entities for smoothing
00601                     //         MBERRCHK(mb->add_entities(smooth_set, &adj_hexes[k], 1), mb);
00602                     inodes.clear();
00603                 }
00604             } // Loop thru BL element nodes ends
00605 
00606             //TODO: Set Connectivity of tet's, break prisms into 3 tets, Another loop is required.
00607             if(m_Conn == 3 && m_BElemNodes == 2 && hybrid == false){
00608                 for(int c=0; c<m_Intervals; c++){
00609                     if(tri_sch == 1){
00610                         // lower triangle
00611                         tri_conn[m_Conn*c*2] =     conn[c*m_HConn];
00612                         tri_conn[m_Conn*c*2 + 1] = conn[c*m_HConn + 1];
00613                         tri_conn[m_Conn*c*2 + 2] = conn[c*m_HConn + 3];
00614                         // upper triangle
00615                         tri_conn[m_Conn*c*2 + 3] = conn[c*m_HConn + 1];
00616                         tri_conn[m_Conn*c*2 + 4] = conn[c*m_HConn + 2];
00617                         tri_conn[m_Conn*c*2 + 5] = conn[c*m_HConn + 3];
00618                     }
00619                     else if(tri_sch == 2){
00620                         // lower triangle
00621                         tri_conn[m_Conn*c*2] =     conn[c*m_HConn];
00622                         tri_conn[m_Conn*c*2 + 1] = conn[c*m_HConn + 1];
00623                         tri_conn[m_Conn*c*2 + 2] = conn[c*m_HConn + 2];
00624                         // upper triangle
00625                         tri_conn[m_Conn*c*2 + 3] = conn[c*m_HConn + 2];
00626                         tri_conn[m_Conn*c*2 + 4] = conn[c*m_HConn + 3];
00627                         tri_conn[m_Conn*c*2 + 5] = conn[c*m_HConn];
00628                     }
00629                 }
00630             }
00631 
00632             if (debug)
00633             {
00634                 m_LogFile <<  "\nsetting connectivity of the old BL hex " << std::endl;
00635             }
00636             // First replace BL nodes (part of old hex) with newly created nodes, then set connectivity of the old_hex
00637             // deleting old connectivities
00638             //TODO: Check to see if this step can be avoided for some cases
00639             for(int p=0; p<m_Conn; p++){
00640                 for(int q=0; q<m_BElemNodes; q++){
00641                     if (old_hex_conn[p] == qconn[q]){
00642                         old_hex_conn[p] = conn[m_HConn*(m_Intervals-1) + q];
00643                         // check to see if this node position change also changes lower dimension entities
00644                         std::vector<EntityHandle> adj1, adj2;
00645                         EntityHandle one = qconn[q];
00646                         EntityHandle two = old_hex[0];
00647                         std::vector<EntityHandle> from_entities;
00648                         from_entities.push_back(one);
00649                         from_entities.push_back(two);
00650                         if(m_BLDim == 2){
00651                             MBERRCHK(mb->get_adjacencies(&from_entities[0], 2, 1, false, adj1), mb);
00652                             MBERRCHK(mb->delete_entities(&adj1[0], (int) adj1.size()), mb);
00653                         }
00654                         MBERRCHK(mb->get_adjacencies(&from_entities[0], 2, m_BLDim, false, adj2), mb);
00655                         MBERRCHK(mb->delete_entities(&adj2[0], (int) adj2.size()), mb);
00656                     }
00657                 }
00658             }
00659             double j_old_hex = 0.0;
00660             get_det_jacobian(old_hex_conn, 0, j_old_hex);
00661             MBERRCHK(mb->set_connectivity(old_hex[0], &old_hex_conn[0], m_Conn), mb);
00662             old_hex.clear();
00663 
00664             // mark entities for smoothing
00665             //        MBERRCHK(mb->add_entities(smooth_set, &old_hex[0], 1), mb);
00666 
00667             if (debug){
00668                 m_LogFile <<  "creating new boundary layer hexes" << std::endl;
00669             }
00670             // create boundary layer hexes
00671             for(int j=0; j< m_Intervals; j++){
00672                 double j_hex = 0.0;
00673                 get_det_jacobian(conn, j*m_Conn, j_hex);
00674                 if(m_Conn == 8){
00675                     MBERRCHK(mb->create_element(MBHEX, &conn[j*m_Conn], m_Conn, hex),mb);
00676                 }
00677                 else if(m_Conn==4 && m_GD ==3 && hybrid == true){
00678                     MBERRCHK(mb->create_element(MBPRISM, &conn[j*6], 6, hex),mb);
00679                 }
00680                 else if(m_Conn==4 && m_GD ==2){
00681                     MBERRCHK(mb->create_element(MBQUAD, &conn[j*m_Conn], m_Conn, hex),mb);
00682                 }
00683                 else if(m_Conn==3 && m_GD ==2 && hybrid == true){
00684                     MBERRCHK(mb->create_element(MBQUAD, &conn[j*m_HConn], m_HConn, hex),mb);
00685                 }
00686                 else if(m_Conn==3 && m_GD ==2 && hybrid == false){
00687                     MBERRCHK(mb->create_element(MBTRI, &tri_conn[j*m_Conn*2], m_Conn, hex),mb);
00688                     MBERRCHK(mb->create_element(MBTRI, &tri_conn[j*m_Conn*2+3], m_Conn, hex1),mb);
00689                     MBERRCHK(mb->add_entities(mthis_set, &hex1, 1), mb);
00690                     //        MBERRCHK(mb->add_entities(smooth_set, &hex1, 1), mb);
00691                 }
00692                 // add this hex to a block
00693                 MBERRCHK(mb->add_entities(mthis_set, &hex, 1), mb);
00694                 // mark entities for smoothing
00695                 //                MBERRCHK(mb->add_entities(smooth_set, &hex, 1), mb);
00696                 // add geom dim tag
00697                 MBERRCHK(mb->add_entities(geom_set, &hex, 1), mb);
00698                 // TODO: Add Local Smooting
00699             }
00700         } // Loop thru quads ends
00701 
00702         // TODO: Global smoothing works after PostBL step; make global smoothing available as an option inside
00703         // get the skin of the entities
00704         //        moab::Range skin_verts;
00705         //        all_elems.clear();
00706         //        MBERRCHK(mb->get_entities_by_dimension(0, 3, all_elems,true),mb);
00707 
00708         //        moab::Skinner skinner(mb);
00709         //        skinner.find_skin(all_elems, 0, skin_verts);
00710 
00711         //        m_LogFile << "setting 'fixed'' tag = 1 on verts in the skin = " <<  skin_verts.size() << std::endl;
00712 
00713         //        // set fixed tag = 1 on all skin verts
00714         //        std::vector<int> all_skin_data(skin_verts.size(), 1);
00715         //        MBERRCHK(mb->tag_set_data(FTag, skin_verts, &all_skin_data[0]), mb);
00716 
00717         m_LogFile << "\nTotal Jacobian calls/Min/Max: " << m_JacCalls << ", " << m_JLo << ", " << m_JHi << std::endl;
00718 
00719         // save the final boundary layer mesh
00720         MBERRCHK(mb->write_mesh(m_OutFile.c_str()),mb);
00721         m_LogFile <<  "\n\nWrote Mesh File: " << m_OutFile << std::endl;
00722         // get the current date and time
00723         Timer.GetDateTime (szDateTime);
00724         m_LogFile << "Ending at : " << szDateTime;
00725         // report/compute the elapsed time
00726         m_LogFile <<  "Elapsed wall clock time: " << Timer.DiffTime ()
00727                    << " seconds or " << (Timer.DiffTime ())/60.0 << " mins\n";
00728         m_LogFile <<  "Total CPU time used: " << (double) (clock() - sTime)/CLOCKS_PER_SEC \
00729                    << " seconds" << std::endl;
00730     }
00731     else{
00732         Algo2();
00733     }
00734 }
00735 
00736 void PostBL::PrepareIO (int argc, char *argv[], std::string  TestDir)
00737 // ---------------------------------------------------------------------------
00741 // ---------------------------------------------------------------------------
00742 {
00743     // set and open input output files
00744     bool bDone = false;
00745     do{
00746         if (2 == argc) {
00747             m_InputFile = argv[1];
00748             m_LogName = m_InputFile + ".log";
00749         }
00750         else if (1 == argc){
00751             m_LogFile << "\nRunning default case:\n" << std::endl;
00752 
00753             m_InputFile = TestDir + "/" + (char *)DEFAULT_TEST_POSTBL;
00754             m_LogName = m_InputFile + ".log";
00755         }
00756 
00757         // open input file for reading
00758         m_FileInput.open (m_InputFile.c_str(), std::ios::in);
00759         if (!m_FileInput){
00760             m_LogFile << "Unable to open file: " << m_InputFile << std::endl;
00761             m_FileInput.clear ();
00762             exit(1);
00763         }
00764         else
00765             bDone = true; // file opened successfully
00766 
00767         // open the log file for dumping debug/output statements
00768         m_LogFile.coss.open (m_LogName.c_str(), std::ios::out);
00769         if (!m_LogFile.coss){
00770             m_LogFile <<  "Unable to open file: " << m_LogName << std::endl;
00771             m_LogFile.coss.clear ();
00772             exit(1);
00773         }
00774         else
00775             bDone = true; // file opened successfully
00776         m_LogFile <<  '\n';
00777         m_LogFile <<  "\t\t---------------------------------------------------------" << '\n';
00778         m_LogFile <<  "\t\t         Tool to generate Post-mesh Boundary Layers      " << '\n';
00779         m_LogFile <<  "\t\t\t\tArgonne National Laboratory" << '\n';
00780         m_LogFile <<  "\t\t\t\t        2012         " << '\n';
00781         m_LogFile <<  "\t\t---------------------------------------------------------" << '\n';
00782         m_LogFile <<  "\nsee README file for using the program and details on various cards.\n"<< std::endl;
00783 
00784     }while (!bDone);
00785 
00786     // Get the meshfile name, surface(s), thickness, intervals and bias
00787     CParser Parse;
00788 
00789     // count the total number of cylinder commands in each pincellh
00790     for(;;){
00791         if (!Parse.ReadNextLine (m_FileInput, m_nLineNumber, szInputString,
00792                                  MAXCHARS, szComment))
00793             IOErrorHandler (INVALIDINPUT);
00794 
00795         // Get tri scheme
00796         if (szInputString.substr(0,9) == "trischeme"){
00797             std::istringstream szFormatString (szInputString);
00798             szFormatString >> m_Card >> tri_sch;
00799             if(szFormatString.fail())
00800                 IOErrorHandler(INVALIDINPUT);
00801             m_LogFile <<  m_Card << " name read: "<< tri_sch << std::endl;
00802         }
00803         // Get hybrid
00804         if (szInputString.substr(0,6) == "hybrid"){
00805             std::istringstream szFormatString (szInputString);
00806             szFormatString >> m_Card >> hybrid;
00807             if(szFormatString.fail())
00808                 IOErrorHandler(INVALIDINPUT);
00809             m_LogFile <<  m_Card << " name read: "<< hybrid << std::endl;
00810         }
00811         // Get hybrid
00812         if (szInputString.substr(0,6) == "fixmat"){
00813             std::istringstream szFormatString (szInputString);
00814             szFormatString >> m_Card >> fixmat;
00815             if(szFormatString.fail())
00816                 IOErrorHandler(INVALIDINPUT);
00817             m_LogFile <<  m_Card << " name read: "<< fixmat << std::endl;
00818         }
00819         // Get MeshFile name
00820         if (szInputString.substr(0,8) == "meshfile"){
00821             std::istringstream szFormatString (szInputString);
00822             szFormatString >> m_Card >> m_MeshFile;
00823             if(szFormatString.fail())
00824                 IOErrorHandler(INVALIDINPUT);
00825             m_LogFile <<  m_Card << " name read: "<< m_MeshFile << std::endl;
00826             if (argc == 1){
00827                 m_MeshFile = TestDir + "/" + m_MeshFile;
00828             }
00829         }
00830         // Get BL surface
00831         if (szInputString.substr(0,8) == "surfaces"){
00832             std::istringstream szFormatString (szInputString);
00833             szFormatString >> m_Card >> m_SurfId;
00834             if(m_SurfId < 0 || szFormatString.fail())
00835                 IOErrorHandler(INVALIDINPUT);
00836             m_LogFile <<  m_Card << " read: "<< m_SurfId <<std::endl;
00837         }
00838         // Get BL surface via neumann set or sideset
00839         if (szInputString.substr(0,10) == "neumannset"){
00840             std::istringstream szFormatString (szInputString);
00841             szFormatString >> m_Card >> m_NeumannSet;
00842             if(m_NeumannSet < 0 || szFormatString.fail())
00843                 IOErrorHandler(INVALIDINPUT);
00844             m_LogFile <<  m_Card << " read: "<< m_NeumannSet <<std::endl;
00845         }
00846         // Get BL material (block) number
00847         if (szInputString.substr(0,8) == "material"){
00848             std::istringstream szFormatString (szInputString);
00849             szFormatString >> m_Card >> m_Material;
00850             if(m_Material < 0 || szFormatString.fail())
00851                 IOErrorHandler(INVALIDINPUT);
00852             m_LogFile <<  m_Card << " read: "<< m_Material <<std::endl;
00853         }
00854 
00855         // Get thickness
00856         if (szInputString.substr(0,9) == "thickness"){
00857             std::istringstream szFormatString (szInputString);
00858             szFormatString >> m_Card >> m_Thickness;
00859             if(m_Thickness < 0 || szFormatString.fail())
00860                 IOErrorHandler(INVALIDINPUT);
00861             m_LogFile <<  m_Card << " read: "<< m_Thickness <<std::endl;
00862         }
00863         // Get intervals
00864         if (szInputString.substr(0,9) == "intervals"){
00865             std::istringstream szFormatString (szInputString);
00866             szFormatString >> m_Card >> m_Intervals;
00867             if(m_Intervals < 0 || szFormatString.fail())
00868                 IOErrorHandler(INVALIDINPUT);
00869             m_LogFile <<  m_Card << " read: "<< m_Intervals <<std::endl;
00870         }
00871         // Get bias
00872         if (szInputString.substr(0,4) == "bias"){
00873             std::istringstream szFormatString (szInputString);
00874             szFormatString >> m_Card >> m_Bias;
00875             if(m_Bias < 0 || szFormatString.fail())
00876                 IOErrorHandler(INVALIDINPUT);
00877             m_LogFile <<  m_Card << " read: "<< m_Bias <<std::endl;
00878         }
00879         // Output file name
00880         if (szInputString.substr(0,7) == "outfile"){
00881             std::istringstream szFormatString (szInputString);
00882             szFormatString >> m_Card >> m_OutFile;
00883             if(szFormatString.fail())
00884                 IOErrorHandler(INVALIDINPUT);
00885             m_LogFile <<  m_Card << " name read: "<< m_OutFile <<std::endl;
00886         }
00887         // Debug flag
00888         if (szInputString.substr(0,5) == "debug"){
00889             std::istringstream szFormatString (szInputString);
00890             szFormatString >> m_Card >> debug;
00891             if(szFormatString.fail())
00892                 IOErrorHandler(INVALIDINPUT);
00893             m_LogFile <<  m_Card << " name read: "<< debug <<std::endl;
00894         }
00895         if (szInputString.substr(0,3) == "end"){
00896             break;
00897         }
00898     }
00899 }
00900 
00901 void PostBL::IOErrorHandler (ErrorStates ECode) const
00902 // ---------------------------------------------------------------------------
00906 // ---------------------------------------------------------------------------
00907 {
00908     std::cerr << '\n';
00909     if (ECode == INVALIDINPUT) // invalid input
00910         std::cerr << "Invalid input.";
00911     else
00912         std::cerr << "Unknown error ...?";
00913 
00914     std::cerr << '\n' << "Error in input file line : " << m_nLineNumber;
00915     std::cerr << std::endl;
00916     exit (1);
00917 }
00918 
00919 void PostBL::get_normal_quad (std::vector<EntityHandle>conn, moab::CartVect &v)
00920 // ---------------------------------------------------------------------------
00924 // ---------------------------------------------------------------------------
00925 {
00926     moab::CartVect coords[3];
00927     MBERRCHK(mb->get_coords(&conn[0], 3, (double*) &coords[0]), mb);
00928     moab::CartVect AB(coords[1] - coords[0]);
00929     moab::CartVect BC(coords[2] - coords[1]);
00930     moab::CartVect normal = AB*BC;
00931     normal = normal/normal.length();
00932     v = normal;
00933 }
00934 
00935 void PostBL::get_normal_edge (std::vector<EntityHandle>conn, moab::CartVect BC, moab::CartVect &v)
00936 // ---------------------------------------------------------------------------
00940 // ---------------------------------------------------------------------------
00941 {
00942     moab::CartVect coords[2];
00943     MBERRCHK(mb->get_coords(&conn[0], 2, (double*) &coords[0]), mb);
00944     moab::CartVect AB(coords[1] - coords[0]);
00945     moab::CartVect normal = AB*BC;
00946     normal = normal/normal.length();
00947     v = normal;
00948 }
00949 
00950 void PostBL::find_min_edge_length(moab::Range adj_qn, moab::EntityHandle node , moab::Range bl_nodes, double &e_len)
00951 // ---------------------------------------------------------------------------
00955 // ---------------------------------------------------------------------------
00956 {
00957     // get nodes adj(a) to BL node
00958     moab::CartVect coords[1];
00959     double len = 0; e_len = 0;
00960     MBERRCHK(mb->get_coords(&node, 1, (double*) &coords[0]), mb);
00961     moab::Range non_bl;
00962     non_bl = subtract(adj_qn, bl_nodes);
00963     int n_non_bl = (int) non_bl.size();
00964 
00965     // if there are no bl nodes - this case has already been dealt with
00966     if(non_bl.size() > 0){
00967         moab::CartVect non_bl_coords[4];
00968         for(int i=0; i< n_non_bl; i++){
00969             MBERRCHK(mb->get_coords(non_bl,(double*) &non_bl_coords[0]), mb);
00970             moab::CartVect edge(coords[0] - non_bl_coords[0]);
00971             len = edge.length();
00972             if(i==0)
00973                 e_len = len;
00974             if(len < e_len)
00975                 e_len = len;
00976         }
00977     }
00978     // m_LogFile << " node minimum edge length" << e_len << std::endl;
00979 }
00980 
00981 void PostBL::get_det_jacobian(std::vector<moab::EntityHandle> conn, int offset, double &AvgJ)
00982 // ---------------------------------------------------------------------------
00986 // ---------------------------------------------------------------------------
00987 {
00988     //TODO: Add quality check for tri/quad and pyramids
00989     if(m_Conn ==8){
00990         ++m_JacCalls;
00991         moab::CartVect vertex[8], xi;
00992         mstream m_LogFile;
00993         MBERRCHK(mb->get_coords(&conn[offset], 8, (double*) &vertex[0]), mb);
00994 
00995         double corner[8][3] = { { -1, -1, -1 },
00996                                 {  1, -1, -1 },
00997                                 {  1,  1, -1 },
00998                                 { -1,  1, -1 },
00999                                 { -1, -1,  1 },
01000                                 {  1, -1,  1 },
01001                                 {  1,  1,  1 },
01002                                 { -1,  1,  1 } };
01003 
01004         for (unsigned j = 0; j < 8; ++j) {
01005             xi[0] = corner[j][0];
01006             xi[1] = corner[j][1];
01007             xi[2] = corner[j][2];
01008             Matrix3 J(0.0);
01009             double detJ = 0;
01010             for (unsigned i = 0; i < 8; ++i) {
01011                 const double   xi_p = 1 + xi[0]*corner[i][0];
01012                 const double  eta_p = 1 + xi[1]*corner[i][1];
01013                 const double zeta_p = 1 + xi[2]*corner[i][2];
01014                 const double dNi_dxi   = corner[i][0] * eta_p * zeta_p;
01015                 const double dNi_deta  = corner[i][1] *  xi_p * zeta_p;
01016                 const double dNi_dzeta = corner[i][2] *  xi_p *  eta_p;
01017                 J(0,0) += dNi_dxi   * vertex[i][0];
01018                 J(1,0) += dNi_dxi   * vertex[i][1];
01019                 J(2,0) += dNi_dxi   * vertex[i][2];
01020                 J(0,1) += dNi_deta  * vertex[i][0];
01021                 J(1,1) += dNi_deta  * vertex[i][1];
01022                 J(2,1) += dNi_deta  * vertex[i][2];
01023                 J(0,2) += dNi_dzeta * vertex[i][0];
01024                 J(1,2) += dNi_dzeta * vertex[i][1];
01025                 J(2,2) += dNi_dzeta * vertex[i][2];
01026             }
01027             J *= 0.125;
01028             detJ = J.determinant();
01029             if(detJ <= 0.0){
01030                 m_LogFile << "We've negative jacobian at the hex corner: "<< j+1 << std::endl;
01031                 exit(0);
01032             }
01033             AvgJ+=detJ;
01034         }
01035         AvgJ/=8;
01036         if(m_JacCalls == 1){
01037             m_JLo = AvgJ;
01038             m_JHi = AvgJ;
01039         }
01040         else if(AvgJ < m_JLo){
01041             m_JLo = AvgJ;
01042         }
01043         else if(AvgJ > m_JHi){
01044             m_JHi = AvgJ;
01045         }
01046     }
01047 }
01048 } // namespace MeshKit
01049 
01050 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines