$extrastylesheet
mesh_smoother_vsmoother.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 #include "libmesh/libmesh_config.h"
00019 #ifdef LIBMESH_ENABLE_VSMOOTHER
00020 
00021 // C++ includes
00022 #include <time.h> // for clock_t, clock()
00023 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00024 #include <cmath>
00025 #include <iomanip>
00026 
00027 // Local includes
00028 #include "libmesh/mesh_smoother_vsmoother.h"
00029 #include "libmesh/mesh_tools.h"
00030 #include "libmesh/elem.h"
00031 #include "libmesh/unstructured_mesh.h"
00032 #include "libmesh/utility.h"
00033 
00034 namespace libMesh
00035 {
00036 
00037 // Optimization at -O2 or greater seem to break Intel's icc. So if we are
00038 // being compiled with icc let's dumb-down the optimizations for this file
00039 #ifdef __INTEL_COMPILER
00040 #  pragma optimize ( "", off )
00041 #endif
00042 
00043 // Member functions for the Variational Smoother
00044 VariationalMeshSmoother::VariationalMeshSmoother(UnstructuredMesh& mesh,
00045                                                  double theta,
00046                                                  unsigned miniter,
00047                                                  unsigned maxiter,
00048                                                  unsigned miniterBC) :
00049   MeshSmoother(mesh),
00050   _percent_to_move(1),
00051   _dist_norm(0.),
00052   _adapt_data(NULL),
00053   _dim(mesh.mesh_dimension()),
00054   _miniter(miniter),
00055   _maxiter(maxiter),
00056   _miniterBC(miniterBC),
00057   _metric(UNIFORM),
00058   _adaptive_func(NONE),
00059   _theta(theta),
00060   _generate_data(false),
00061   _n_nodes(0),
00062   _n_cells(0),
00063   _n_hanging_edges(0),
00064   _area_of_interest(NULL)
00065 {}
00066 
00067 
00068 
00069 
00070 VariationalMeshSmoother::VariationalMeshSmoother(UnstructuredMesh& mesh,
00071                                                  std::vector<float>* adapt_data,
00072                                                  double theta,
00073                                                  unsigned miniter,
00074                                                  unsigned maxiter,
00075                                                  unsigned miniterBC,
00076                                                  double percent_to_move) :
00077   MeshSmoother(mesh),
00078   _percent_to_move(percent_to_move),
00079   _dist_norm(0.),
00080   _adapt_data(adapt_data),
00081   _dim(mesh.mesh_dimension()),
00082   _miniter(miniter),
00083   _maxiter(maxiter),
00084   _miniterBC(miniterBC),
00085   _metric(UNIFORM),
00086   _adaptive_func(CELL),
00087   _theta(theta),
00088   _generate_data(false),
00089   _n_nodes(0),
00090   _n_cells(0),
00091   _n_hanging_edges(0),
00092   _area_of_interest(NULL)
00093 {}
00094 
00095 
00096 
00097 VariationalMeshSmoother::VariationalMeshSmoother(UnstructuredMesh& mesh,
00098                                                  const UnstructuredMesh* area_of_interest,
00099                                                  std::vector<float>* adapt_data,
00100                                                  double theta,
00101                                                  unsigned miniter,
00102                                                  unsigned maxiter,
00103                                                  unsigned miniterBC,
00104                                                  double percent_to_move) :
00105   MeshSmoother(mesh),
00106   _percent_to_move(percent_to_move),
00107   _dist_norm(0.),
00108   _adapt_data(adapt_data),
00109   _dim(mesh.mesh_dimension()),
00110   _miniter(miniter),
00111   _maxiter(maxiter),
00112   _miniterBC(miniterBC),
00113   _metric(UNIFORM),
00114   _adaptive_func(CELL),
00115   _theta(theta),
00116   _generate_data(false),
00117   _n_nodes(0),
00118   _n_cells(0),
00119   _n_hanging_edges(0),
00120   _area_of_interest(area_of_interest)
00121 {}
00122 
00123 
00124 
00125 double VariationalMeshSmoother::smooth(unsigned int)
00126 {
00127   // If the log file is already open, for example on subsequent calls
00128   // to smooth() on the same object, we'll just keep writing to it,
00129   // otherwise we'll open it...
00130   if (!_logfile.is_open())
00131     _logfile.open("smoother.out");
00132 
00133   int
00134     me = _metric,
00135     gr = _generate_data ? 0 : 1,
00136     adp = _adaptive_func,
00137     miniter = _miniter,
00138     maxiter = _maxiter,
00139     miniterBC = _miniterBC;
00140 
00141   double theta = _theta;
00142 
00143   // Metric file name
00144   std::string metric_filename = "smoother.metric";
00145   if (gr == 0 && me > 1)
00146     {
00147       // grid filename
00148       std::string grid_filename = "smoother.grid";
00149 
00150       // generate metric from initial mesh (me = 2,3)
00151       metr_data_gen(grid_filename, metric_filename, me);
00152     }
00153 
00154   // Initialize the _n_nodes and _n_cells member variables
00155   this->_n_nodes = _mesh.n_nodes();
00156   this->_n_cells = _mesh.n_active_elem();
00157 
00158   // Initialize the _n_hanging_edges member variable
00159   MeshTools::find_hanging_nodes_and_parents(_mesh, _hanging_nodes);
00160   this->_n_hanging_edges =
00161     cast_int<dof_id_type>(_hanging_nodes.size());
00162 
00163   std::vector<int>
00164     mask(_n_nodes),
00165     edges(2*_n_hanging_edges),
00166     mcells(_n_cells),
00167     hnodes(_n_hanging_edges);
00168 
00169   Array2D<double> R(_n_nodes, _dim);
00170   Array2D<int> cells(_n_cells, 3*_dim + _dim%2);
00171   Array3D<double> H(_n_cells, _dim, _dim);
00172 
00173   // initial grid
00174   int vms_err = readgr(R, mask, cells, mcells, edges, hnodes);
00175   if (vms_err < 0)
00176     {
00177       _logfile << "Error reading input mesh file" << std::endl;
00178       return _dist_norm;
00179     }
00180 
00181   if (me > 1)
00182     vms_err = readmetr(metric_filename, H);
00183 
00184   if (vms_err < 0)
00185     {
00186       _logfile << "Error reading metric file" << std::endl;
00187       return _dist_norm;
00188     }
00189 
00190   std::vector<int> iter(4);
00191   iter[0] = miniter;
00192   iter[1] = maxiter;
00193   iter[2] = miniterBC;
00194 
00195   // grid optimization
00196   _logfile << "Starting Grid Optimization" << std::endl;
00197   clock_t ticks1 = clock();
00198   full_smooth(R, mask, cells, mcells, edges, hnodes, theta, iter, me, H, adp, gr);
00199   clock_t ticks2 = clock();
00200   _logfile << "full_smooth took ("
00201            << ticks2
00202            << "-"
00203            << ticks1
00204            << ")/"
00205            << CLOCKS_PER_SEC
00206            << " = "
00207            << static_cast<double>(ticks2-ticks1)/static_cast<double>(CLOCKS_PER_SEC)
00208            << " seconds"
00209            << std::endl;
00210 
00211   // save result
00212   _logfile << "Saving Result" << std::endl;
00213   writegr(R);
00214 
00215   libmesh_assert_greater (_dist_norm, 0);
00216   return _dist_norm;
00217 }
00218 
00219 
00220 
00221 // save grid
00222 int VariationalMeshSmoother::writegr(const Array2D<double>& R)
00223 {
00224   libMesh::out << "Starting writegr" << std::endl;
00225 
00226   // Adjust nodal coordinates to new positions
00227   {
00228     MeshBase::node_iterator       it  = _mesh.nodes_begin();
00229     const MeshBase::node_iterator end = _mesh.nodes_end();
00230 
00231     libmesh_assert_equal_to(_dist_norm, 0.);
00232     _dist_norm = 0;
00233     for (int i=0; it!=end; ++it)
00234       {
00235         double total_dist = 0.;
00236 
00237         // For each node set its X Y [Z] coordinates
00238         for (unsigned int j=0; j<_dim; j++)
00239           {
00240             // Get a reference to the node
00241             Node& node = *(*it);
00242 
00243             double distance = R[i][j] - node(j);
00244 
00245             // Save the squares of the distance
00246             total_dist += Utility::pow<2>(distance);
00247 
00248             node(j) += distance*_percent_to_move;
00249           }
00250 
00251         libmesh_assert_greater_equal (total_dist, 0.);
00252 
00253         // Add the distance this node moved to the global distance
00254         _dist_norm += total_dist;
00255 
00256         i++;
00257       }
00258 
00259     // Relative "error"
00260     _dist_norm = std::sqrt(_dist_norm/_mesh.n_nodes());
00261   }
00262 
00263   libMesh::out << "Finished writegr" << std::endl;
00264   return 0;
00265 }
00266 
00267 
00268 
00269 // reading grid from input file
00270 int VariationalMeshSmoother::readgr(Array2D<double>& R,
00271                                     std::vector<int>& mask,
00272                                     Array2D<int>& cells,
00273                                     std::vector<int>& mcells,
00274                                     std::vector<int>& edges,
00275                                     std::vector<int>& hnodes)
00276 {
00277   libMesh::out << "Sarting readgr" << std::endl;
00278   // add error messages where format can be inconsistent
00279 
00280   // Find the boundary nodes
00281   std::vector<bool> on_boundary;
00282   MeshTools::find_boundary_nodes(_mesh, on_boundary);
00283 
00284   // Grab node coordinates and set mask
00285   {
00286     MeshBase::const_node_iterator       it  = _mesh.nodes_begin();
00287     const MeshBase::const_node_iterator end = _mesh.nodes_end();
00288 
00289     // Only compute the node to elem map once
00290     std::vector<std::vector<const Elem*> > nodes_to_elem_map;
00291     MeshTools::build_nodes_to_elem_map(_mesh, nodes_to_elem_map);
00292 
00293     for (int i=0; it != end; ++it)
00294       {
00295         // Get a reference to the node
00296         Node& node = *(*it);
00297 
00298         // For each node grab its X Y [Z] coordinates
00299         for (unsigned int j=0; j<_dim; j++)
00300           R[i][j] = node(j);
00301 
00302         // Set the Proper Mask
00303         // Internal nodes are 0
00304         // Immovable boundary nodes are 1
00305         // Movable boundary nodes are 2
00306         if (on_boundary[i])
00307           {
00308             // Only look for sliding edge nodes in 2D
00309             if (_dim == 2)
00310               {
00311                 // Find all the nodal neighbors... that is the nodes directly connected
00312                 // to this node through one edge
00313                 std::vector<const Node*> neighbors;
00314                 MeshTools::find_nodal_neighbors(_mesh, node, nodes_to_elem_map, neighbors);
00315 
00316                 std::vector<const Node*>::const_iterator ne = neighbors.begin();
00317                 std::vector<const Node*>::const_iterator ne_end = neighbors.end();
00318 
00319                 // Grab the x,y coordinates
00320                 Real x = node(0);
00321                 Real y = node(1);
00322 
00323                 // Theta will represent the atan2 angle (meaning with the proper quadrant in mind)
00324                 // of the neighbor node in a system where the current node is at the origin
00325                 Real theta = 0;
00326                 std::vector<Real> thetas;
00327 
00328                 // Calculate the thetas
00329                 for (; ne != ne_end; ne++)
00330                   {
00331                     const Node& neighbor = *(*ne);
00332 
00333                     // Note that the x and y values of this node are subtracted off
00334                     // this centers the system around this node
00335                     theta = atan2(neighbor(1)-y, neighbor(0)-x);
00336 
00337                     // Save it for later
00338                     thetas.push_back(theta);
00339                   }
00340 
00341                 // Assume the node is immovable... then prove otherwise
00342                 mask[i] = 1;
00343 
00344                 // Search through neighbor nodes looking for two that form a straight line with this node
00345                 for (unsigned int a=0; a<thetas.size()-1; a++)
00346                   {
00347                     // Only try each pairing once
00348                     for (unsigned int b=a+1; b<thetas.size(); b++)
00349                       {
00350                         // Find if the two neighbor nodes angles are 180 degrees (pi) off of eachother (withing a tolerance)
00351                         // In order to make this a true movable boundary node... the two that forma  straight line with
00352                         // it must also be on the boundary
00353                         if (on_boundary[neighbors[a]->id()] &&
00354                             on_boundary[neighbors[b]->id()] &&
00355                             (
00356                              (std::abs(thetas[a] - (thetas[b] + (libMesh::pi))) < .001) ||
00357                              (std::abs(thetas[a] - (thetas[b] - (libMesh::pi))) < .001)
00358                              )
00359                             )
00360                           {
00361                             // if ((*(*it))(1) > 0.25 || (*(*it))(0) > .7 || (*(*it))(0) < .01)
00362                             mask[i] = 2;
00363                           }
00364 
00365                       }
00366                   }
00367               }
00368             else // In 3D set all boundary nodes to be fixed
00369               mask[i] = 1;
00370           }
00371         else
00372           mask[i] = 0;  // Internal Node
00373 
00374         // libMesh::out << "Node: " << i << "  Mask: " << mask[i] << std::endl;
00375         i++;
00376       }
00377   }
00378 
00379   // Grab the connectivity
00380   // FIXME: Generalize this!
00381   {
00382     MeshBase::const_element_iterator it  = _mesh.active_elements_begin();
00383     const MeshBase::const_element_iterator end = _mesh.active_elements_end();
00384 
00385     for (int i=0; it != end; ++it)
00386       {
00387         const Elem* elem = *it;
00388 
00389         // Keep track of the number of nodes
00390         // there must be 6 for 2D
00391         // 10 for 3D
00392         // If there are actually less than that -1 must be used
00393         // to fill out the rest
00394         int num = 0;
00395         /*
00396           int num_necessary = 0;
00397 
00398           if (_dim == 2)
00399           num_necessary = 6;
00400           else
00401           num_necessary = 10;
00402         */
00403 
00404         if (_dim == 2)
00405           {
00406             switch (elem->n_vertices())
00407               {
00408                 // Grab nodes that do exist
00409               case 3:  // Tri
00410                 for (unsigned int k=0; k<elem->n_vertices(); k++)
00411                   cells[i][k] = elem->node(k);
00412 
00413                 num = elem->n_vertices();
00414                 break;
00415 
00416               case 4:  // Quad 4
00417                 cells[i][0] = elem->node(0);
00418                 cells[i][1] = elem->node(1);
00419                 cells[i][2] = elem->node(3); // Note that 2 and 3 are switched!
00420                 cells[i][3] = elem->node(2);
00421                 num = 4;
00422                 break;
00423 
00424               default:
00425                 libmesh_error_msg("Unknown number of vertices = " << elem->n_vertices());
00426               }
00427           }
00428         else
00429           {
00430             // Grab nodes that do exist
00431             switch (elem->n_vertices())
00432               {
00433                 // Tet 4
00434               case 4:
00435                 for (unsigned int k=0; k<elem->n_vertices(); k++)
00436                   cells[i][k] = elem->node(k);
00437                 num = elem->n_vertices();
00438                 break;
00439 
00440                 // Hex 8
00441               case 8:
00442                 cells[i][0] = elem->node(0);
00443                 cells[i][1] = elem->node(1);
00444                 cells[i][2] = elem->node(3); // Note that 2 and 3 are switched!
00445                 cells[i][3] = elem->node(2);
00446 
00447                 cells[i][4] = elem->node(4);
00448                 cells[i][5] = elem->node(5);
00449                 cells[i][6] = elem->node(7); // Note that 6 and 7 are switched!
00450                 cells[i][7] = elem->node(6);
00451                 num=8;
00452                 break;
00453 
00454               default:
00455                 libmesh_error_msg("Unknown 3D element with = " << elem->n_vertices() << " vertices.");
00456               }
00457           }
00458 
00459         // Fill in the rest with -1
00460         for (int j=num; j<static_cast<int>(cells[i].size()); j++)
00461           cells[i][j] = -1;
00462 
00463         // Mask it with 0 to state that this is an active element
00464         // FIXME: Could be something other than zero
00465         mcells[i] = 0;
00466         i++;
00467       }
00468   }
00469 
00470   // Grab hanging node connectivity
00471   {
00472     std::map<dof_id_type, std::vector<dof_id_type> >::iterator
00473       it = _hanging_nodes.begin(),
00474       end = _hanging_nodes.end();
00475 
00476     for (int i=0; it!=end; it++)
00477       {
00478         libMesh::out << "Parent 1: " << (it->second)[0] << std::endl;
00479         libMesh::out << "Parent 2: " << (it->second)[1] << std::endl;
00480         libMesh::out << "Hanging Node: " << it->first << std::endl << std::endl;
00481 
00482         // First Parent
00483         edges[2*i] = (it->second)[1];
00484 
00485         // Second Parent
00486         edges[2*i+1] = (it->second)[0];
00487 
00488         // Hanging Node
00489         hnodes[i] = it->first;
00490 
00491         i++;
00492       }
00493   }
00494   libMesh::out << "Finished readgr" << std::endl;
00495 
00496   return 0;
00497 }
00498 
00499 
00500 
00501 // Read Metrics
00502 int VariationalMeshSmoother::readmetr(std::string name,
00503                                       Array3D<double>& H)
00504 {
00505   std::ifstream infile(name.c_str());
00506   std::string dummy;
00507 
00508   for (dof_id_type i=0; i<_n_cells; i++)
00509     for (unsigned j=0; j<_dim; j++)
00510       {
00511         for (unsigned k=0; k<_dim; k++)
00512           infile >> H[i][j][k];
00513 
00514         // Read to end of line and discard
00515         std::getline(infile, dummy);
00516       }
00517 
00518   return 0;
00519 }
00520 
00521 
00522 
00523 // Stolen from ErrorVector!
00524 float VariationalMeshSmoother::adapt_minimum() const
00525 {
00526   float min = 1.e30;
00527 
00528   for (unsigned int i=0; i<_adapt_data->size(); i++)
00529     {
00530       // Only positive (or zero) values in the error vector
00531       libmesh_assert_greater_equal ((*_adapt_data)[i], 0.);
00532       min = std::min (min, (*_adapt_data)[i]);
00533     }
00534 
00535   // ErrorVectors are for positive values
00536   libmesh_assert_greater_equal (min, 0.);
00537 
00538   return min;
00539 }
00540 
00541 
00542 
00543 void VariationalMeshSmoother::adjust_adapt_data()
00544 {
00545   // For convenience
00546   const UnstructuredMesh & aoe_mesh = *_area_of_interest;
00547   std::vector<float>& adapt_data = *_adapt_data;
00548 
00549   float min = adapt_minimum();
00550 
00551   MeshBase::const_element_iterator       el     = _mesh.elements_begin();
00552   const MeshBase::const_element_iterator end_el = _mesh.elements_end();
00553 
00554   MeshBase::const_element_iterator       aoe_el     = aoe_mesh.elements_begin();
00555   const MeshBase::const_element_iterator aoe_end_el = aoe_mesh.elements_end();
00556 
00557   // Counter to keep track of which spot in adapt_data we're looking at
00558   for (int i=0; el!=end_el; el++)
00559     {
00560       // Only do this for active elements
00561       if (adapt_data[i])
00562         {
00563           Point centroid = (*el)->centroid();
00564           bool in_aoe = false;
00565 
00566           // See if the elements centroid lies in the aoe mesh
00567           // for (aoe_el=aoe_mesh.elements_begin(); aoe_el != aoe_end_el; ++aoe_el)
00568           // {
00569           if ((*aoe_el)->contains_point(centroid))
00570             in_aoe = true;
00571           // }
00572 
00573           // If the element is not in the area of interest... then set
00574           // it's adaptivity value to the minimum.
00575           if (!in_aoe)
00576             adapt_data[i] = min;
00577         }
00578       i++;
00579     }
00580 }
00581 
00582 
00583 
00584 // Read Adaptivity
00585 int VariationalMeshSmoother::read_adp(std::vector<double>& afun)
00586 {
00587   std::vector<float>& adapt_data = *_adapt_data;
00588 
00589   if (_area_of_interest)
00590     adjust_adapt_data();
00591 
00592   std::size_t m = adapt_data.size();
00593 
00594   std::size_t j =0 ;
00595   for (std::size_t i=0; i<m; i++)
00596     if (adapt_data[i] != 0)
00597       {
00598         afun[j] = adapt_data[i];
00599         j++;
00600       }
00601 
00602   return 0;
00603 }
00604 
00605 
00606 
00607 double VariationalMeshSmoother::jac3(double x1,
00608                                      double y1,
00609                                      double z1,
00610                                      double x2,
00611                                      double y2,
00612                                      double z2,
00613                                      double x3,
00614                                      double y3,
00615                                      double z3)
00616 {
00617   return x1*(y2*z3 - y3*z2) + y1*(z2*x3 - z3*x2) + z1*(x2*y3 - x3*y2);
00618 }
00619 
00620 
00621 
00622 double VariationalMeshSmoother::jac2(double x1,
00623                                      double y1,
00624                                      double x2,
00625                                      double y2)
00626 {
00627   return x1*y2 - x2*y1;
00628 }
00629 
00630 
00631 
00632 // BasisA determines matrix H^(-T)Q on one Jacobian matrix
00633 int VariationalMeshSmoother::basisA(Array2D<double>& Q,
00634                                     int nvert,
00635                                     const std::vector<double>& K,
00636                                     const Array2D<double>& H,
00637                                     int me)
00638 {
00639   Array2D<double> U(_dim, nvert);
00640 
00641   // Some useful constants
00642   const double
00643     sqrt3 = std::sqrt(3.),
00644     sqrt6 = std::sqrt(6.);
00645 
00646   if (_dim == 2)
00647     {
00648       if (nvert == 4)
00649         {
00650           // quad
00651           U[0][0] = -(1-K[1]);
00652           U[0][1] =  (1-K[1]);
00653           U[0][2] = -K[1];
00654           U[0][3] =  K[1];
00655 
00656           U[1][0] = -(1-K[0]);
00657           U[1][1] = -K[0];
00658           U[1][2] =  (1-K[0]);
00659           U[1][3] =  K[0];
00660         }
00661       else if (nvert == 3)
00662         {
00663           // tri
00664           // for right target triangle
00665           // U[0][0] = -1.; U[1][0] = -1.;
00666           // U[0][1] = 1.;  U[1][1] = 0.;
00667           // U[0][2] = 0.;  U[1][2] = 1.;
00668 
00669           // for regular triangle
00670           U[0][0] = -1.;
00671           U[0][1] =  1.;
00672           U[0][2] =    0;
00673 
00674           U[1][0] = -1./sqrt3;
00675           U[1][1] = -1./sqrt3;
00676           U[1][2] =  2./sqrt3;
00677         }
00678       else if (nvert == 6)
00679         {
00680           // curved triangle
00681           U[0][0] = -3*(1-K[0]-K[1]*0.5)+(K[0]-0.5*K[1])+K[1];
00682           U[0][1] = -(1-K[0]-K[1]*0.5)+(K[0]-0.5*K[1])*3-K[1];
00683           U[0][2] = 0;
00684           U[0][3] = K[1]*4;
00685           U[0][4] = -4*K[1];
00686           U[0][5] = 4*(1-K[0]-K[1]*0.5)-4*(K[0]-0.5*K[1]);
00687 
00688           U[1][0] = (1-K[2]-K[3]*0.5)*(-1.5)+(K[2]-0.5*K[3])*(0.5)+K[3]*(0.5);
00689           U[1][1] = (1-K[2]-K[3]*0.5)*(0.5)+(K[2]-0.5*K[3])*(-1.5)+K[3]*(0.5);
00690           U[1][2] = (1-K[2]-K[3]*0.5)*(-1)+(K[2]-0.5*K[3])*(-1)+K[3]*(3);
00691           U[1][3] = (K[2]-0.5*K[3])*(4.)+K[3]*(-2.);
00692           U[1][4] = (1-K[2]-K[3]*0.5)*(4.)+K[3]*(-2.);
00693           U[1][5] = (1-K[2]-K[3]*0.5)*(-2.)+(K[2]-0.5*K[3])*(-2.);
00694         }
00695       else
00696         libmesh_error_msg("Invalid nvert = " << nvert);
00697     }
00698 
00699   if (_dim == 3)
00700     {
00701       if (nvert == 8)
00702         {
00703           // hex
00704           U[0][0] = -(1-K[0])*(1-K[1]);
00705           U[0][1] =  (1-K[0])*(1-K[1]);
00706           U[0][2] = -K[0]*(1-K[1]);
00707           U[0][3] =  K[0]*(1-K[1]);
00708           U[0][4] = -(1-K[0])*K[1];
00709           U[0][5] =  (1-K[0])*K[1];
00710           U[0][6] = -K[0]*K[1];
00711           U[0][7] =  K[0]*K[1];
00712 
00713           U[1][0] = -(1-K[2])*(1-K[3]);
00714           U[1][1] = -K[2]*(1-K[3]);
00715           U[1][2] =  (1-K[2])*(1-K[3]);
00716           U[1][3] =  K[2]*(1-K[3]);
00717           U[1][4] = -(1-K[2])*K[3];
00718           U[1][5] = -K[2]*K[3];
00719           U[1][6] =  (1-K[2])*K[3];
00720           U[1][7] =  K[2]*K[3];
00721 
00722           U[2][0] = -(1-K[4])*(1-K[5]);
00723           U[2][1] = -K[4]*(1-K[5]);
00724           U[2][2] = -(1-K[4])*K[5];
00725           U[2][3] = -K[4]*K[5];
00726           U[2][4] =  (1-K[4])*(1-K[5]);
00727           U[2][5] =  K[4]*(1-K[5]);
00728           U[2][6] =  (1-K[4])*K[5];
00729           U[2][7] =  K[4]*K[5];
00730         }
00731       else if (nvert == 4)
00732         {
00733           // linear tetr
00734           // for regular reference tetrahedron
00735           U[0][0] = -1;
00736           U[0][1] = 1;
00737           U[0][2] = 0;
00738           U[0][3] = 0;
00739 
00740           U[1][0] = -1./sqrt3;
00741           U[1][1] = -1./sqrt3;
00742           U[1][2] = 2./sqrt3;
00743           U[1][3] = 0;
00744 
00745           U[2][0] = -1./sqrt6;
00746           U[2][1] = -1./sqrt6;
00747           U[2][2] = -1./sqrt6;
00748           U[2][3] = 3./sqrt6;
00749 
00750           // for right corner reference tetrahedron
00751           // U[0][0] = -1; U[1][0] = -1; U[2][0] = -1;
00752           // U[0][1] = 1;  U[1][1] = 0;  U[2][1] = 0;
00753           // U[0][2] = 0;  U[1][2] = 1;  U[2][2] = 0;
00754           // U[0][3] = 0;  U[1][3] = 0;  U[2][3] = 1;
00755         }
00756       else if (nvert == 6)
00757         {
00758           // prism
00759           // for regular triangle in the prism base
00760           U[0][0] = -1+K[0];
00761           U[0][1] = 1-K[0];
00762           U[0][2] = 0;
00763           U[0][3] = -K[0];
00764           U[0][4] = K[0];
00765           U[0][5] = 0;
00766 
00767           U[1][0] = 0.5*(-1+K[1]);
00768           U[1][1] = 0.5*(-1+K[1]);
00769           U[1][2] = (1-K[1]);
00770           U[1][3] = -0.5*K[1];
00771           U[1][4] = -0.5*K[1];
00772           U[1][5] = K[1];
00773 
00774           U[2][0] = -1. + K[2] + 0.5*K[3];
00775           U[2][1] = -K[2] + 0.5*K[3];
00776           U[2][2] = -K[3];
00777           U[2][3] = 1 - K[2] - 0.5*K[3];
00778           U[2][4] = K[2] - 0.5*K[3];
00779           U[2][5] = K[3];
00780         }
00781       else if (nvert == 10)
00782         {
00783           // quad tetr
00784           U[0][0] = -3.*(1 - K[0] - 0.5*K[1] - K[2]/3.) + (K[0] - 0.5*K[1] - K[2]/3.)    + (K[1] - K[2]/3.) + K[2];
00785           U[0][1] = -1.*(1 - K[0] - 0.5*K[1] - K[2]/3.) + 3.*(K[0] - 0.5*K[1] - K[2]/3.) - (K[1] - K[2]/3.) - K[2];
00786           U[0][2] = 0.;
00787           U[0][3] = 0.;
00788           U[0][4] = 4.*(K[1] - K[2]/3.);
00789           U[0][5] = -4.*(K[1] - K[2]/3.);
00790           U[0][6] = 4.*(1. - K[0] - 0.5*K[1] - K[2]/3.) - 4.*(K[0] - 0.5*K[1] - K[2]/3.);
00791           U[0][7] = 4.*K[2];
00792           U[0][8] = 0.;
00793           U[0][9] = -4.*K[2];
00794 
00795           U[1][0] = -1.5*(1. - K[3] - K[4]*0.5 - K[5]/3.) + 0.5*(K[3] - 0.5*K[4] - K[5]/3.) + 0.5*(K[4] - K[5]/3.) + 0.5*K[5];
00796           U[1][1] =  0.5*(1. - K[3] - K[4]*0.5 - K[5]/3.) - 1.5*(K[3] - 0.5*K[4] - K[5]/3.) + 0.5*(K[4] - K[5]/3.) + 0.5*K[5];
00797           U[1][2] = -1.*(1. - K[3] - K[4]*0.5 - K[5]/3.) - (K[3] - 0.5*K[4] - K[5]/3.) + 3.*(K[4] - K[5]/3.) - K[5];
00798           U[1][3] = 0.;
00799           U[1][4] =  4.*(     K[3] - 0.5*K[4] - K[5]/3.) - 2.*(K[4] - K[5]/3.);
00800           U[1][5] =  4.*(1. - K[3] - 0.5*K[4] - K[5]/3.) - 2.*(K[4] - K[5]/3.);
00801           U[1][6] = -2.*(1. - K[3] - 0.5*K[4] - K[5]/3.) - 2.*(K[3] - 0.5*K[4] - K[5]/3.);
00802           U[1][7] = -2.*K[5];
00803           U[1][8] = 4.*K[5];
00804           U[1][9] = -2.*K[5];
00805 
00806           U[2][0] = -(1. - K[6] - 0.5*K[7] - K[8]/3.)    + (K[6] - 0.5*K[7] - K[8]/3.)/3. + (K[7] - K[8]/3.)/3. + K[8]/3.;
00807           U[2][1] =  (1. - K[6] - 0.5*K[7] - K[8]/3.)/3. - (K[6] - 0.5*K[7] - K[8]/3.)    + (K[7] - K[8]/3.)/3. + K[8]/3.;
00808           U[2][2] =  (1. - K[6] - 0.5*K[7] - K[8]/3.)/3. + (K[6] - 0.5*K[7] - K[8]/3.)/3. - (K[7] - K[8]/3.)    + K[8]/3.;
00809           U[2][3] = -(1. - K[6] - 0.5*K[7] - K[8]/3.)    - (K[6] - 0.5*K[7] - K[8]/3.)    - (K[7] - K[8]/3.)    + 3.*K[8];
00810           U[2][4] = -4.*(K[6] - K[7]*0.5 - K[8]/3.)/3. - 4.*(K[7] - K[8]/3.)/3.;
00811           U[2][5] = -4.*(1. - K[6] - K[7]*0.5 - K[8]/3.)/3. - 4.*(           K[7] - K[8]/3.)/3.;
00812           U[2][6] = -4.*(1. - K[6] - K[7]*0.5 - K[8]/3.)/3. - 4.*(K[6] - 0.5*K[7] - K[8]/3.)/3.;
00813           U[2][7] =  4.*(K[6] - K[7]*0.5 - K[8]/3.) - 4.*K[8]/3.;
00814           U[2][8] =  4.*(K[7] - K[8]/3.) - 4.*K[8]/3.;
00815           U[2][9] =  4.*(1. - K[6] - K[7]*0.5 - K[8]/3.) - 4.*K[8]/3.;
00816         }
00817       else
00818         libmesh_error_msg("Invalid nvert = " << nvert);
00819     }
00820 
00821   if (me == 1)
00822     Q = U;
00823 
00824   else
00825     {
00826       for (unsigned i=0; i<_dim; i++)
00827         for (int j=0; j<nvert; j++)
00828           {
00829             Q[i][j] = 0;
00830             for (unsigned k=0; k<_dim; k++)
00831               Q[i][j] += H[k][i]*U[k][j];
00832           }
00833     }
00834 
00835   return 0;
00836 }
00837 
00838 
00839 
00840 // Specify adaptive function
00841 void VariationalMeshSmoother::adp_renew(const Array2D<double>& R,
00842                                         const Array2D<int>& cells,
00843                                         std::vector<double>& afun,
00844                                         int adp)
00845 {
00846   // evaluates given adaptive function on the provided mesh
00847   if (adp < 0)
00848     {
00849       for (dof_id_type i=0; i<_n_cells; i++)
00850         {
00851           double
00852             x = 0.,
00853             y = 0.,
00854             z = 0.;
00855           int nvert = 0;
00856 
00857           while (cells[i][nvert] >= 0)
00858             {
00859               x += R[cells[i][nvert]][0];
00860               y += R[cells[i][nvert]][1];
00861               if (_dim == 3)
00862                 z += R[cells[i][nvert]][2];
00863               nvert++;
00864             }
00865 
00866           // adaptive function, cell based
00867           afun[i] = 5.*(x+y+z);
00868         }
00869     }
00870 
00871   else if (adp > 0)
00872     {
00873       for (dof_id_type i=0; i<_n_nodes; i++)
00874         {
00875           double z = 0;
00876           for (unsigned j=0; j<_dim; j++)
00877             z += R[i][j];
00878 
00879           // adaptive function, node based
00880           afun[i] = 5*std::sin(R[i][0]);
00881         }
00882     }
00883 }
00884 
00885 
00886 
00887 // Preprocess mesh data and control smoothing/untangling iterations
00888 void VariationalMeshSmoother::full_smooth(Array2D<double>& R,
00889                                           const std::vector<int>& mask,
00890                                           const Array2D<int>& cells,
00891                                           const std::vector<int>& mcells,
00892                                           const std::vector<int>& edges,
00893                                           const std::vector<int>& hnodes,
00894                                           double w,
00895                                           const std::vector<int>& iter,
00896                                           int me,
00897                                           const Array3D<double>& H,
00898                                           int adp,
00899                                           int gr)
00900 {
00901   // Control the amount of print statements in this funcion
00902   int msglev = 1;
00903 
00904   dof_id_type afun_size = 0;
00905 
00906   // Adaptive function is on cells
00907   if (adp < 0)
00908     afun_size = _n_cells;
00909 
00910   // Adaptive function is on nodes
00911   else if (adp > 0)
00912     afun_size = _n_nodes;
00913 
00914   std::vector<double> afun(afun_size);
00915   std::vector<int> maskf(_n_nodes);
00916   std::vector<double> Gamma(_n_cells);
00917 
00918   if (msglev >= 1)
00919     _logfile << "N=" << _n_nodes
00920              << " ncells=" << _n_cells
00921              << " nedges=" << _n_hanging_edges
00922              << std::endl;
00923 
00924 
00925   // Boundary node counting
00926   int NBN=0;
00927   for (dof_id_type i=0; i<_n_nodes; i++)
00928     if (mask[i] == 2 || mask[i] == 1)
00929       NBN++;
00930 
00931   if (NBN > 0)
00932     {
00933       if (msglev >= 1)
00934         _logfile << "# of Boundary Nodes=" << NBN << std::endl;
00935 
00936       NBN=0;
00937       for (dof_id_type i=0; i<_n_nodes; i++)
00938         if (mask[i] == 2)
00939           NBN++;
00940 
00941       if (msglev >= 1)
00942         _logfile << "# of moving Boundary Nodes=" << NBN << std::endl;
00943     }
00944 
00945   for (dof_id_type i=0; i<_n_nodes; i++)
00946     {
00947       if ((mask[i]==1) || (mask[i]==2))
00948         maskf[i] = 1;
00949       else
00950         maskf[i] = 0;
00951     }
00952 
00953   // determination of min jacobian
00954   double vol, Vmin;
00955   double qmin = minq(R, cells, mcells, me, H, vol, Vmin);
00956 
00957   if (me > 1)
00958     vol = 1.;
00959 
00960   if (msglev >= 1)
00961     _logfile << "vol=" << vol
00962              << " qmin=" << qmin
00963              << " min volume = " << Vmin
00964              << std::endl;
00965 
00966   // compute max distortion measure over all cells
00967   double epsilon = 1.e-9;
00968   double eps = qmin < 0 ? std::sqrt(epsilon*epsilon+0.004*qmin*qmin*vol*vol) : epsilon;
00969   double emax = maxE(R, cells, mcells, me, H, vol, eps, w, Gamma, qmin);
00970 
00971   if (msglev >= 1)
00972     _logfile << " emax=" << emax << std::endl;
00973 
00974   // unfolding/smoothing
00975 
00976   // iteration tolerance
00977   double Enm1 = 1.;
00978 
00979   // read adaptive function from file
00980   if (adp*gr != 0)
00981     read_adp(afun);
00982 
00983   {
00984     int
00985       counter = 0,
00986       ii = 0;
00987 
00988     while (((qmin <= 0) || (counter < iter[0]) || (std::abs(emax-Enm1) > 1e-3)) &&
00989            (ii < iter[1]) &&
00990            (counter < iter[1]))
00991       {
00992         libmesh_assert_less (counter, iter[1]);
00993 
00994         Enm1 = emax;
00995 
00996         if ((ii >= 0) && (ii % 2 == 0))
00997           {
00998             if (qmin < 0)
00999               eps = std::sqrt(epsilon*epsilon + 0.004*qmin*qmin*vol*vol);
01000             else
01001               eps = epsilon;
01002           }
01003 
01004         int ladp = adp;
01005 
01006         if ((qmin <= 0) || (counter < ii))
01007           ladp = 0;
01008 
01009         // update adaptation function before each iteration
01010         if ((ladp != 0) && (gr == 0))
01011           adp_renew(R, cells, afun, adp);
01012 
01013         double Jk = minJ(R, maskf, cells, mcells, eps, w, me, H, vol, edges, hnodes,
01014                          msglev, Vmin, emax, qmin, ladp, afun);
01015 
01016         if (qmin > 0)
01017           counter++;
01018         else
01019           ii++;
01020 
01021         if (msglev >= 1)
01022           _logfile << "niter=" << counter
01023                    << ", qmin*G/vol=" << qmin
01024                    << ", Vmin=" << Vmin
01025                    << ", emax=" << emax
01026                    << ", Jk=" << Jk
01027                    << ", Enm1=" << Enm1
01028                    << std::endl;
01029       }
01030   }
01031 
01032   // BN correction - 2D only!
01033   epsilon = 1.e-9;
01034   if (NBN > 0)
01035     for (int counter=0; counter<iter[2]; counter++)
01036       {
01037         // update adaptation function before each iteration
01038         if ((adp != 0) && (gr == 0))
01039           adp_renew(R, cells, afun, adp);
01040 
01041         double Jk = minJ_BC(R, mask, cells, mcells, eps, w, me, H, vol, msglev, Vmin, emax, qmin, adp, afun, NBN);
01042 
01043         if (msglev >= 1)
01044           _logfile << "NBC niter=" << counter
01045                    << ", qmin*G/vol=" << qmin
01046                    << ", Vmin=" << Vmin
01047                    << ", emax=" << emax
01048                    << std::endl;
01049 
01050         // Outrageous Enm1 to make sure we hit this at least once
01051         Enm1 = 99999;
01052 
01053         // Now that we've moved the boundary nodes (or not) we need to resmoooth
01054         for (int j=0; j<iter[1]; j++)
01055           {
01056             if (std::abs(emax-Enm1) < 1e-2)
01057               break;
01058 
01059             // Save off the error from the previous smoothing step
01060             Enm1 = emax;
01061 
01062             // update adaptation function before each iteration
01063             if ((adp != 0) && (gr == 0))
01064               adp_renew(R, cells, afun, adp);
01065 
01066             Jk = minJ(R, maskf, cells, mcells, eps, w, me, H, vol, edges, hnodes, msglev, Vmin, emax, qmin, adp, afun);
01067 
01068             if (msglev >= 1)
01069               _logfile << "  Re-smooth: niter=" << j
01070                        << ", qmin*G/vol=" << qmin
01071                        << ", Vmin=" << Vmin
01072                        << ", emax=" << emax
01073                        << ", Jk=" << Jk
01074                        << std::endl;
01075           }
01076 
01077         if (msglev >= 1)
01078           _logfile << "NBC smoothed niter=" << counter
01079                    << ", qmin*G/vol=" << qmin
01080                    << ", Vmin=" << Vmin
01081                    << ", emax=" << emax
01082                    << std::endl;
01083       }
01084 }
01085 
01086 
01087 
01088 // Determines the values of maxE_theta
01089 double VariationalMeshSmoother::maxE(Array2D<double>& R,
01090                                      const Array2D<int>& cells,
01091                                      const std::vector<int>& mcells,
01092                                      int me,
01093                                      const Array3D<double>& H,
01094                                      double v,
01095                                      double epsilon,
01096                                      double w,
01097                                      std::vector<double>& Gamma,
01098                                      double& qmin)
01099 {
01100   Array2D<double> Q(3, 3*_dim + _dim%2);
01101   std::vector<double> K(9);
01102 
01103   double
01104     gemax = -1.e32,
01105     vmin = 1.e32;
01106 
01107   for (dof_id_type ii=0; ii<_n_cells; ii++)
01108     if (mcells[ii] >= 0)
01109       {
01110         // Final value of E will be saved in Gamma at the end of this loop
01111         double E = 0.;
01112 
01113         if (_dim == 2)
01114           {
01115             if (cells[ii][3] == -1)
01116               {
01117                 // tri
01118                 basisA(Q, 3, K, H[ii], me);
01119 
01120                 std::vector<double> a1(3), a2(3);
01121                 for (int k=0; k<2; k++)
01122                   for (int l=0; l<3; l++)
01123                     {
01124                       a1[k] += Q[k][l]*R[cells[ii][l]][0];
01125                       a2[k] += Q[k][l]*R[cells[ii][l]][1];
01126                     }
01127 
01128                 double det = jac2(a1[0], a1[1], a2[0], a2[1]);
01129                 double tr = 0.5*(a1[0]*a1[0] + a2[0]*a2[0] + a1[1]*a1[1] + a2[1]*a2[1]);
01130                 double chi = 0.5*(det+std::sqrt(det*det+epsilon*epsilon));
01131                 E = (1-w)*tr/chi + 0.5*w*(v + det*det/v)/chi;
01132 
01133                 if (E > gemax)
01134                   gemax = E;
01135                 if (vmin > det)
01136                   vmin = det;
01137 
01138               }
01139             else if (cells[ii][4] == -1)
01140               {
01141                 // quad
01142                 for (int i=0; i<2; i++)
01143                   {
01144                     K[0] = i;
01145                     for (int j=0; j<2; j++)
01146                       {
01147                         K[1] = j;
01148                         basisA(Q, 4, K, H[ii], me);
01149 
01150                         std::vector<double> a1(3), a2(3);
01151                         for (int k=0; k<2; k++)
01152                           for (int l=0; l<4; l++)
01153                             {
01154                               a1[k] += Q[k][l]*R[cells[ii][l]][0];
01155                               a2[k] += Q[k][l]*R[cells[ii][l]][1];
01156                             }
01157 
01158                         double det = jac2(a1[0],a1[1],a2[0],a2[1]);
01159                         double tr = 0.5*(a1[0]*a1[0] + a2[0]*a2[0] + a1[1]*a1[1] + a2[1]*a2[1]);
01160                         double chi = 0.5*(det+std::sqrt(det*det+epsilon*epsilon));
01161                         E += 0.25*((1-w)*tr/chi + 0.5*w*(v + det*det/v)/chi);
01162 
01163                         if (vmin > det)
01164                           vmin = det;
01165                       }
01166                   }
01167 
01168                 if (E > gemax)
01169                   gemax = E;
01170               }
01171             else
01172               {
01173                 // quad tri
01174                 for (int i=0; i<3; i++)
01175                   {
01176                     K[0] = i*0.5;
01177                     int k = i/2;
01178                     K[1] = static_cast<double>(k);
01179 
01180                     for (int j=0; j<3; j++)
01181                       {
01182                         K[2] = j*0.5;
01183                         k = j/2;
01184                         K[3] = static_cast<double>(k);
01185 
01186                         basisA(Q, 6, K, H[ii], me);
01187 
01188                         std::vector<double> a1(3), a2(3);
01189                         for (int k=0; k<2; k++)
01190                           for (int l=0; l<6; l++)
01191                             {
01192                               a1[k] += Q[k][l]*R[cells[ii][l]][0];
01193                               a2[k] += Q[k][l]*R[cells[ii][l]][1];
01194                             }
01195 
01196                         double det = jac2(a1[0],a1[1],a2[0],a2[1]);
01197                         double sigma = 1./24.;
01198 
01199                         if (i==j)
01200                           sigma = 1./12.;
01201 
01202                         double tr = 0.5*(a1[0]*a1[0] + a2[0]*a2[0] + a1[1]*a1[1] + a2[1]*a2[1]);
01203                         double chi = 0.5*(det + std::sqrt(det*det + epsilon*epsilon));
01204                         E += sigma*((1-w)*tr/chi + 0.5*w*(v + det*det/v)/chi);
01205                         if (vmin > det)
01206                           vmin = det;
01207                       }
01208                   }
01209 
01210                 if (E > gemax)
01211                   gemax = E;
01212               }
01213           }
01214 
01215         if (_dim == 3)
01216           {
01217             if (cells[ii][4] == -1)
01218               {
01219                 // tetr
01220                 basisA(Q, 4, K, H[ii], me);
01221 
01222                 std::vector<double> a1(3), a2(3), a3(3);
01223                 for (int k=0; k<3; k++)
01224                   for (int l=0; l<4; l++)
01225                     {
01226                       a1[k] += Q[k][l]*R[cells[ii][l]][0];
01227                       a2[k] += Q[k][l]*R[cells[ii][l]][1];
01228                       a3[k] += Q[k][l]*R[cells[ii][l]][2];
01229                     }
01230 
01231                 double det = jac3(a1[0], a1[1], a1[2],
01232                                   a2[0], a2[1], a2[2],
01233                                   a3[0], a3[1], a3[2]);
01234                 double tr = 0.;
01235                 for (int k=0; k<3; k++)
01236                   tr += (a1[k]*a1[k] + a2[k]*a2[k] + a3[k]*a3[k])/3.;
01237 
01238                 double chi = 0.5*(det+std::sqrt(det*det+epsilon*epsilon));
01239                 E = (1-w)*pow(tr,1.5)/chi + 0.5*w*(v + det*det/v)/chi;
01240 
01241                 if (E > gemax)
01242                   gemax = E;
01243 
01244                 if (vmin > det)
01245                   vmin = det;
01246               }
01247             else if (cells[ii][6] == -1)
01248               {
01249                 // prism
01250                 for (int i=0; i<2; i++)
01251                   {
01252                     K[0] = i;
01253                     for (int j=0; j<2; j++)
01254                       {
01255                         K[1] = j;
01256                         for (int k=0; k<3; k++)
01257                           {
01258                             K[2] = 0.5*static_cast<double>(k);
01259                             K[3] = static_cast<double>(k % 2);
01260                             basisA(Q, 6, K, H[ii], me);
01261 
01262                             std::vector<double> a1(3), a2(3), a3(3);
01263                             for (int kk=0; kk<3; kk++)
01264                               for (int ll=0; ll<6; ll++)
01265                                 {
01266                                   a1[kk] += Q[kk][ll]*R[cells[ii][ll]][0];
01267                                   a2[kk] += Q[kk][ll]*R[cells[ii][ll]][1];
01268                                   a3[kk] += Q[kk][ll]*R[cells[ii][ll]][2];
01269                                 }
01270 
01271                             double det = jac3(a1[0], a1[1], a1[2],
01272                                               a2[0], a2[1], a2[2],
01273                                               a3[0], a3[1], a3[2]);
01274                             double tr = 0;
01275                             for (int kk=0; kk<3; kk++)
01276                               tr += (a1[kk]*a1[kk] + a2[kk]*a2[kk] + a3[kk]*a3[kk])/3.;
01277 
01278                             double chi = 0.5*(det+std::sqrt(det*det+epsilon*epsilon));
01279                             E += ((1-w)*pow(tr,1.5)/chi + 0.5*w*(v + det*det/v)/chi)/12.;
01280                             if (vmin > det)
01281                               vmin = det;
01282                           }
01283                       }
01284                   }
01285 
01286                 if (E > gemax)
01287                   gemax = E;
01288               }
01289             else if (cells[ii][8] == -1)
01290               {
01291                 // hex
01292                 for (int i=0; i<2; i++)
01293                   {
01294                     K[0] = i;
01295                     for (int j=0; j<2; j++)
01296                       {
01297                         K[1] = j;
01298                         for (int k=0; k<2; k++)
01299                           {
01300                             K[2] = k;
01301                             for (int l=0; l<2; l++)
01302                               {
01303                                 K[3] = l;
01304                                 for (int m=0; m<2; m++)
01305                                   {
01306                                     K[4] = m;
01307                                     for (int nn=0; nn<2; nn++)
01308                                       {
01309                                         K[5] = nn;
01310                                         basisA(Q, 8, K, H[ii], me);
01311 
01312                                         std::vector<double> a1(3), a2(3), a3(3);
01313                                         for (int kk=0; kk<3; kk++)
01314                                           for (int ll=0; ll<8; ll++)
01315                                             {
01316                                               a1[kk] += Q[kk][ll]*R[cells[ii][ll]][0];
01317                                               a2[kk] += Q[kk][ll]*R[cells[ii][ll]][1];
01318                                               a3[kk] += Q[kk][ll]*R[cells[ii][ll]][2];
01319                                             }
01320 
01321                                         double det = jac3(a1[0], a1[1], a1[2],
01322                                                           a2[0], a2[1], a2[2],
01323                                                           a3[0], a3[1], a3[2]);
01324                                         double sigma = 0.;
01325 
01326                                         if ((i==nn) && (j==l) && (k==m))
01327                                           sigma = 1./27.;
01328 
01329                                         if (((i==nn) && (j==l) && (k!=m)) ||
01330                                             ((i==nn) && (j!=l) && (k==m)) ||
01331                                             ((i!=nn) && (j==l) && (k==m)))
01332                                           sigma = 1./54.;
01333 
01334                                         if (((i==nn) && (j!=l) && (k!=m)) ||
01335                                             ((i!=nn) && (j!=l) && (k==m)) ||
01336                                             ((i!=nn) && (j==l) && (k!=m)))
01337                                           sigma = 1./108.;
01338 
01339                                         if ((i!=nn) && (j!=l) && (k!=m))
01340                                           sigma = 1./216.;
01341 
01342                                         double tr = 0;
01343                                         for (int kk=0; kk<3; kk++)
01344                                           tr += (a1[kk]*a1[kk] + a2[kk]*a2[kk] + a3[kk]*a3[kk])/3.;
01345 
01346                                         double chi = 0.5*(det+std::sqrt(det*det + epsilon*epsilon));
01347                                         E += ((1-w)*pow(tr,1.5)/chi + 0.5*w*(v + det*det/v)/chi)*sigma;
01348                                         if (vmin > det)
01349                                           vmin = det;
01350                                       }
01351                                   }
01352                               }
01353                           }
01354                       }
01355                   }
01356                 if (E > gemax)
01357                   gemax = E;
01358               }
01359             else
01360               {
01361                 // quad tetr
01362                 for (int i=0; i<4; i++)
01363                   {
01364                     for (int j=0; j<4; j++)
01365                       {
01366                         for (int k=0; k<4; k++)
01367                           {
01368                             switch (i)
01369                               {
01370                               case 0:
01371                                 K[0] = 0;
01372                                 K[1] = 0;
01373                                 K[2] = 0;
01374                                 break;
01375                               case 1:
01376                                 K[0] = 1;
01377                                 K[1] = 0;
01378                                 K[2] = 0;
01379                                 break;
01380                               case 2:
01381                                 K[0] = 0.5;
01382                                 K[1] = 1;
01383                                 K[2] = 0;
01384                                 break;
01385                               case 3:
01386                                 K[0] = 0.5;
01387                                 K[1] = 1./3.;
01388                                 K[2] = 1;
01389                                 break;
01390                               }
01391 
01392                             switch (j)
01393                               {
01394                               case 0:
01395                                 K[3] = 0;
01396                                 K[4] = 0;
01397                                 K[5] = 0;
01398                                 break;
01399                               case 1:
01400                                 K[3] = 1;
01401                                 K[4] = 0;
01402                                 K[5] = 0;
01403                                 break;
01404                               case 2:
01405                                 K[3] = 0.5;
01406                                 K[4] = 1;
01407                                 K[5] = 0;
01408                                 break;
01409                               case 3:
01410                                 K[3] = 0.5;
01411                                 K[4] = 1./3.;
01412                                 K[5] = 1;
01413                                 break;
01414                               }
01415 
01416                             switch (k)
01417                               {
01418                               case 0:
01419                                 K[6] = 0;
01420                                 K[7] = 0;
01421                                 K[8] = 0;
01422                                 break;
01423                               case 1:
01424                                 K[6] = 1;
01425                                 K[7] = 0;
01426                                 K[8] = 0;
01427                                 break;
01428                               case 2:
01429                                 K[6] = 0.5;
01430                                 K[7] = 1;
01431                                 K[8] = 0;
01432                                 break;
01433                               case 3:
01434                                 K[6] = 0.5;
01435                                 K[7] = 1./3.;
01436                                 K[8] = 1;
01437                                 break;
01438                               }
01439 
01440                             basisA(Q, 10, K, H[ii], me);
01441 
01442                             std::vector<double> a1(3), a2(3), a3(3);
01443                             for (int kk=0; kk<3; kk++)
01444                               for (int ll=0; ll<10; ll++)
01445                                 {
01446                                   a1[kk] += Q[kk][ll]*R[cells[ii][ll]][0];
01447                                   a2[kk] += Q[kk][ll]*R[cells[ii][ll]][1];
01448                                   a3[kk] += Q[kk][ll]*R[cells[ii][ll]][2];
01449                                 }
01450 
01451                             double det = jac3(a1[0], a1[1], a1[2],
01452                                               a2[0], a2[1], a2[2],
01453                                               a3[0], a3[1], a3[2]);
01454                             double sigma = 0.;
01455 
01456                             if ((i==j) && (j==k))
01457                               sigma = 1./120.;
01458                             else if ((i==j) || (j==k) || (i==k))
01459                               sigma = 1./360.;
01460                             else
01461                               sigma = 1./720.;
01462 
01463                             double tr = 0;
01464                             for (int kk=0; kk<3; kk++)
01465                               tr += (a1[kk]*a1[kk] + a2[kk]*a2[kk] + a3[kk]*a3[kk])/3.;
01466 
01467                             double chi = 0.5*(det+std::sqrt(det*det+epsilon*epsilon));
01468                             E += ((1-w)*pow(tr,1.5)/chi + 0.5*w*(v+det*det/v)/chi)*sigma;
01469                             if (vmin > det)
01470                               vmin = det;
01471                           }
01472                       }
01473                   }
01474 
01475                 if (E > gemax)
01476                   gemax = E;
01477               }
01478           }
01479         Gamma[ii] = E;
01480       }
01481 
01482   qmin = vmin;
01483 
01484   return gemax;
01485 }
01486 
01487 
01488 
01489 // Compute min Jacobian determinant (minq), min cell volume (Vmin), and average cell volume (vol).
01490 double VariationalMeshSmoother::minq(const Array2D<double>& R,
01491                                      const Array2D<int>& cells,
01492                                      const std::vector<int>& mcells,
01493                                      int me,
01494                                      const Array3D<double>& H,
01495                                      double& vol,
01496                                      double& Vmin)
01497 {
01498   std::vector<double> K(9);
01499   Array2D<double> Q(3, 3*_dim + _dim%2);
01500 
01501   double v = 0;
01502   double vmin = 1.e32;
01503   double gqmin = 1.e32;
01504 
01505   for (dof_id_type ii=0; ii<_n_cells; ii++)
01506     if (mcells[ii] >= 0)
01507       {
01508         if (_dim == 2)
01509           {
01510             // 2D
01511             if (cells[ii][3] == -1)
01512               {
01513                 // tri
01514                 basisA(Q, 3, K, H[ii], me);
01515 
01516                 std::vector<double> a1(3), a2(3);
01517                 for (int k=0; k<2; k++)
01518                   for (int l=0; l<3; l++)
01519                     {
01520                       a1[k] += Q[k][l]*R[cells[ii][l]][0];
01521                       a2[k] += Q[k][l]*R[cells[ii][l]][1];
01522                     }
01523 
01524                 double det = jac2(a1[0],a1[1],a2[0],a2[1]);
01525                 if (gqmin > det)
01526                   gqmin = det;
01527 
01528                 if (vmin > det)
01529                   vmin = det;
01530 
01531                 v += det;
01532               }
01533             else if (cells[ii][4] == -1)
01534               {
01535                 // quad
01536                 double vcell = 0.;
01537                 for (int i=0; i<2; i++)
01538                   {
01539                     K[0] = i;
01540                     for (int j=0; j<2; j++)
01541                       {
01542                         K[1] = j;
01543                         basisA(Q, 4, K, H[ii], me);
01544 
01545                         std::vector<double> a1(3), a2(3);
01546                         for (int k=0; k<2; k++)
01547                           for (int l=0; l<4; l++)
01548                             {
01549                               a1[k] += Q[k][l]*R[cells[ii][l]][0];
01550                               a2[k] += Q[k][l]*R[cells[ii][l]][1];
01551                             }
01552 
01553                         double det = jac2(a1[0],a1[1],a2[0],a2[1]);
01554                         if (gqmin > det)
01555                           gqmin = det;
01556 
01557                         v += 0.25*det;
01558                         vcell += 0.25*det;
01559                       }
01560                   }
01561                 if (vmin > vcell)
01562                   vmin = vcell;
01563               }
01564             else
01565               {
01566                 // quad tri
01567                 double vcell = 0.;
01568                 for (int i=0; i<3; i++)
01569                   {
01570                     K[0] = i*0.5;
01571                     int k = i/2;
01572                     K[1] = static_cast<double>(k);
01573 
01574                     for (int j=0; j<3; j++)
01575                       {
01576                         K[2] = j*0.5;
01577                         k = j/2;
01578                         K[3] = static_cast<double>(k);
01579                         basisA(Q, 6, K, H[ii], me);
01580 
01581                         std::vector<double> a1(3), a2(3);
01582                         for (int k=0; k<2; k++)
01583                           for (int l=0; l<6; l++)
01584                             {
01585                               a1[k] += Q[k][l]*R[cells[ii][l]][0];
01586                               a2[k] += Q[k][l]*R[cells[ii][l]][1];
01587                             }
01588 
01589                         double det = jac2(a1[0], a1[1], a2[0], a2[1]);
01590                         if (gqmin > det)
01591                           gqmin = det;
01592 
01593                         double sigma = 1./24.;
01594                         if (i == j)
01595                           sigma = 1./12.;
01596 
01597                         v += sigma*det;
01598                         vcell += sigma*det;
01599                       }
01600                   }
01601                 if (vmin > vcell)
01602                   vmin = vcell;
01603               }
01604           }
01605         if (_dim == 3)
01606           {
01607             // 3D
01608             if (cells[ii][4] == -1)
01609               {
01610                 // tetr
01611                 basisA(Q, 4, K, H[ii], me);
01612 
01613                 std::vector<double> a1(3), a2(3), a3(3);
01614                 for (int k=0; k<3; k++)
01615                   for (int l=0; l<4; l++)
01616                     {
01617                       a1[k] += Q[k][l]*R[cells[ii][l]][0];
01618                       a2[k] += Q[k][l]*R[cells[ii][l]][1];
01619                       a3[k] += Q[k][l]*R[cells[ii][l]][2];
01620                     }
01621 
01622                 double det = jac3(a1[0], a1[1], a1[2],
01623                                   a2[0], a2[1], a2[2],
01624                                   a3[0], a3[1], a3[2]);
01625 
01626                 if (gqmin > det)
01627                   gqmin = det;
01628 
01629                 if (vmin > det)
01630                   vmin = det;
01631                 v += det;
01632               }
01633             else if (cells[ii][6] == -1)
01634               {
01635                 // prism
01636                 double vcell = 0.;
01637                 for (int i=0; i<2; i++)
01638                   {
01639                     K[0] = i;
01640                     for (int j=0; j<2; j++)
01641                       {
01642                         K[1] = j;
01643 
01644                         for (int k=0; k<3; k++)
01645                           {
01646                             K[2] = 0.5*k;
01647                             K[3] = static_cast<double>(k%2);
01648                             basisA(Q, 6, K, H[ii], me);
01649 
01650                             std::vector<double> a1(3), a2(3), a3(3);
01651                             for (int kk=0; kk<3; kk++)
01652                               for (int ll=0; ll<6; ll++)
01653                                 {
01654                                   a1[kk] += Q[kk][ll]*R[cells[ii][ll]][0];
01655                                   a2[kk] += Q[kk][ll]*R[cells[ii][ll]][1];
01656                                   a3[kk] += Q[kk][ll]*R[cells[ii][ll]][2];
01657                                 }
01658 
01659                             double det = jac3(a1[0], a1[1], a1[2],
01660                                               a2[0], a2[1], a2[2],
01661                                               a3[0], a3[1], a3[2]);
01662                             if (gqmin > det)
01663                               gqmin = det;
01664 
01665                             double sigma = 1./12.;
01666                             v += sigma*det;
01667                             vcell += sigma*det;
01668                           }
01669                       }
01670                   }
01671                 if (vmin > vcell)
01672                   vmin = vcell;
01673               }
01674             else if (cells[ii][8] == -1)
01675               {
01676                 // hex
01677                 double vcell = 0.;
01678                 for (int i=0; i<2; i++)
01679                   {
01680                     K[0] = i;
01681                     for (int j=0; j<2; j++)
01682                       {
01683                         K[1] = j;
01684                         for (int k=0; k<2; k++)
01685                           {
01686                             K[2] = k;
01687                             for (int l=0; l<2; l++)
01688                               {
01689                                 K[3] = l;
01690                                 for (int m=0; m<2; m++)
01691                                   {
01692                                     K[4] = m;
01693                                     for (int nn=0; nn<2; nn++)
01694                                       {
01695                                         K[5] = nn;
01696                                         basisA(Q, 8, K, H[ii], me);
01697 
01698                                         std::vector<double> a1(3), a2(3), a3(3);
01699                                         for (int kk=0; kk<3; kk++)
01700                                           for (int ll=0; ll<8; ll++)
01701                                             {
01702                                               a1[kk] += Q[kk][ll]*R[cells[ii][ll]][0];
01703                                               a2[kk] += Q[kk][ll]*R[cells[ii][ll]][1];
01704                                               a3[kk] += Q[kk][ll]*R[cells[ii][ll]][2];
01705                                             }
01706 
01707                                         double det = jac3(a1[0], a1[1], a1[2],
01708                                                           a2[0], a2[1], a2[2],
01709                                                           a3[0], a3[1], a3[2]);
01710 
01711                                         if (gqmin > det)
01712                                           gqmin = det;
01713 
01714                                         double sigma = 0.;
01715 
01716                                         if ((i==nn) && (j==l) && (k==m))
01717                                           sigma = 1./27.;
01718 
01719                                         if (((i==nn) && (j==l) && (k!=m)) ||
01720                                             ((i==nn) && (j!=l) && (k==m)) ||
01721                                             ((i!=nn) && (j==l) && (k==m)))
01722                                           sigma = 1./54.;
01723 
01724                                         if (((i==nn) && (j!=l) && (k!=m)) ||
01725                                             ((i!=nn) && (j!=l) && (k==m)) ||
01726                                             ((i!=nn) && (j==l) && (k!=m)))
01727                                           sigma = 1./108.;
01728 
01729                                         if ((i!=nn) && (j!=l) && (k!=m))
01730                                           sigma = 1./216.;
01731 
01732                                         v += sigma*det;
01733                                         vcell += sigma*det;
01734                                       }
01735                                   }
01736                               }
01737                           }
01738                       }
01739                   }
01740 
01741                 if (vmin > vcell)
01742                   vmin = vcell;
01743               }
01744             else
01745               {
01746                 // quad tetr
01747                 double vcell = 0.;
01748                 for (int i=0; i<4; i++)
01749                   {
01750                     for (int j=0; j<4; j++)
01751                       {
01752                         for (int k=0; k<4; k++)
01753                           {
01754                             switch (i)
01755                               {
01756                               case 0:
01757                                 K[0] = 0;
01758                                 K[1] = 0;
01759                                 K[2] = 0;
01760                                 break;
01761 
01762                               case 1:
01763                                 K[0] = 1;
01764                                 K[1] = 0;
01765                                 K[2] = 0;
01766                                 break;
01767 
01768                               case 2:
01769                                 K[0] = 0.5;
01770                                 K[1] = 1;
01771                                 K[2] = 0;
01772                                 break;
01773 
01774                               case 3:
01775                                 K[0] = 0.5;
01776                                 K[1] = 1./3.;
01777                                 K[2] = 1;
01778                                 break;
01779 
01780                               }
01781                             switch (j)
01782                               {
01783                               case 0:
01784                                 K[3] = 0;
01785                                 K[4] = 0;
01786                                 K[5] = 0;
01787                                 break;
01788 
01789                               case 1:
01790                                 K[3] = 1;
01791                                 K[4] = 0;
01792                                 K[5] = 0;
01793                                 break;
01794 
01795                               case 2:
01796                                 K[3] = 0.5;
01797                                 K[4] = 1;
01798                                 K[5] = 0;
01799                                 break;
01800 
01801                               case 3:
01802                                 K[3] = 0.5;
01803                                 K[4] = 1./3.;
01804                                 K[5] = 1;
01805                                 break;
01806 
01807                               }
01808                             switch (k)
01809                               {
01810                               case 0:
01811                                 K[6] = 0;
01812                                 K[7] = 0;
01813                                 K[8] = 0;
01814                                 break;
01815 
01816                               case 1:
01817                                 K[6] = 1;
01818                                 K[7] = 0;
01819                                 K[8] = 0;
01820                                 break;
01821 
01822                               case 2:
01823                                 K[6] = 0.5;
01824                                 K[7] = 1;
01825                                 K[8] = 0;
01826                                 break;
01827 
01828                               case 3:
01829                                 K[6] = 0.5;
01830                                 K[7] = 1./3.;
01831                                 K[8] = 1;
01832                                 break;
01833                               }
01834 
01835                             basisA(Q, 10, K, H[ii], me);
01836 
01837                             std::vector<double> a1(3), a2(3), a3(3);
01838                             for (int kk=0; kk<3; kk++)
01839                               for (int ll=0; ll<10; ll++)
01840                                 {
01841                                   a1[kk] += Q[kk][ll]*R[cells[ii][ll]][0];
01842                                   a2[kk] += Q[kk][ll]*R[cells[ii][ll]][1];
01843                                   a3[kk] += Q[kk][ll]*R[cells[ii][ll]][2];
01844                                 }
01845 
01846                             double det = jac3(a1[0], a1[1], a1[2],
01847                                               a2[0], a2[1], a2[2],
01848                                               a3[0], a3[1], a3[2]);
01849                             if (gqmin > det)
01850                               gqmin = det;
01851 
01852                             double sigma = 0.;
01853 
01854                             if ((i==j) && (j==k))
01855                               sigma = 1./120.;
01856 
01857                             else if ((i==j) || (j==k) || (i==k))
01858                               sigma = 1./360.;
01859 
01860                             else
01861                               sigma = 1./720.;
01862 
01863                             v += sigma*det;
01864                             vcell += sigma*det;
01865                           }
01866                       }
01867                   }
01868                 if (vmin > vcell)
01869                   vmin = vcell;
01870               }
01871           }
01872       }
01873 
01874   // Fill in return value references
01875   vol = v/static_cast<double>(_n_cells);
01876   Vmin = vmin;
01877 
01878   return gqmin;
01879 }
01880 
01881 
01882 
01883 // Executes one step of minimization algorithm:
01884 // finds minimization direction (P=H^{-1} \grad J) and solves approximately
01885 // local minimization problem for optimal step in this minimization direction (tau=min J(R+tau P))
01886 double VariationalMeshSmoother::minJ(Array2D<double>& R,
01887                                      const std::vector<int>& mask,
01888                                      const Array2D<int>& cells,
01889                                      const std::vector<int>& mcells,
01890                                      double epsilon,
01891                                      double w,
01892                                      int me,
01893                                      const Array3D<double>& H,
01894                                      double vol,
01895                                      const std::vector<int>& edges,
01896                                      const std::vector<int>& hnodes,
01897                                      int msglev,
01898                                      double& Vmin,
01899                                      double& emax,
01900                                      double& qmin,
01901                                      int adp,
01902                                      const std::vector<double>& afun)
01903 {
01904   // columns - max number of nonzero entries in every row of global matrix
01905   int columns = _dim*_dim*10;
01906 
01907   // local Hessian matrix
01908   Array3D<double> W(_dim, 3*_dim + _dim%2, 3*_dim + _dim%2);
01909 
01910   // F - local gradient
01911   Array2D<double> F(_dim, 3*_dim + _dim%2);
01912 
01913   Array2D<double> Rpr(_n_nodes, _dim);
01914 
01915   // P - minimization direction
01916   Array2D<double> P(_n_nodes, _dim);
01917 
01918   // A, JA - internal form of global matrix
01919   Array2D<int> JA(_dim*_n_nodes, columns);
01920   Array2D<double> A(_dim*_n_nodes, columns);
01921 
01922   // G - adaptation metric
01923   Array2D<double> G(_n_cells, _dim);
01924 
01925   // rhs for solver
01926   std::vector<double> b(_dim*_n_nodes);
01927 
01928   // u - solution vector
01929   std::vector<double> u(_dim*_n_nodes);
01930 
01931   // matrix
01932   std::vector<double> a(_dim*_n_nodes*columns);
01933   std::vector<int> ia(_dim*_n_nodes + 1);
01934   std::vector<int> ja(_dim*_n_nodes*columns);
01935 
01936   // nonzero - norm of gradient
01937   double nonzero = 0.;
01938 
01939   // Jpr - value of functional
01940   double Jpr = 0.;
01941 
01942   // find minimization direction P
01943   for (dof_id_type i=0; i<_n_cells; i++)
01944     {
01945       int nvert = 0;
01946       while (cells[i][nvert] >= 0)
01947         nvert++;
01948 
01949       // determination of local matrices on each cell
01950       for (unsigned j=0; j<_dim; j++)
01951         {
01952           G[i][j] = 0;  // adaptation metric G is held constant throughout minJ run
01953           if (adp < 0)
01954             {
01955               for (int k=0; k<std::abs(adp); k++)
01956                 G[i][j] += afun[i*(-adp)+k];  // cell-based adaptivity is computed here
01957             }
01958         }
01959       for (unsigned index=0; index<_dim; index++)
01960         {
01961           // initialise local matrices
01962           for (unsigned k=0; k<3*_dim + _dim%2; k++)
01963             {
01964               F[index][k] = 0;
01965 
01966               for (unsigned j=0; j<3*_dim + _dim%2; j++)
01967                 W[index][k][j] = 0;
01968             }
01969         }
01970       if (mcells[i] >= 0)
01971         {
01972           // if cell is not excluded
01973           double lVmin, lqmin;
01974           Jpr += localP(W, F, R, cells[i], mask, epsilon, w, nvert, H[i],
01975                         me, vol, 0, lVmin, lqmin, adp, afun, G[i]);
01976         }
01977       else
01978         {
01979           for (unsigned index=0; index<_dim; index++)
01980             for (int j=0; j<nvert; j++)
01981               W[index][j][j] = 1;
01982         }
01983 
01984       // assembly of an upper triangular part of a global matrix A
01985       for (unsigned index=0; index<_dim; index++)
01986         {
01987           for (int l=0; l<nvert; l++)
01988             {
01989               for (int m=0; m<nvert; m++)
01990                 {
01991                   if ((W[index][l][m] != 0) &&
01992                       (cells[i][m] >= cells[i][l]))
01993                     {
01994                       int sch = 0;
01995                       int ind = 1;
01996                       while (ind != 0)
01997                         {
01998                           if (A[cells[i][l] + index*_n_nodes][sch] != 0)
01999                             {
02000                               if (JA[cells[i][l] + index*_n_nodes][sch] == static_cast<int>(cells[i][m] + index*_n_nodes))
02001                                 {
02002                                   A[cells[i][l] + index*_n_nodes][sch] = A[cells[i][l] + index*_n_nodes][sch] + W[index][l][m];
02003                                   ind=0;
02004                                 }
02005                               else
02006                                 sch++;
02007                             }
02008                           else
02009                             {
02010                               A[cells[i][l] + index*_n_nodes][sch] = W[index][l][m];
02011                               JA[cells[i][l] + index*_n_nodes][sch] = cells[i][m] + index*_n_nodes;
02012                               ind = 0;
02013                             }
02014 
02015                           if (sch > columns-1)
02016                             _logfile << "error: # of nonzero entries in the "
02017                                      << cells[i][l]
02018                                      << " row of Hessian ="
02019                                      << sch
02020                                      << ">= columns="
02021                                      << columns
02022                                      << std::endl;
02023                         }
02024                     }
02025                 }
02026               b[cells[i][l] + index*_n_nodes] = b[cells[i][l] + index*_n_nodes] - F[index][l];
02027             }
02028         }
02029       // end of matrix A
02030     }
02031 
02032   // HN correction
02033 
02034   // tolerance for HN being the mid-edge node for its parents
02035   double Tau_hn = pow(vol, 1./static_cast<double>(_dim))*1e-10;
02036   for (dof_id_type i=0; i<_n_hanging_edges; i++)
02037     {
02038       int ind_i = hnodes[i];
02039       int ind_j = edges[2*i];
02040       int ind_k = edges[2*i+1];
02041 
02042       for (unsigned j=0; j<_dim; j++)
02043         {
02044           int g_i = R[ind_i][j] - 0.5*(R[ind_j][j]+R[ind_k][j]);
02045           Jpr += g_i*g_i/(2*Tau_hn);
02046           b[ind_i + j*_n_nodes] -= g_i/Tau_hn;
02047           b[ind_j + j*_n_nodes] += 0.5*g_i/Tau_hn;
02048           b[ind_k + j*_n_nodes] += 0.5*g_i/Tau_hn;
02049         }
02050 
02051       for (int ind=0; ind<columns; ind++)
02052         {
02053           if (JA[ind_i][ind] == ind_i)
02054             A[ind_i][ind] += 1./Tau_hn;
02055 
02056           if (JA[ind_i+_n_nodes][ind] == static_cast<int>(ind_i+_n_nodes))
02057             A[ind_i+_n_nodes][ind] += 1./Tau_hn;
02058 
02059           if (_dim == 3)
02060             if (JA[ind_i+2*_n_nodes][ind] == static_cast<int>(ind_i+2*_n_nodes))
02061               A[ind_i+2*_n_nodes][ind] += 1./Tau_hn;
02062 
02063           if ((JA[ind_i][ind] == ind_j) ||
02064               (JA[ind_i][ind] == ind_k))
02065             A[ind_i][ind] -= 0.5/Tau_hn;
02066 
02067           if ((JA[ind_i+_n_nodes][ind] == static_cast<int>(ind_j+_n_nodes)) ||
02068               (JA[ind_i+_n_nodes][ind] == static_cast<int>(ind_k+_n_nodes)))
02069             A[ind_i+_n_nodes][ind] -= 0.5/Tau_hn;
02070 
02071           if (_dim == 3)
02072             if ((JA[ind_i+2*_n_nodes][ind] == static_cast<int>(ind_j+2*_n_nodes)) ||
02073                 (JA[ind_i+2*_n_nodes][ind] == static_cast<int>(ind_k+2*_n_nodes)))
02074               A[ind_i+2*_n_nodes][ind] -= 0.5/Tau_hn;
02075 
02076           if (JA[ind_j][ind] == ind_i)
02077             A[ind_j][ind] -= 0.5/Tau_hn;
02078 
02079           if (JA[ind_k][ind] == ind_i)
02080             A[ind_k][ind] -= 0.5/Tau_hn;
02081 
02082           if (JA[ind_j+_n_nodes][ind] == static_cast<int>(ind_i+_n_nodes))
02083             A[ind_j+_n_nodes][ind] -= 0.5/Tau_hn;
02084 
02085           if (JA[ind_k+_n_nodes][ind] == static_cast<int>(ind_i+_n_nodes))
02086             A[ind_k+_n_nodes][ind] -= 0.5/Tau_hn;
02087 
02088           if (_dim == 3)
02089             if (JA[ind_j+2*_n_nodes][ind] == static_cast<int>(ind_i+2*_n_nodes))
02090               A[ind_j+2*_n_nodes][ind] -= 0.5/Tau_hn;
02091 
02092           if (_dim == 3)
02093             if (JA[ind_k+2*_n_nodes][ind] == static_cast<int>(ind_i+2*_n_nodes))
02094               A[ind_k+2*_n_nodes][ind] -= 0.5/Tau_hn;
02095 
02096           if ((JA[ind_j][ind] == ind_j) ||
02097               (JA[ind_j][ind] == ind_k))
02098             A[ind_j][ind] += 0.25/Tau_hn;
02099 
02100           if ((JA[ind_k][ind] == ind_j) ||
02101               (JA[ind_k][ind] == ind_k))
02102             A[ind_k][ind] += 0.25/Tau_hn;
02103 
02104           if ((JA[ind_j+_n_nodes][ind] == static_cast<int>(ind_j+_n_nodes)) ||
02105               (JA[ind_j+_n_nodes][ind] == static_cast<int>(ind_k+_n_nodes)))
02106             A[ind_j+_n_nodes][ind] += 0.25/Tau_hn;
02107 
02108           if ((JA[ind_k+_n_nodes][ind] == static_cast<int>(ind_j+_n_nodes)) ||
02109               (JA[ind_k+_n_nodes][ind] == static_cast<int>(ind_k+_n_nodes)))
02110             A[ind_k+_n_nodes][ind] += 0.25/Tau_hn;
02111 
02112           if (_dim == 3)
02113             if ((JA[ind_j+2*_n_nodes][ind] == static_cast<int>(ind_j+2*_n_nodes)) ||
02114                 (JA[ind_j+2*_n_nodes][ind] == static_cast<int>(ind_k+2*_n_nodes)))
02115               A[ind_j+2*_n_nodes][ind] += 0.25/Tau_hn;
02116 
02117           if (_dim==3)
02118             if ((JA[ind_k+2*_n_nodes][ind] == static_cast<int>(ind_j+2*_n_nodes)) ||
02119                 (JA[ind_k+2*_n_nodes][ind] == static_cast<int>(ind_k+2*_n_nodes)))
02120               A[ind_k+2*_n_nodes][ind] += 0.25/Tau_hn;
02121         }
02122     }
02123 
02124   // ||\grad J||_2
02125   for (dof_id_type i=0; i<_dim*_n_nodes; i++)
02126     nonzero += b[i]*b[i];
02127 
02128   // sort matrix A
02129   for (dof_id_type i=0; i<_dim*_n_nodes; i++)
02130     {
02131       for (int j=columns-1; j>1; j--)
02132         {
02133           for (int k=0; k<j; k++)
02134             {
02135               if (JA[i][k] > JA[i][k+1])
02136                 {
02137                   int sch = JA[i][k];
02138                   JA[i][k] = JA[i][k+1];
02139                   JA[i][k+1] = sch;
02140                   double tmp = A[i][k];
02141                   A[i][k] = A[i][k+1];
02142                   A[i][k+1] = tmp;
02143                 }
02144             }
02145         }
02146     }
02147 
02148   double eps = std::sqrt(vol)*1e-9;
02149 
02150   // solver for P (unconstrained)
02151   ia[0] = 0;
02152   {
02153     int j = 0;
02154     for (dof_id_type i=0; i<_dim*_n_nodes; i++)
02155       {
02156         u[i] = 0;
02157         int nz = 0;
02158         for (int k=0; k<columns; k++)
02159           {
02160             if (A[i][k] != 0)
02161               {
02162                 nz++;
02163                 ja[j] = JA[i][k]+1;
02164                 a[j] = A[i][k];
02165                 j++;
02166               }
02167           }
02168         ia[i+1] = ia[i] + nz;
02169       }
02170   }
02171 
02172   dof_id_type m = _dim*_n_nodes;
02173   int sch = (msglev >= 3) ? 1 : 0;
02174 
02175   solver(m, ia, ja, a, u, b, eps, 100, sch);
02176   // sol_pcg_pj(m, ia, ja, a, u, b, eps, 100, sch);
02177 
02178   for (dof_id_type i=0; i<_n_nodes; i++)
02179     {
02180       //ensure fixed nodes are not moved
02181       for (unsigned index=0; index<_dim; index++)
02182         if (mask[i] == 1)
02183           P[i][index] = 0;
02184         else
02185           P[i][index] = u[i+index*_n_nodes];
02186     }
02187 
02188   // P is determined
02189   if (msglev >= 4)
02190     {
02191       for (dof_id_type i=0; i<_n_nodes; i++)
02192         {
02193           for (unsigned j=0; j<_dim; j++)
02194             if (P[i][j] != 0)
02195               _logfile << "P[" << i << "][" << j << "]=" << P[i][j];
02196         }
02197     }
02198 
02199   // local minimization problem, determination of tau
02200   if (msglev >= 3)
02201     _logfile << "dJ=" << std::sqrt(nonzero) << " J0=" << Jpr << std::endl;
02202 
02203   double
02204     J = 1.e32,
02205     tau = 0.,
02206     gVmin = 0.,
02207     gemax = 0.,
02208     gqmin = 0.;
02209 
02210   int j = 1;
02211 
02212   while ((Jpr <= J) && (j > -30))
02213     {
02214       j = j-1;
02215 
02216       // search through finite # of values for tau
02217       tau = pow(2., j);
02218       for (dof_id_type i=0; i<_n_nodes; i++)
02219         for (unsigned k=0; k<_dim; k++)
02220           Rpr[i][k] = R[i][k] + tau*P[i][k];
02221 
02222       J = 0;
02223       gVmin = 1e32;
02224       gemax = -1e32;
02225       gqmin = 1e32;
02226       for (dof_id_type i=0; i<_n_cells; i++)
02227         {
02228           if (mcells[i] >= 0)
02229             {
02230               int nvert = 0;
02231               while (cells[i][nvert] >= 0)
02232                 nvert++;
02233 
02234               double lVmin, lqmin;
02235               double lemax = localP(W, F, Rpr, cells[i], mask, epsilon, w, nvert, H[i], me, vol, 1, lVmin, lqmin, adp, afun, G[i]);
02236 
02237               J += lemax;
02238               if (gVmin > lVmin)
02239                 gVmin = lVmin;
02240 
02241               if (gemax < lemax)
02242                 gemax = lemax;
02243 
02244               if (gqmin > lqmin)
02245                 gqmin = lqmin;
02246 
02247               // HN correction
02248               for (dof_id_type ii=0; ii<_n_hanging_edges; ii++)
02249                 {
02250                   int ind_i = hnodes[ii];
02251                   int ind_j = edges[2*ii];
02252                   int ind_k = edges[2*ii+1];
02253                   for (unsigned jj=0; jj<_dim; jj++)
02254                     {
02255                       int g_i = Rpr[ind_i][jj] - 0.5*(Rpr[ind_j][jj]+Rpr[ind_k][jj]);
02256                       J += g_i*g_i/(2*Tau_hn);
02257                     }
02258                 }
02259             }
02260         }
02261       if (msglev >= 3)
02262         _logfile << "tau=" << tau << " J=" << J << std::endl;
02263     }
02264 
02265 
02266   double
02267     T = 0.,
02268     gtmin0 = 0.,
02269     gtmax0 = 0.,
02270     gqmin0 = 0.;
02271 
02272   if (j != -30)
02273     {
02274       Jpr = J;
02275       for (unsigned i=0; i<_n_nodes; i++)
02276         for (unsigned k=0; k<_dim; k++)
02277           Rpr[i][k] = R[i][k] + tau*0.5*P[i][k];
02278 
02279       J = 0;
02280       gtmin0 = 1e32;
02281       gtmax0 = -1e32;
02282       gqmin0 = 1e32;
02283       for (dof_id_type i=0; i<_n_cells; i++)
02284         {
02285           if (mcells[i] >= 0)
02286             {
02287               int nvert = 0;
02288               while (cells[i][nvert] >= 0)
02289                 nvert++;
02290 
02291               double lVmin, lqmin;
02292               double lemax = localP(W, F, Rpr, cells[i], mask, epsilon, w, nvert, H[i], me, vol, 1, lVmin, lqmin, adp, afun, G[i]);
02293               J += lemax;
02294 
02295               if (gtmin0 > lVmin)
02296                 gtmin0 = lVmin;
02297 
02298               if (gtmax0 < lemax)
02299                 gtmax0 = lemax;
02300 
02301               if (gqmin0 > lqmin)
02302                 gqmin0 = lqmin;
02303 
02304               // HN correction
02305               for (dof_id_type ii=0; ii<_n_hanging_edges; ii++)
02306                 {
02307                   int ind_i = hnodes[ii];
02308                   int ind_j = edges[2*ii];
02309                   int ind_k = edges[2*ii+1];
02310 
02311                   for (unsigned jj=0; jj<_dim; jj++)
02312                     {
02313                       int g_i = Rpr[ind_i][jj] - 0.5*(Rpr[ind_j][jj] + Rpr[ind_k][jj]);
02314                       J += g_i*g_i/(2*Tau_hn);
02315                     }
02316                 }
02317             }
02318         }
02319     }
02320 
02321   if (Jpr > J)
02322     {
02323       T = 0.5*tau;
02324       // Set up return values passed by reference
02325       Vmin = gtmin0;
02326       emax = gtmax0;
02327       qmin = gqmin0;
02328     }
02329   else
02330     {
02331       T = tau;
02332       J = Jpr;
02333       // Set up return values passed by reference
02334       Vmin = gVmin;
02335       emax = gemax;
02336       qmin = gqmin;
02337     }
02338 
02339   nonzero = 0;
02340   for (dof_id_type j=0; j<_n_nodes; j++)
02341     for (unsigned k=0; k<_dim; k++)
02342       {
02343         R[j][k] = R[j][k] + T*P[j][k];
02344         nonzero += T*P[j][k]*T*P[j][k];
02345       }
02346 
02347   if (msglev >= 2)
02348     _logfile << "tau=" << T << ", J=" << J << std::endl;
02349 
02350   return std::sqrt(nonzero);
02351 }
02352 
02353 
02354 
02355 // minJ() with sliding Boundary Nodes constraints and no account for HN,
02356 // using Lagrange multiplier formulation: minimize L=J+\sum lam*g;
02357 // only works in 2D
02358 double VariationalMeshSmoother::minJ_BC(Array2D<double>& R,
02359                                         const std::vector<int>& mask,
02360                                         const Array2D<int>& cells,
02361                                         const std::vector<int>& mcells,
02362                                         double epsilon,
02363                                         double w,
02364                                         int me,
02365                                         const Array3D<double>& H,
02366                                         double vol,
02367                                         int msglev,
02368                                         double& Vmin,
02369                                         double& emax,
02370                                         double& qmin,
02371                                         int adp,
02372                                         const std::vector<double>& afun,
02373                                         int NCN)
02374 {
02375   // new form of matrices, 5 iterations for minL
02376   double tau = 0., J = 0., T, Jpr, L, lVmin, lqmin, gVmin = 0., gqmin = 0., gVmin0 = 0.,
02377     gqmin0 = 0., lemax, gemax = 0., gemax0 = 0.;
02378 
02379   // array of sliding BN
02380   std::vector<int> Bind(NCN);
02381   std::vector<double> lam(NCN);
02382   std::vector<double> hm(2*_n_nodes);
02383   std::vector<double> Plam(NCN);
02384 
02385   // holds constraints = local approximation to the boundary
02386   std::vector<double> constr(4*NCN);
02387 
02388   Array2D<double> F(2, 6);
02389   Array3D<double> W(2, 6, 6);
02390   Array2D<double> Rpr(_n_nodes, 2);
02391   Array2D<double> P(_n_nodes, 2);
02392 
02393   std::vector<double> b(2*_n_nodes);
02394 
02395   Array2D<double> G(_n_cells, 6);
02396 
02397   // assembler of constraints
02398   const double eps = std::sqrt(vol)*1e-9;
02399 
02400   for (int i=0; i<4*NCN; i++)
02401     constr[i] = 1./eps;
02402 
02403   {
02404     int I = 0;
02405     for (dof_id_type i=0; i<_n_nodes; i++)
02406       if (mask[i] == 2)
02407         {
02408           Bind[I] = i;
02409           I++;
02410         }
02411   }
02412 
02413   for (int I=0; I<NCN; I++)
02414     {
02415       // The boundary connectivity loop sets up the j and k indices
02416       // but I am not sure about the logic of this: j and k are overwritten
02417       // at every iteration of the boundary connectivity loop and only used
02418       // *after* the boundary connectivity loop -- this seems like a bug but
02419       // I maintained the original behavior of the algorithm [JWP].
02420       int
02421         i = Bind[I],
02422         j = 0,
02423         k = 0,
02424         ind = 0;
02425 
02426       // boundary connectivity
02427       for (dof_id_type l=0; l<_n_cells; l++)
02428         {
02429           int nvert = 0;
02430 
02431           while (cells[l][nvert] >= 0)
02432             nvert++;
02433 
02434           switch (nvert)
02435             {
02436             case 3: // tri
02437               if (i == cells[l][0])
02438                 {
02439                   if (mask[cells[l][1]] > 0)
02440                     {
02441                       if (ind == 0)
02442                         j = cells[l][1];
02443                       else
02444                         k = cells[l][1];
02445                       ind++;
02446                     }
02447 
02448                   if (mask[cells[l][2]] > 0)
02449                     {
02450                       if (ind == 0)
02451                         j = cells[l][2];
02452                       else
02453                         k = cells[l][2];
02454                       ind++;
02455                     }
02456                 }
02457 
02458               if (i == cells[l][1])
02459                 {
02460                   if (mask[cells[l][0]] > 0)
02461                     {
02462                       if (ind == 0)
02463                         j = cells[l][0];
02464                       else
02465                         k = cells[l][0];
02466                       ind++;
02467                     }
02468 
02469                   if (mask[cells[l][2]] > 0)
02470                     {
02471                       if (ind == 0)
02472                         j = cells[l][2];
02473                       else
02474                         k = cells[l][2];
02475                       ind++;
02476                     }
02477                 }
02478 
02479               if (i == cells[l][2])
02480                 {
02481                   if (mask[cells[l][1]] > 0)
02482                     {
02483                       if (ind == 0)
02484                         j = cells[l][1];
02485                       else
02486                         k = cells[l][1];
02487                       ind++;
02488                     }
02489 
02490                   if (mask[cells[l][0]] > 0)
02491                     {
02492                       if (ind == 0)
02493                         j = cells[l][0];
02494                       else
02495                         k = cells[l][0];
02496                       ind++;
02497                     }
02498                 }
02499               break;
02500 
02501             case 4: // quad
02502               if ((i == cells[l][0]) ||
02503                   (i == cells[l][3]))
02504                 {
02505                   if (mask[cells[l][1]] > 0)
02506                     {
02507                       if (ind == 0)
02508                         j = cells[l][1];
02509                       else
02510                         k = cells[l][1];
02511                       ind++;
02512                     }
02513 
02514                   if (mask[cells[l][2]] > 0)
02515                     {
02516                       if (ind == 0)
02517                         j = cells[l][2];
02518                       else
02519                         k = cells[l][2];
02520                       ind++;
02521                     }
02522                 }
02523 
02524               if ((i == cells[l][1]) ||
02525                   (i == cells[l][2]))
02526                 {
02527                   if (mask[cells[l][0]] > 0)
02528                     {
02529                       if (ind == 0)
02530                         j = cells[l][0];
02531                       else
02532                         k = cells[l][0];
02533                       ind++;
02534                     }
02535 
02536                   if (mask[cells[l][3]] > 0)
02537                     {
02538                       if (ind == 0)
02539                         j = cells[l][3];
02540                       else
02541                         k = cells[l][3];
02542                       ind++;
02543                     }
02544                 }
02545               break;
02546 
02547             case 6: //quad tri
02548               if (i == cells[l][0])
02549                 {
02550                   if (mask[cells[l][1]] > 0)
02551                     {
02552                       if (ind == 0)
02553                         j = cells[l][5];
02554                       else
02555                         k = cells[l][5];
02556                       ind++;
02557                     }
02558 
02559                   if (mask[cells[l][2]] > 0)
02560                     {
02561                       if (ind == 0)
02562                         j = cells[l][4];
02563                       else
02564                         k = cells[l][4];
02565                       ind++;
02566                     }
02567                 }
02568 
02569               if (i == cells[l][1])
02570                 {
02571                   if (mask[cells[l][0]] > 0)
02572                     {
02573                       if (ind == 0)
02574                         j = cells[l][5];
02575                       else
02576                         k = cells[l][5];
02577                       ind++;
02578                     }
02579 
02580                   if (mask[cells[l][2]] > 0)
02581                     {
02582                       if (ind == 0)
02583                         j = cells[l][3];
02584                       else
02585                         k = cells[l][3];
02586                       ind++;
02587                     }
02588                 }
02589 
02590               if (i == cells[l][2])
02591                 {
02592                   if (mask[cells[l][1]] > 0)
02593                     {
02594                       if (ind == 0)
02595                         j = cells[l][3];
02596                       else
02597                         k = cells[l][3];
02598                       ind++;
02599                     }
02600 
02601                   if (mask[cells[l][0]] > 0)
02602                     {
02603                       if (ind == 0)
02604                         j = cells[l][4];
02605                       else
02606                         k = cells[l][4];
02607                       ind++;
02608                     }
02609                 }
02610 
02611               if (i == cells[l][3])
02612                 {
02613                   j = cells[l][1];
02614                   k = cells[l][2];
02615                 }
02616 
02617               if (i == cells[l][4])
02618                 {
02619                   j = cells[l][2];
02620                   k = cells[l][0];
02621                 }
02622 
02623               if (i == cells[l][5])
02624                 {
02625                   j = cells[l][0];
02626                   k = cells[l][1];
02627                 }
02628               break;
02629 
02630             default:
02631               libmesh_error_msg("Unrecognized nvert = " << nvert);
02632             }
02633         } // end boundary connectivity
02634 
02635       // lines
02636       double del1 = R[j][0] - R[i][0];
02637       double del2 = R[i][0] - R[k][0];
02638 
02639       if ((std::abs(del1) < eps) &&
02640           (std::abs(del2) < eps))
02641         {
02642           constr[I*4] = 1;
02643           constr[I*4+1] = 0;
02644           constr[I*4+2] = R[i][0];
02645           constr[I*4+3] = R[i][1];
02646         }
02647       else
02648         {
02649           del1 = R[j][1] - R[i][1];
02650           del2 = R[i][1] - R[k][1];
02651           if ((std::abs(del1) < eps) &&
02652               (std::abs(del2) < eps))
02653             {
02654               constr[I*4] = 0;
02655               constr[I*4+1] = 1;
02656               constr[I*4+2] = R[i][0];
02657               constr[I*4+3] = R[i][1];
02658             }
02659           else
02660             {
02661               J =
02662                 (R[i][0]-R[j][0])*(R[k][1]-R[j][1]) -
02663                 (R[k][0]-R[j][0])*(R[i][1]-R[j][1]);
02664 
02665               if (std::abs(J) < eps)
02666                 {
02667                   constr[I*4] = 1./(R[k][0]-R[j][0]);
02668                   constr[I*4+1] = -1./(R[k][1]-R[j][1]);
02669                   constr[I*4+2] = R[i][0];
02670                   constr[I*4+3] = R[i][1];
02671                 }
02672               else
02673                 {
02674                   // circle
02675                   double x0 = ((R[k][1]-R[j][1])*(R[i][0]*R[i][0]-R[j][0]*R[j][0]+R[i][1]*R[i][1]-R[j][1]*R[j][1]) +
02676                                (R[j][1]-R[i][1])*(R[k][0]*R[k][0]-R[j][0]*R[j][0]+R[k][1]*R[k][1]-R[j][1]*R[j][1]))/(2*J);
02677                   double y0 = ((R[j][0]-R[k][0])*(R[i][0]*R[i][0]-R[j][0]*R[j][0]+R[i][1]*R[i][1]-R[j][1]*R[j][1]) +
02678                                (R[i][0]-R[j][0])*(R[k][0]*R[k][0]-R[j][0]*R[j][0]+R[k][1]*R[k][1]-R[j][1]*R[j][1]))/(2*J);
02679                   constr[I*4] = x0;
02680                   constr[I*4+1] = y0;
02681                   constr[I*4+2] = (R[i][0]-x0)*(R[i][0]-x0) + (R[i][1]-y0)*(R[i][1]-y0);
02682                 }
02683             }
02684         }
02685     }
02686 
02687   // for (int i=0; i<NCN; i++){
02688   // for (int j=0; j<4; j++) fprintf(stdout," %e ",constr[4*i+j]);
02689   // fprintf(stdout, "constr %d node %d \n",i,Bind[i]);
02690   // }
02691 
02692   // initial values
02693   for (int i=0; i<NCN; i++)
02694     lam[i] = 0;
02695 
02696   // Eventual return value
02697   double nonzero = 0.;
02698 
02699   // Temporary result variable
02700   double qq = 0.;
02701 
02702   for (int nz=0; nz<5; nz++)
02703     {
02704       // find H and -grad J
02705       nonzero = 0.;
02706       Jpr = 0;
02707       for (dof_id_type i=0; i<2*_n_nodes; i++)
02708         {
02709           b[i] = 0;
02710           hm[i] = 0;
02711         }
02712 
02713       for (dof_id_type i=0; i<_n_cells; i++)
02714         {
02715           int nvert = 0;
02716 
02717           while (cells[i][nvert] >= 0)
02718             nvert++;
02719 
02720           for (int j=0; j<nvert; j++)
02721             {
02722               G[i][j] = 0;
02723               if (adp < 0)
02724                 for (int k=0; k<std::abs(adp); k++)
02725                   G[i][j] += afun[i*(-adp) + k];
02726             }
02727 
02728           for (int index=0; index<2; index++)
02729             for (int k=0; k<nvert; k++)
02730               {
02731                 F[index][k] = 0;
02732                 for (int j=0; j<nvert; j++)
02733                   W[index][k][j] = 0;
02734               }
02735 
02736           if (mcells[i] >= 0)
02737             Jpr += localP(W, F, R, cells[i], mask, epsilon, w, nvert, H[i],
02738                           me, vol, 0, lVmin, lqmin, adp, afun, G[i]);
02739 
02740           else
02741             {
02742               for (unsigned index=0; index<2; index++)
02743                 for (int j=0; j<nvert; j++)
02744                   W[index][j][j] = 1;
02745             }
02746 
02747           for (unsigned index=0; index<2; index++)
02748             for (int l=0; l<nvert; l++)
02749               {
02750                 // diagonal Hessian
02751                 hm[cells[i][l] + index*_n_nodes] += W[index][l][l];
02752                 b[cells[i][l] + index*_n_nodes] -= F[index][l];
02753               }
02754         }
02755 
02756       // ||grad J||_2
02757       for (dof_id_type i=0; i<2*_n_nodes; i++)
02758         nonzero += b[i]*b[i];
02759 
02760       // solve for Plam
02761       for (int I=0; I<NCN; I++)
02762         {
02763           int i = Bind[I];
02764           double
02765             Bx = 0.,
02766             By = 0.,
02767             g = 0.;
02768 
02769           if (constr[4*I+3] < 0.5/eps)
02770             {
02771               Bx = constr[4*I];
02772               By = constr[4*I+1];
02773               g = (R[i][0]-constr[4*I+2])*constr[4*I] + (R[i][1]-constr[4*I+3])*constr[4*I+1];
02774             }
02775           else
02776             {
02777               Bx = 2*(R[i][0] - constr[4*I]);
02778               By = 2*(R[i][1] - constr[4*I+1]);
02779               hm[i] += 2*lam[I];
02780               hm[i+_n_nodes] += 2*lam[I];
02781               g =
02782                 (R[i][0] - constr[4*I])*(R[i][0]-constr[4*I]) +
02783                 (R[i][1] - constr[4*I+1])*(R[i][1]-constr[4*I+1]) - constr[4*I+2];
02784             }
02785 
02786           Jpr += lam[I]*g;
02787           qq = Bx*b[i]/hm[i] + By*b[i+_n_nodes]/hm[i+_n_nodes] - g;
02788           double a = Bx*Bx/hm[i] + By*By/hm[i+_n_nodes];
02789 
02790           if (a != 0)
02791             Plam[I] = qq/a;
02792           else
02793             _logfile << "error: B^TH-1B is degenerate" << std::endl;
02794 
02795           b[i] -= Plam[I]*Bx;
02796           b[i+_n_nodes] -= Plam[I]*By;
02797           Plam[I] -= lam[I];
02798         }
02799 
02800       // solve for P
02801       for (dof_id_type i=0; i<_n_nodes; i++)
02802         {
02803           P[i][0] = b[i]/hm[i];
02804           P[i][1] = b[i+_n_nodes]/hm[i+_n_nodes];
02805         }
02806 
02807       // correct solution
02808       for (dof_id_type i=0; i<_n_nodes; i++)
02809         for (unsigned j=0; j<2; j++)
02810           if ((std::abs(P[i][j]) < eps) || (mask[i] == 1))
02811             P[i][j] = 0;
02812 
02813       // P is determined
02814       if (msglev >= 3)
02815         {
02816           for (dof_id_type i=0; i<_n_nodes; i++)
02817             for (unsigned j=0; j<2; j++)
02818               if (P[i][j] != 0)
02819                 _logfile << "P[" << i << "][" << j << "]=" << P[i][j] << "  ";
02820         }
02821 
02822       // local minimization problem, determination of tau
02823       if (msglev >= 3)
02824         _logfile << "dJ=" << std::sqrt(nonzero) << " L0=" << Jpr << std::endl;
02825 
02826       L = 1.e32;
02827       int j = 1;
02828 
02829       while ((Jpr <= L) && (j > -30))
02830         {
02831           j = j-1;
02832           tau = pow(2.,j);
02833           for (dof_id_type i=0; i<_n_nodes; i++)
02834             for (unsigned k=0; k<2; k++)
02835               Rpr[i][k] = R[i][k] + tau*P[i][k];
02836 
02837           J = 0;
02838           gVmin = 1.e32;
02839           gemax = -1.e32;
02840           gqmin = 1.e32;
02841           for (dof_id_type i=0; i<_n_cells; i++)
02842             if (mcells[i] >= 0)
02843               {
02844                 int nvert = 0;
02845                 while (cells[i][nvert] >= 0)
02846                   nvert++;
02847 
02848                 lemax = localP(W, F, Rpr, cells[i], mask, epsilon, w, nvert, H[i], me, vol, 1, lVmin,
02849                                lqmin, adp, afun, G[i]);
02850                 J += lemax;
02851 
02852                 if (gVmin > lVmin)
02853                   gVmin = lVmin;
02854 
02855                 if (gemax < lemax)
02856                   gemax = lemax;
02857 
02858                 if (gqmin > lqmin)
02859                   gqmin = lqmin;
02860               }
02861 
02862           L = J;
02863 
02864           // constraints contribution
02865           for (int I=0; I<NCN; I++)
02866             {
02867               int i = Bind[I];
02868               double g = 0.;
02869 
02870               if (constr[4*I+3] < 0.5/eps)
02871                 g = (Rpr[i][0] - constr[4*I+2])*constr[4*I] + (Rpr[i][1]-constr[4*I+3])*constr[4*I+1];
02872 
02873               else
02874                 g = (Rpr[i][0]-constr[4*I])*(Rpr[i][0]-constr[4*I]) +
02875                   (Rpr[i][1]-constr[4*I+1])*(Rpr[i][1]-constr[4*I+1]) - constr[4*I+2];
02876 
02877               L += (lam[I] + tau*Plam[I])*g;
02878             }
02879 
02880           // end of constraints
02881           if (msglev >= 3)
02882             _logfile << " tau=" << tau << " J=" << J << std::endl;
02883         } // end while
02884 
02885       if (j == -30)
02886         T = 0;
02887       else
02888         {
02889           Jpr = L;
02890           qq = J;
02891           for (dof_id_type i=0; i<_n_nodes; i++)
02892             for (unsigned k=0; k<2; k++)
02893               Rpr[i][k] = R[i][k] + tau*0.5*P[i][k];
02894 
02895           J = 0;
02896           gVmin0 = 1.e32;
02897           gemax0 = -1.e32;
02898           gqmin0 = 1.e32;
02899 
02900           for (dof_id_type i=0; i<_n_cells; i++)
02901             if (mcells[i] >= 0)
02902               {
02903                 int nvert = 0;
02904                 while (cells[i][nvert] >= 0)
02905                   nvert++;
02906 
02907                 lemax = localP(W, F, Rpr, cells[i], mask, epsilon, w, nvert, H[i], me, vol, 1, lVmin,
02908                                lqmin, adp, afun, G[i]);
02909                 J += lemax;
02910 
02911                 if (gVmin0 > lVmin)
02912                   gVmin0 = lVmin;
02913 
02914                 if (gemax0 < lemax)
02915                   gemax0 = lemax;
02916 
02917                 if (gqmin0 > lqmin)
02918                   gqmin0 = lqmin;
02919               }
02920 
02921           L = J;
02922 
02923           // constraints contribution
02924           for (int I=0; I<NCN; I++)
02925             {
02926               int i = Bind[I];
02927               double g = 0.;
02928 
02929               if (constr[4*I+3] < 0.5/eps)
02930                 g = (Rpr[i][0]-constr[4*I+2])*constr[4*I] + (Rpr[i][1]-constr[4*I+3])*constr[4*I+1];
02931 
02932               else
02933                 g = (Rpr[i][0]-constr[4*I])*(Rpr[i][0]-constr[4*I]) +
02934                   (Rpr[i][1]-constr[4*I+1])*(Rpr[i][1]-constr[4*I+1]) - constr[4*I+2];
02935 
02936               L += (lam[I] + tau*0.5*Plam[I])*g;
02937             }
02938           // end of constraints
02939         }
02940 
02941       if (Jpr > L)
02942         {
02943           T = 0.5*tau;
02944           // Set return values by reference
02945           Vmin = gVmin0;
02946           emax = gemax0;
02947           qmin = gqmin0;
02948         }
02949       else
02950         {
02951           T = tau;
02952           L = Jpr;
02953           J = qq;
02954           // Set return values by reference
02955           Vmin = gVmin;
02956           emax = gemax;
02957           qmin = gqmin;
02958         }
02959 
02960       for (dof_id_type i=0; i<_n_nodes; i++)
02961         for (unsigned k=0; k<2; k++)
02962           R[i][k] += T*P[i][k];
02963 
02964       for (int i=0; i<NCN; i++)
02965         lam[i] += T*Plam[i];
02966 
02967     } // end Lagrangian iter
02968 
02969   if (msglev >= 2)
02970     _logfile << "tau=" << T << ", J=" << J << ", L=" << L << std::endl;
02971 
02972   return std::sqrt(nonzero);
02973 }
02974 
02975 
02976 
02977 // composes local matrix W and right side F from all quadrature nodes of one cell
02978 double VariationalMeshSmoother::localP(Array3D<double>& W,
02979                                        Array2D<double>& F,
02980                                        Array2D<double>& R,
02981                                        const std::vector<int>& cell_in,
02982                                        const std::vector<int>& mask,
02983                                        double epsilon,
02984                                        double w,
02985                                        int nvert,
02986                                        const Array2D<double>& H,
02987                                        int me,
02988                                        double vol,
02989                                        int f,
02990                                        double& Vmin,
02991                                        double& qmin,
02992                                        int adp,
02993                                        const std::vector<double>& afun,
02994                                        std::vector<double>& Gloc)
02995 {
02996   // K - determines approximation rule for local integral over the cell
02997   std::vector<double> K(9);
02998 
02999   // f - flag, f=0 for determination of Hessian and gradient of the functional,
03000   // f=1 for determination of the functional value only;
03001   // adaptivity is determined on the first step for adp>0 (nodal based)
03002   if (f == 0)
03003     {
03004       if (adp > 0)
03005         avertex(afun, Gloc, R, cell_in, nvert, adp);
03006       if (adp == 0)
03007         {
03008           for (unsigned i=0; i<_dim; i++)
03009             Gloc[i] = 1.;
03010         }
03011     }
03012 
03013   double
03014     sigma = 0.,
03015     fun = 0,
03016     gqmin = 1e32,
03017     g = 0,  // Vmin
03018     lqmin = 0.;
03019 
03020   // cell integration depending on cell type
03021   if (_dim == 2)
03022     {
03023       // 2D
03024       if (nvert == 3)
03025         {
03026           // tri
03027           sigma = 1.;
03028           fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me, vol, f, lqmin, adp, Gloc, sigma);
03029           g += sigma*lqmin;
03030           if (gqmin > lqmin)
03031             gqmin = lqmin;
03032         }
03033       if (nvert == 4)
03034         {
03035           //quad
03036           for (unsigned i=0; i<2; i++)
03037             {
03038               K[0] = i;
03039               for (unsigned j=0; j<2; j++)
03040                 {
03041                   K[1] = j;
03042                   sigma = 0.25;
03043                   fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me,
03044                                 vol, f, lqmin, adp, Gloc, sigma);
03045                   g += sigma*lqmin;
03046                   if (gqmin > lqmin)
03047                     gqmin = lqmin;
03048                 }
03049             }
03050         }
03051       else
03052         {
03053           // quad tri
03054           for (unsigned i=0; i<3; i++)
03055             {
03056               K[0] = i*0.5;
03057               unsigned k = i/2;
03058               K[1] = static_cast<double>(k);
03059 
03060               for (unsigned j=0; j<3; j++)
03061                 {
03062                   K[2] = j*0.5;
03063                   k = j/2;
03064                   K[3] = static_cast<double>(k);
03065                   if (i == j)
03066                     sigma = 1./12.;
03067                   else
03068                     sigma = 1./24.;
03069 
03070                   fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me,
03071                                 vol, f, lqmin, adp, Gloc, sigma);
03072                   g += sigma*lqmin;
03073                   if (gqmin > lqmin)
03074                     gqmin = lqmin;
03075                 }
03076             }
03077         }
03078     }
03079   if (_dim == 3)
03080     {
03081       // 3D
03082       if (nvert == 4)
03083         {
03084           // tetr
03085           sigma = 1.;
03086           fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me,
03087                         vol, f, lqmin, adp, Gloc, sigma);
03088           g += sigma*lqmin;
03089           if (gqmin > lqmin)
03090             gqmin = lqmin;
03091         }
03092       if (nvert == 6)
03093         {
03094           //prism
03095           for (unsigned i=0; i<2; i++)
03096             {
03097               K[0] = i;
03098               for (unsigned j=0; j<2; j++)
03099                 {
03100                   K[1] = j;
03101                   for (unsigned k=0; k<3; k++)
03102                     {
03103                       K[2] = 0.5*static_cast<double>(k);
03104                       K[3] = static_cast<double>(k % 2);
03105                       sigma = 1./12.;
03106                       fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me,
03107                                     vol, f, lqmin, adp, Gloc, sigma);
03108                       g += sigma*lqmin;
03109                       if (gqmin > lqmin)
03110                         gqmin = lqmin;
03111                     }
03112                 }
03113             }
03114         }
03115       if (nvert == 8)
03116         {
03117           // hex
03118           for (unsigned i=0; i<2; i++)
03119             {
03120               K[0] = i;
03121               for (unsigned j=0; j<2; j++)
03122                 {
03123                   K[1] = j;
03124                   for (unsigned k=0; k<2; k++)
03125                     {
03126                       K[2] = k;
03127                       for (unsigned l=0; l<2; l++)
03128                         {
03129                           K[3] = l;
03130                           for (unsigned m=0; m<2; m++)
03131                             {
03132                               K[4] = m;
03133                               for (unsigned nn=0; nn<2; nn++)
03134                                 {
03135                                   K[5] = nn;
03136 
03137                                   if ((i==nn) && (j==l) && (k==m))
03138                                     sigma = 1./27.;
03139 
03140                                   if (((i==nn) && (j==l) && (k!=m)) ||
03141                                       ((i==nn) && (j!=l) && (k==m)) ||
03142                                       ((i!=nn) && (j==l) && (k==m)))
03143                                     sigma = 1./54.;
03144 
03145                                   if (((i==nn) && (j!=l) && (k!=m)) ||
03146                                       ((i!=nn) && (j!=l) && (k==m)) ||
03147                                       ((i!=nn) && (j==l) && (k!=m)))
03148                                     sigma = 1./108.;
03149 
03150                                   if ((i!=nn) && (j!=l) && (k!=m))
03151                                     sigma=1./216.;
03152 
03153                                   fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me,
03154                                                 vol, f, lqmin, adp, Gloc, sigma);
03155                                   g += sigma*lqmin;
03156 
03157                                   if (gqmin > lqmin)
03158                                     gqmin = lqmin;
03159                                 }
03160                             }
03161                         }
03162                     }
03163                 }
03164             }
03165         }
03166       else
03167         {
03168           // quad tetr
03169           for (unsigned i=0; i<4; i++)
03170             {
03171               for (unsigned j=0; j<4; j++)
03172                 {
03173                   for (unsigned k=0; k<4; k++)
03174                     {
03175                       switch (i)
03176                         {
03177                         case 0:
03178                           K[0] = 0;
03179                           K[1] = 0;
03180                           K[2] = 0;
03181                           break;
03182 
03183                         case 1:
03184                           K[0] = 1;
03185                           K[1] = 0;
03186                           K[2] = 0;
03187                           break;
03188 
03189                         case 2:
03190                           K[0] = 0.5;
03191                           K[1] = 1;
03192                           K[2] = 0;
03193                           break;
03194 
03195                         case 3:
03196                           K[0] = 0.5;
03197                           K[1] = 1./3.;
03198                           K[2] = 1;
03199                           break;
03200                         }
03201 
03202                       switch (j)
03203                         {
03204                         case 0:
03205                           K[3] = 0;
03206                           K[4] = 0;
03207                           K[5] = 0;
03208                           break;
03209 
03210                         case 1:
03211                           K[3] = 1;
03212                           K[4] = 0;
03213                           K[5] = 0;
03214                           break;
03215 
03216                         case 2:
03217                           K[3] = 0.5;
03218                           K[4] = 1;
03219                           K[5] = 0;
03220                           break;
03221 
03222                         case 3:
03223                           K[3] = 0.5;
03224                           K[4] = 1./3.;
03225                           K[5] = 1;
03226                           break;
03227 
03228                         }
03229 
03230                       switch (k)
03231                         {
03232                         case 0:
03233                           K[6] = 0;
03234                           K[7] = 0;
03235                           K[8] = 0;
03236                           break;
03237 
03238                         case 1:
03239                           K[6] = 1;
03240                           K[7] = 0;
03241                           K[8] = 0;
03242                           break;
03243 
03244                         case 2:
03245                           K[6] = 0.5;
03246                           K[7] = 1;
03247                           K[8] = 0;
03248                           break;
03249 
03250                         case 3:
03251                           K[6] = 0.5;
03252                           K[7] = 1./3.;
03253                           K[8] = 1;
03254                           break;
03255 
03256                         }
03257 
03258                       if ((i==j) && (j==k))
03259                         sigma = 1./120.;
03260 
03261                       else if ((i==j) || (j==k) || (i==k))
03262                         sigma = 1./360.;
03263 
03264                       else
03265                         sigma = 1./720.;
03266 
03267                       fun += vertex(W, F, R, cell_in, epsilon, w, nvert, K, H, me,
03268                                     vol, f, lqmin, adp, Gloc, sigma);
03269 
03270                       g += sigma*lqmin;
03271                       if (gqmin > lqmin)
03272                         gqmin = lqmin;
03273                     }
03274                 }
03275             }
03276         }
03277     }
03278 
03279   // fixed nodes correction
03280   for (int ii=0; ii<nvert; ii++)
03281     {
03282       if (mask[cell_in[ii]] == 1)
03283         {
03284           for (unsigned kk=0; kk<_dim; kk++)
03285             {
03286               for (int jj=0; jj<nvert; jj++)
03287                 {
03288                   W[kk][ii][jj] = 0;
03289                   W[kk][jj][ii] = 0;
03290                 }
03291 
03292               W[kk][ii][ii] = 1;
03293               F[kk][ii] = 0;
03294             }
03295         }
03296     }
03297   // end of fixed nodes correction
03298 
03299   // Set up return value references
03300   Vmin = g;
03301   qmin = gqmin/vol;
03302 
03303   return fun;
03304 }
03305 
03306 
03307 
03308 // avertex - assembly of adaptivity metric on a cell
03309 double VariationalMeshSmoother::avertex(const std::vector<double>& afun,
03310                                         std::vector<double>& G,
03311                                         const Array2D<double>& R,
03312                                         const std::vector<int>& cell_in,
03313                                         int nvert,
03314                                         int adp)
03315 {
03316   std::vector<double> a1(3), a2(3), a3(3), qu(3), K(8);
03317   Array2D<double> Q(3, nvert);
03318 
03319   for (int i=0; i<8; i++)
03320     K[i] = 0.5;  // cell center
03321 
03322   basisA(Q, nvert, K, Q, 1);
03323 
03324   for (unsigned i=0; i<_dim; i++)
03325     for (int j=0; j<nvert; j++)
03326       {
03327         a1[i] += Q[i][j]*R[cell_in[j]][0];
03328         a2[i] += Q[i][j]*R[cell_in[j]][1];
03329         if (_dim == 3)
03330           a3[i] += Q[i][j]*R[cell_in[j]][2];
03331 
03332         qu[i] += Q[i][j]*afun[cell_in[j]];
03333       }
03334 
03335   double det = 0.;
03336 
03337   if (_dim == 2)
03338     det = jac2(a1[0], a1[1],
03339                a2[0], a2[1]);
03340   else
03341     det = jac3(a1[0], a1[1], a1[2],
03342                a2[0], a2[1], a2[2],
03343                a3[0], a3[1], a3[2]);
03344 
03345   // Return val
03346   double g = 0.;
03347 
03348   if (det != 0)
03349     {
03350       if (_dim == 2)
03351         {
03352           double df0 = jac2(qu[0], qu[1], a2[0], a2[1])/det;
03353           double df1 = jac2(a1[0], a1[1], qu[0], qu[1])/det;
03354           g = (1. + df0*df0 + df1*df1);
03355 
03356           if (adp == 2)
03357             {
03358               // directional adaptation G=diag(g_i)
03359               G[0] = 1. + df0*df0;
03360               G[1] = 1. + df1*df1;
03361             }
03362           else
03363             {
03364               for (unsigned i=0; i<_dim; i++)
03365                 G[i] = g;  // simple adaptation G=gI
03366             }
03367         }
03368       else
03369         {
03370           double df0 = (qu[0]*(a2[1]*a3[2]-a2[2]*a3[1]) + qu[1]*(a2[2]*a3[0]-a2[0]*a3[2]) + qu[2]*(a2[0]*a3[1]-a2[1]*a3[0]))/det;
03371           double df1 = (qu[0]*(a3[1]*a1[2]-a3[2]*a1[1]) + qu[1]*(a3[2]*a1[0]-a3[0]*a1[2]) + qu[2]*(a3[0]*a1[1]-a3[1]*a1[0]))/det;
03372           double df2 = (qu[0]*(a1[1]*a2[2]-a1[2]*a2[1]) + qu[1]*(a1[2]*a2[0]-a1[0]*a2[2]) + qu[2]*(a1[0]*a2[1]-a1[1]*a2[0]))/det;
03373           g = 1. + df0*df0 + df1*df1 + df2*df2;
03374           if (adp == 2)
03375             {
03376               // directional adaptation G=diag(g_i)
03377               G[0] = 1. + df0*df0;
03378               G[1] = 1. + df1*df1;
03379               G[2] = 1. + df2*df2;
03380             }
03381           else
03382             {
03383               for (unsigned i=0; i<_dim; i++)
03384                 G[i] = g;  // simple adaptation G=gI
03385             }
03386         }
03387     }
03388   else
03389     {
03390       g = 1.;
03391       for (unsigned i=0; i<_dim; i++)
03392         G[i] = g;
03393     }
03394 
03395   return g;
03396 }
03397 
03398 
03399 
03400 // Computes local matrics W and local rhs F on one basis
03401 double VariationalMeshSmoother::vertex(Array3D<double>& W,
03402                                        Array2D<double>& F,
03403                                        const Array2D<double>& R,
03404                                        const std::vector<int>& cell_in,
03405                                        double epsilon,
03406                                        double w,
03407                                        int nvert,
03408                                        const std::vector<double>& K,
03409                                        const Array2D<double>& H,
03410                                        int me,
03411                                        double vol,
03412                                        int f,
03413                                        double& qmin,
03414                                        int adp,
03415                                        const std::vector<double>& g,
03416                                        double sigma)
03417 {
03418   // hessian, function, gradient
03419   Array2D<double> Q(3, nvert);
03420   basisA(Q, nvert, K, H, me);
03421 
03422   std::vector<double> a1(3), a2(3), a3(3);
03423   for (unsigned i=0; i<_dim; i++)
03424     for (int j=0; j<nvert; j++)
03425       {
03426         a1[i] += Q[i][j]*R[cell_in[j]][0];
03427         a2[i] += Q[i][j]*R[cell_in[j]][1];
03428         if (_dim == 3)
03429           a3[i] += Q[i][j]*R[cell_in[j]][2];
03430       }
03431 
03432   // account for adaptation
03433   double G = 0.;
03434   if (adp < 2)
03435     G = g[0];
03436   else
03437     {
03438       G = 1.;
03439       for (unsigned i=0; i<_dim; i++)
03440         {
03441           a1[i] *= std::sqrt(g[0]);
03442           a2[i] *= std::sqrt(g[1]);
03443           if (_dim == 3)
03444             a3[i] *= std::sqrt(g[2]);
03445         }
03446     }
03447 
03448   double
03449     det = 0.,
03450     tr = 0.,
03451     phit = 0.;
03452 
03453   std::vector<double> av1(3), av2(3), av3(3);
03454 
03455   if (_dim == 2)
03456     {
03457       av1[0] =  a2[1];
03458       av1[1] = -a2[0];
03459       av2[0] = -a1[1];
03460       av2[1] =  a1[0];
03461       det = jac2(a1[0], a1[1], a2[0], a2[1]);
03462       for (int i=0; i<2; i++)
03463         tr += 0.5*(a1[i]*a1[i] + a2[i]*a2[i]);
03464 
03465       phit = (1-w)*tr + w*0.5*(vol/G + det*det*G/vol);
03466     }
03467 
03468   if (_dim == 3)
03469     {
03470       av1[0] = a2[1]*a3[2] - a2[2]*a3[1];
03471       av1[1] = a2[2]*a3[0] - a2[0]*a3[2];
03472       av1[2] = a2[0]*a3[1] - a2[1]*a3[0];
03473 
03474       av2[0] = a3[1]*a1[2] - a3[2]*a1[1];
03475       av2[1] = a3[2]*a1[0] - a3[0]*a1[2];
03476       av2[2] = a3[0]*a1[1] - a3[1]*a1[0];
03477 
03478       av3[0] = a1[1]*a2[2] - a1[2]*a2[1];
03479       av3[1] = a1[2]*a2[0] - a1[0]*a2[2];
03480       av3[2] = a1[0]*a2[1] - a1[1]*a2[0];
03481 
03482       det = jac3(a1[0], a1[1], a1[2],
03483                  a2[0], a2[1], a2[2],
03484                  a3[0], a3[1], a3[2]);
03485 
03486       for (int i=0; i<3; i++)
03487         tr += (1./3.)*(a1[i]*a1[i] + a2[i]*a2[i] + a3[i]*a3[i]);
03488 
03489       phit = (1-w)*pow(tr,1.5) + w*0.5*(vol/G + det*det*G/vol);
03490     }
03491 
03492   double dchi = 0.5 + det*0.5/std::sqrt(epsilon*epsilon + det*det);
03493   double chi = 0.5*(det + std::sqrt(epsilon*epsilon + det*det));
03494   double fet = (chi != 0.) ? phit/chi : 1.e32;
03495 
03496   // Set return value reference
03497   qmin = det*G;
03498 
03499   // gradient and Hessian
03500   if (f == 0)
03501     {
03502       Array3D<double> P(3, 3, 3);
03503       Array3D<double> d2phi(3, 3, 3);
03504       Array2D<double> dphi(3, 3);
03505       Array2D<double> dfe(3, 3);
03506 
03507       if (_dim == 2)
03508         {
03509           for (int i=0; i<2; i++)
03510             {
03511               dphi[0][i] = (1-w)*a1[i] + w*G*det*av1[i]/vol;
03512               dphi[1][i] = (1-w)*a2[i] + w*G*det*av2[i]/vol;
03513             }
03514 
03515           for (int i=0; i<2; i++)
03516             for (int j=0; j<2; j++)
03517               {
03518                 d2phi[0][i][j] = w*G*av1[i]*av1[j]/vol;
03519                 d2phi[1][i][j] = w*G*av2[i]*av2[j]/vol;
03520 
03521                 if (i == j)
03522                   for (int k=0; k<2; k++)
03523                     d2phi[k][i][j] += 1.-w;
03524               }
03525 
03526           for (int i=0; i<2; i++)
03527             {
03528               dfe[0][i] = (dphi[0][i] - fet*dchi*av1[i])/chi;
03529               dfe[1][i] = (dphi[1][i] - fet*dchi*av2[i])/chi;
03530             }
03531 
03532           for (int i=0; i<2; i++)
03533             for (int j=0; j<2; j++)
03534               {
03535                 P[0][i][j] = (d2phi[0][i][j] - dchi*(av1[i]*dfe[0][j] + dfe[0][i]*av1[j]))/chi;
03536                 P[1][i][j] = (d2phi[1][i][j] - dchi*(av2[i]*dfe[1][j] + dfe[1][i]*av2[j]))/chi;
03537               }
03538         }
03539 
03540       if (_dim == 3)
03541         {
03542           for (int i=0; i<3; i++)
03543             {
03544               dphi[0][i] = (1-w)*std::sqrt(tr)*a1[i] + w*G*det*av1[i]/vol;
03545               dphi[1][i] = (1-w)*std::sqrt(tr)*a2[i] + w*G*det*av2[i]/vol;
03546               dphi[2][i] = (1-w)*std::sqrt(tr)*a3[i] + w*G*det*av3[i]/vol;
03547             }
03548 
03549           for (int i=0; i<3; i++)
03550             {
03551               if (tr != 0)
03552                 {
03553                   d2phi[0][i][i] = (1-w)/(3.*std::sqrt(tr))*a1[i]*a1[i] + w*G*av1[i]*av1[i]/vol;
03554                   d2phi[1][i][i] = (1-w)/(3.*std::sqrt(tr))*a2[i]*a2[i] + w*G*av2[i]*av2[i]/vol;
03555                   d2phi[2][i][i] = (1-w)/(3.*std::sqrt(tr))*a3[i]*a3[i] + w*G*av3[i]*av3[i]/vol;
03556                 }
03557               else
03558                 {
03559                   for (int k=0; k<3; k++)
03560                     d2phi[k][i][i] = 0.;
03561                 }
03562 
03563               for (int k=0; k<3; k++)
03564                 d2phi[k][i][i] += (1-w)*std::sqrt(tr);
03565             }
03566 
03567           const double con = 100.;
03568 
03569           for (int i=0; i<3; i++)
03570             {
03571               dfe[0][i] = (dphi[0][i] - fet*dchi*av1[i] + con*epsilon*a1[i])/chi;
03572               dfe[1][i] = (dphi[1][i] - fet*dchi*av2[i] + con*epsilon*a2[i])/chi;
03573               dfe[2][i] = (dphi[2][i] - fet*dchi*av3[i] + con*epsilon*a3[i])/chi;
03574             }
03575 
03576           for (int i=0; i<3; i++)
03577             {
03578               P[0][i][i] = (d2phi[0][i][i] - dchi*(av1[i]*dfe[0][i] + dfe[0][i]*av1[i]) + con*epsilon)/chi;
03579               P[1][i][i] = (d2phi[1][i][i] - dchi*(av2[i]*dfe[1][i] + dfe[1][i]*av2[i]) + con*epsilon)/chi;
03580               P[2][i][i] = (d2phi[2][i][i] - dchi*(av3[i]*dfe[2][i] + dfe[2][i]*av3[i]) + con*epsilon)/chi;
03581             }
03582 
03583           for (int k=0; k<3; k++)
03584             for (int i=0; i<3; i++)
03585               for (int j=0; j<3; j++)
03586                 if (i != j)
03587                   P[k][i][j] = 0.;
03588         }
03589 
03590       /*--------matrix W, right side F---------------------*/
03591       Array2D<double> gpr(3, nvert);
03592 
03593       for (unsigned i1=0; i1<_dim; i1++)
03594         {
03595           for (unsigned i=0; i<_dim; i++)
03596             for (int j=0; j<nvert; j++)
03597               for (unsigned k=0; k<_dim; k++)
03598                 gpr[i][j] += P[i1][i][k]*Q[k][j];
03599 
03600           for (int i=0; i<nvert; i++)
03601             for (int j=0; j<nvert; j++)
03602               for (unsigned k=0; k<_dim; k++)
03603                 W[i1][i][j] += Q[k][i]*gpr[k][j]*sigma;
03604 
03605           for (int i=0; i<nvert; i++)
03606             for (int k=0; k<2; k++)
03607               F[i1][i] += Q[k][i]*dfe[i1][k]*sigma;
03608         }
03609     }
03610 
03611   return fet*sigma;
03612 }
03613 
03614 
03615 
03616 // Solve Symmetric Positive Definite (SPD) linear system
03617 // by Conjugate Gradient (CG) method preconditioned by
03618 // Point Jacobi (diagonal scaling)
03619 int VariationalMeshSmoother::solver(int n,
03620                                     const std::vector<int>& ia,
03621                                     const std::vector<int>& ja,
03622                                     const std::vector<double>& a,
03623                                     std::vector<double>& x,
03624                                     const std::vector<double>& b,
03625                                     double eps,
03626                                     int maxite,
03627                                     int msglev)
03628 {
03629   _logfile << "Beginning Solve " << n << std::endl;
03630 
03631   // Check parameters
03632   int info = pcg_par_check(n, ia, ja, a, eps, maxite, msglev);
03633   if (info != 0)
03634     return info;
03635 
03636   // PJ preconditioner construction
03637   std::vector<double> u(n);
03638   for (int i=0; i<n; i++)
03639     u[i] = 1./a[ia[i]];
03640 
03641   // PCG iterations
03642   std::vector<double> r(n), p(n), z(n);
03643   info = pcg_ic0(n, ia, ja, a, u, x, b, r, p, z, eps, maxite, msglev);
03644 
03645   // Mat sparse_global;
03646   // MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,n,n,ia,ja,a,&sparse_global);
03647 
03648   _logfile << "Finished Solve " << n << std::endl;
03649 
03650   return info;
03651 }
03652 
03653 
03654 
03655 // Input parameter check
03656 int VariationalMeshSmoother::pcg_par_check(int n,
03657                                            const std::vector<int>& ia,
03658                                            const std::vector<int>& ja,
03659                                            const std::vector<double>& a,
03660                                            double eps,
03661                                            int maxite,
03662                                            int msglev)
03663 {
03664   int i, j, jj, k;
03665 
03666   if (n <= 0)
03667     {
03668       if (msglev > 0)
03669         _logfile << "sol_pcg: incorrect input parameter: n =" << n << std::endl;
03670       return -1;
03671     }
03672 
03673   if (ia[0] != 0)
03674     {
03675       if (msglev > 0)
03676         _logfile << "sol_pcg: incorrect input parameter: ia(1) =" << ia[0] << std::endl;
03677       return -2;
03678     }
03679 
03680   for (i=0; i<n; i++)
03681     {
03682       if (ia[i+1] < ia[i])
03683         {
03684           if (msglev >= 1)
03685             _logfile << "sol_pcg: incorrect input parameter: i ="
03686                      << i+1
03687                      << "; ia(i) ="
03688                      << ia[i]
03689                      << " must be <= a(i+1) ="
03690                      << ia[i+1]
03691                      << std::endl;
03692           return -2;
03693         }
03694     }
03695 
03696   for (i=0; i<n; i++)
03697     {
03698       if (ja[ia[i]] != (i+1))
03699         {
03700           if (msglev >= 1)
03701             _logfile << "sol_pcg: incorrect input parameter: i ="
03702                      << i+1
03703                      << " ; ia(i) ="
03704                      << ia[i]
03705                      << " ; absence of diagonal entry; k ="
03706                      << ia[i]+1
03707                      << " ; the value ja(k) ="
03708                      << ja[ia[i]]
03709                      << " must be equal to i"
03710                      << std::endl;
03711 
03712           return -3;
03713         }
03714 
03715       jj = 0;
03716       for (k=ia[i]; k<ia[i+1]; k++)
03717         {
03718           j=ja[k];
03719           if ((j<(i+1)) || (j>n))
03720             {
03721               if (msglev >= 1)
03722                 _logfile << "sol_pcg: incorrect input parameter: i ="
03723                          << i+1
03724                          << " ; ia(i) ="
03725                          << ia[i]
03726                          << " ; a(i+1) ="
03727                          << ia[i+1]
03728                          << " ; k ="
03729                          << k+1
03730                          << " ; the value ja(k) ="
03731                          << ja[k]
03732                          << " is out of range"
03733                          << std::endl;
03734 
03735               return -3;
03736             }
03737           if (j <= jj)
03738             {
03739               if (msglev >= 1)
03740                 _logfile << "sol_pcg: incorrect input parameter: i ="
03741                          << i+1
03742                          << " ; ia(i) ="
03743                          << ia[i]
03744                          << " ; a(i+1) ="
03745                          << ia[i+1]
03746                          << " ; k ="
03747                          << k+1
03748                          << " ; the value ja(k) ="
03749                          << ja[k]
03750                          << " must be less than ja(k+1) ="
03751                          << ja[k+1]
03752                          << std::endl;
03753 
03754               return -3;
03755             }
03756           jj = j;
03757         }
03758     }
03759 
03760   for (i=0; i<n; i++)
03761     {
03762       if (a[ia[i]] <= 0.)
03763         {
03764           if (msglev >= 1)
03765             _logfile << "sol_pcg: incorrect input parameter: i ="
03766                      << i+1
03767                      << " ; ia(i) ="
03768                      << ia[i]
03769                      << " ; the diagonal entry a(ia(i)) ="
03770                      << a[ia[i]]
03771                      << " must be > 0"
03772                      << std::endl;
03773 
03774           return -4;
03775         }
03776     }
03777 
03778   if (eps < 0.)
03779     {
03780       if (msglev > 0)
03781         _logfile << "sol_pcg: incorrect input parameter: eps =" << eps << std::endl;
03782       return -7;
03783     }
03784 
03785   if (maxite < 1)
03786     {
03787       if (msglev > 0)
03788         _logfile << "sol_pcg: incorrect input parameter: maxite =" << maxite << std::endl;
03789       return -8;
03790     }
03791 
03792   return 0;
03793 }
03794 
03795 
03796 
03797 // Solve the SPD linear system by PCG method
03798 int VariationalMeshSmoother::pcg_ic0(int n,
03799                                      const std::vector<int>& ia,
03800                                      const std::vector<int>& ja,
03801                                      const std::vector<double>& a,
03802                                      const std::vector<double>& u,
03803                                      std::vector<double>& x,
03804                                      const std::vector<double>& b,
03805                                      std::vector<double>& r,
03806                                      std::vector<double>& p,
03807                                      std::vector<double>& z,
03808                                      double eps,
03809                                      int maxite,
03810                                      int msglev)
03811 {
03812   // Return value
03813   int i = 0;
03814 
03815   double
03816     rhr = 0.,
03817     rhr0 = 0.,
03818     rhrold = 0.,
03819     rr0 = 0.;
03820 
03821   for (i=0; i<=maxite; i++)
03822     {
03823       if (i == 0)
03824         p = x;
03825 
03826       // z=Ap
03827       for (int ii=0; ii<n; ii++)
03828         z[ii] = 0.;
03829 
03830       for (int ii=0; ii<n; ii++)
03831         {
03832           z[ii] += a[ia[ii]]*p[ii];
03833 
03834           for (int j=ia[ii]+1; j<ia[ii+1]; j++)
03835             {
03836               z[ii] += a[j]*p[ja[j]-1];
03837               z[ja[j]-1] += a[j]*p[ii];
03838             }
03839         }
03840 
03841       if (i == 0)
03842         for (int k=0; k<n; k++)
03843           r[k] = b[k] - z[k]; // r(0) = b - Ax(0)
03844 
03845       if (i > 0)
03846         {
03847           double pap = 0.;
03848           for (int k=0; k<n; k++)
03849             pap += p[k]*z[k];
03850 
03851           double alpha = rhr/pap;
03852           for (int k=0; k<n; k++)
03853             {
03854               x[k] += p[k]*alpha;
03855               r[k] -= z[k]*alpha;
03856             }
03857           rhrold = rhr;
03858         }
03859 
03860       // z = H * r
03861       for (int ii=0; ii<n; ii++)
03862         z[ii] = r[ii]*u[ii];
03863 
03864       if (i == 0)
03865         p = z;
03866 
03867       rhr = 0.;
03868       double rr = 0.;
03869       for (int k=0; k<n; k++)
03870         {
03871           rhr += r[k]*z[k];
03872           rr += r[k]*r[k];
03873         }
03874 
03875       if (i == 0)
03876         {
03877           rhr0 = rhr;
03878           rr0 = rr;
03879         }
03880 
03881       if (msglev > 0)
03882         _logfile << i
03883                  << " )  rHr ="
03884                  << std::sqrt(rhr/rhr0)
03885                  << " rr ="
03886                  << std::sqrt(rr/rr0)
03887                  << std::endl;
03888 
03889       if (rr <= eps*eps*rr0)
03890         return i;
03891 
03892       if (i >= maxite)
03893         return i;
03894 
03895       if (i > 0)
03896         {
03897           double beta = rhr/rhrold;
03898           for (int k=0; k<n; k++)
03899             p[k] = z[k] + p[k]*beta;
03900         }
03901     } // end for i
03902 
03903   return i;
03904 }
03905 
03906 
03907 
03908 
03909 // Sample mesh file generation
03910 void VariationalMeshSmoother::gener(char grid[],
03911                                     int n)
03912 {
03913   const int n1 = 3;
03914 
03915   int
03916     N = 1,
03917     ncells = 1;
03918 
03919   for (int i=0; i<n; i++)
03920     {
03921       N *= n1;
03922       ncells *= (n1-1);
03923     }
03924 
03925   const double x = 1./static_cast<double>(n1-1);
03926 
03927   std::ofstream outfile(grid);
03928 
03929   outfile << n << "\n" << N << "\n" << ncells << "\n0\n" << std::endl;
03930 
03931   for (int i=0; i<N; i++)
03932     {
03933       // node coordinates
03934       int k = i;
03935       int mask = 0;
03936       for (int j=0; j<n; j++)
03937         {
03938           int ii = k % n1;
03939           if ((ii == 0) || (ii == n1-1))
03940             mask = 1;
03941 
03942           outfile << static_cast<double>(ii)*x << " ";
03943           k /= n1;
03944         }
03945       outfile << mask << std::endl;
03946     }
03947 
03948   for (int i=0; i<ncells; i++)
03949     {
03950       // cell connectivity
03951       int nc = i;
03952       int ii = nc%(n1-1);
03953       nc /= (n1-1);
03954       int jj = nc%(n1-1);
03955       int kk = nc/(n1-1);
03956 
03957       if (n == 2)
03958         outfile << ii+n1*jj << " "
03959                 << ii+1+jj*n1 << " "
03960                 << ii+(jj+1)*n1 << " "
03961                 << ii+1+(jj+1)*n1 << " ";
03962 
03963       if (n == 3)
03964         outfile << ii+n1*jj+n1*n1*kk << " "
03965                 << ii+1+jj*n1+n1*n1*kk << " "
03966                 << ii+(jj+1)*n1+n1*n1*kk << " "
03967                 << ii+1+(jj+1)*n1+n1*n1*kk << " "
03968                 << ii+n1*jj+n1*n1*(kk+1) << " "
03969                 << ii+1+jj*n1+n1*n1*(kk+1) << " "
03970                 << ii+(jj+1)*n1+n1*n1*(kk+1) << " "
03971                 << ii+1+(jj+1)*n1+n1*n1*(kk+1) << " ";
03972 
03973       outfile << "-1 -1 0 \n";
03974     }
03975 }
03976 
03977 
03978 
03979 // Metric Generation
03980 void VariationalMeshSmoother::metr_data_gen(std::string grid,
03981                                             std::string metr,
03982                                             int me)
03983 {
03984   double det, g1, g2, g3, det_o, g1_o, g2_o, g3_o, eps=1e-3;
03985 
03986   std::vector<double> K(9);
03987   Array2D<double> Q(3, 3*_dim + _dim%2);
03988 
03989   // Use _mesh to determine N and ncells
03990   this->_n_nodes = _mesh.n_nodes();
03991   this->_n_cells = _mesh.n_active_elem();
03992 
03993   std::vector<int>
03994     mask(_n_nodes),
03995     mcells(_n_cells);
03996 
03997   Array2D<int> cells(_n_cells, 3*_dim + _dim%2);
03998   Array2D<double> R(_n_nodes,_dim);
03999 
04000   readgr(R, mask, cells, mcells, mcells, mcells);
04001 
04002   // genetrate metric file
04003   std::ofstream metric_file(metr.c_str());
04004   if (!metric_file.good())
04005     libmesh_error_msg("Error opening metric output file.");
04006 
04007   // Use scientific notation with 6 digits
04008   metric_file << std::scientific << std::setprecision(6);
04009 
04010   int Ncells = 0;
04011   det_o = 1.;
04012   g1_o = 1.;
04013   g2_o = 1.;
04014   g3_o = 1.;
04015   for (unsigned i=0; i<_n_cells; i++)
04016     if (mcells[i] >= 0)
04017       {
04018         int nvert=0;
04019         while (cells[i][nvert] >= 0)
04020           nvert++;
04021 
04022         if (_dim == 2)
04023           {
04024             // 2D - tri and quad
04025             if (nvert == 3)
04026               {
04027                 // tri
04028                 basisA(Q, 3, K, Q, 1);
04029 
04030                 Point a1, a2;
04031                 for (int k=0; k<2; k++)
04032                   for (int l=0; l<3; l++)
04033                     {
04034                       a1(k) += Q[k][l]*R[cells[i][l]][0];
04035                       a2(k) += Q[k][l]*R[cells[i][l]][1];
04036                     }
04037 
04038                 det = jac2(a1(0), a1(1), a2(0), a2(1));
04039                 g1 = std::sqrt(a1(0)*a1(0) + a2(0)*a2(0));
04040                 g2 = std::sqrt(a1(1)*a1(1) + a2(1)*a2(1));
04041 
04042                 // need to keep data from previous cell
04043                 if ((std::abs(det) < eps*eps*det_o) || (det < 0))
04044                   det = det_o;
04045 
04046                 if ((std::abs(g1) < eps*g1_o) || (g1<0))
04047                   g1 = g1_o;
04048 
04049                 if ((std::abs(g2) < eps*g2_o) || (g2<0))
04050                   g2 = g2_o;
04051 
04052                 // write to file
04053                 if (me == 2)
04054                   metric_file << 1./std::sqrt(det)
04055                               << " 0.000000e+00 \n0.000000e+00 "
04056                               << 1./std::sqrt(det)
04057                               << std::endl;
04058 
04059                 if (me == 3)
04060                   metric_file << 1./g1
04061                               << " 0.000000e+00 \n0.000000e+00 "
04062                               << 1./g2
04063                               << std::endl;
04064 
04065                 det_o = det;
04066                 g1_o = g1;
04067                 g2_o = g2;
04068                 Ncells++;
04069               }
04070 
04071             if (nvert == 4)
04072               {
04073                 // quad
04074 
04075                 // Set up the node edge neighbor indices
04076                 const unsigned node_indices[4] = {0, 1, 3, 2};
04077                 const unsigned first_neighbor_indices[4] = {1, 3, 2, 0};
04078                 const unsigned second_neighbor_indices[4] = {2, 0, 1, 3};
04079 
04080                 // Loop over each node, compute some quantities associated
04081                 // with its edge neighbors, and write them to file.
04082                 for (unsigned ni=0; ni<4; ++ni)
04083                   {
04084                     unsigned
04085                       node_index = node_indices[ni],
04086                       first_neighbor_index = first_neighbor_indices[ni],
04087                       second_neighbor_index = second_neighbor_indices[ni];
04088 
04089                     Real
04090                       node_x = R[cells[i][node_index]][0],
04091                       node_y = R[cells[i][node_index]][1],
04092                       first_neighbor_x = R[cells[i][first_neighbor_index]][0],
04093                       first_neighbor_y = R[cells[i][first_neighbor_index]][1],
04094                       second_neighbor_x = R[cells[i][second_neighbor_index]][0],
04095                       second_neighbor_y = R[cells[i][second_neighbor_index]][1];
04096 
04097 
04098                     // "dx"
04099                     Point a1(first_neighbor_x - node_x,
04100                              second_neighbor_x - node_x);
04101 
04102                     // "dy"
04103                     Point a2(first_neighbor_y - node_y,
04104                              second_neighbor_y - node_y);
04105 
04106                     det = jac2(a1(0), a1(1), a2(0), a2(1));
04107                     g1 = std::sqrt(a1(0)*a1(0) + a2(0)*a2(0));
04108                     g2 = std::sqrt(a1(1)*a1(1) + a2(1)*a2(1));
04109 
04110                     // need to keep data from previous cell
04111                     if ((std::abs(det) < eps*eps*det_o) || (det < 0))
04112                       det = det_o;
04113 
04114                     if ((std::abs(g1) < eps*g1_o) || (g1 < 0))
04115                       g1 = g1_o;
04116 
04117                     if ((std::abs(g2) < eps*g2_o) || (g2 < 0))
04118                       g2 = g2_o;
04119 
04120                     // write to file
04121                     if (me == 2)
04122                       metric_file << 1./std::sqrt(det) << " "
04123                                   << 0.5/std::sqrt(det) << " \n0.000000e+00 "
04124                                   << 0.5*std::sqrt(3./det)
04125                                   << std::endl;
04126 
04127                     if (me == 3)
04128                       metric_file << 1./g1 << " "
04129                                   << 0.5/g2 << "\n0.000000e+00 "
04130                                   << 0.5*std::sqrt(3.)/g2
04131                                   << std::endl;
04132 
04133                     det_o = det;
04134                     g1_o = g1;
04135                     g2_o = g2;
04136                     Ncells++;
04137                   }
04138               } // end QUAD case
04139           } // end _dim==2
04140 
04141         if (_dim == 3)
04142           {
04143             // 3D - tetr and hex
04144 
04145             if (nvert == 4)
04146               {
04147                 // tetr
04148                 basisA(Q, 4, K, Q, 1);
04149 
04150                 Point a1, a2, a3;
04151 
04152                 for (int k=0; k<3; k++)
04153                   for (int l=0; l<4; l++)
04154                     {
04155                       a1(k) += Q[k][l]*R[cells[i][l]][0];
04156                       a2(k) += Q[k][l]*R[cells[i][l]][1];
04157                       a3(k) += Q[k][l]*R[cells[i][l]][2];
04158                     }
04159 
04160                 det = jac3(a1(0), a1(1), a1(2),
04161                            a2(0), a2(1), a2(2),
04162                            a3(0), a3(1), a3(2));
04163                 g1 = std::sqrt(a1(0)*a1(0) + a2(0)*a2(0) + a3(0)*a3(0));
04164                 g2 = std::sqrt(a1(1)*a1(1) + a2(1)*a2(1) + a3(1)*a3(1));
04165                 g3 = std::sqrt(a1(2)*a1(2) + a2(2)*a2(2) + a3(2)*a3(2));
04166 
04167                 // need to keep data from previous cell
04168                 if ((std::abs(det) < eps*eps*eps*det_o) || (det < 0))
04169                   det = det_o;
04170 
04171                 if ((std::abs(g1) < eps*g1_o) || (g1 < 0))
04172                   g1 = g1_o;
04173 
04174                 if ((std::abs(g2) < eps*g2_o) || (g2 < 0))
04175                   g2 = g2_o;
04176 
04177                 if ((std::abs(g3) < eps*g3_o) || (g3 < 0))
04178                   g3 = g3_o;
04179 
04180                 // write to file
04181                 if (me == 2)
04182                   metric_file << 1./pow(det, 1./3.)
04183                               << " 0.000000e+00  0.000000e+00\n0.000000e+00 "
04184                               << 1./pow(det, 1./3.)
04185                               << " 0.000000e+00\n0.000000e+00 0.000000e+00 "
04186                               << 1./pow(det, 1./3.)
04187                               << std::endl;
04188 
04189                 if (me == 3)
04190                   metric_file << 1./g1
04191                               << " 0.000000e+00  0.000000e+00\n0.000000e+00 "
04192                               << 1./g2
04193                               << " 0.000000e+00\n0.000000e+00 0.000000e+00 "
04194                               << 1./g3
04195                               << std::endl;
04196 
04197                 det_o = det;
04198                 g1_o = g1;
04199                 g2_o = g2;
04200                 g3_o = g3;
04201                 Ncells++;
04202               }
04203 
04204             if (nvert == 8)
04205               {
04206                 // hex
04207 
04208                 // Set up the node edge neighbor indices
04209                 const unsigned node_indices[8] = {0, 1, 3, 2, 4, 5, 7, 6};
04210                 const unsigned first_neighbor_indices[8] = {1, 3, 2, 0, 6, 4, 5, 7};
04211                 const unsigned second_neighbor_indices[8] = {2, 0, 1, 3, 5, 7, 6, 4};
04212                 const unsigned third_neighbor_indices[8] = {4, 5, 7, 6, 0, 1, 3, 2};
04213 
04214                 // Loop over each node, compute some quantities associated
04215                 // with its edge neighbors, and write them to file.
04216                 for (unsigned ni=0; ni<8; ++ni)
04217                   {
04218                     unsigned
04219                       node_index = node_indices[ni],
04220                       first_neighbor_index = first_neighbor_indices[ni],
04221                       second_neighbor_index = second_neighbor_indices[ni],
04222                       third_neighbor_index = third_neighbor_indices[ni];
04223 
04224                     Real
04225                       node_x = R[cells[i][node_index]][0],
04226                       node_y = R[cells[i][node_index]][1],
04227                       node_z = R[cells[i][node_index]][2],
04228                       first_neighbor_x = R[cells[i][first_neighbor_index]][0],
04229                       first_neighbor_y = R[cells[i][first_neighbor_index]][1],
04230                       first_neighbor_z = R[cells[i][first_neighbor_index]][2],
04231                       second_neighbor_x = R[cells[i][second_neighbor_index]][0],
04232                       second_neighbor_y = R[cells[i][second_neighbor_index]][1],
04233                       second_neighbor_z = R[cells[i][second_neighbor_index]][2],
04234                       third_neighbor_x = R[cells[i][third_neighbor_index]][0],
04235                       third_neighbor_y = R[cells[i][third_neighbor_index]][1],
04236                       third_neighbor_z = R[cells[i][third_neighbor_index]][2];
04237 
04238                     // "dx"
04239                     Point a1(first_neighbor_x - node_x,
04240                              second_neighbor_x - node_x,
04241                              third_neighbor_x - node_x);
04242 
04243                     // "dy"
04244                     Point a2(first_neighbor_y - node_y,
04245                              second_neighbor_y - node_y,
04246                              third_neighbor_y - node_y);
04247 
04248                     // "dz"
04249                     Point a3(first_neighbor_z - node_z,
04250                              second_neighbor_z - node_z,
04251                              third_neighbor_z - node_z);
04252 
04253                     det = jac3(a1(0), a1(1), a1(2),
04254                                a2(0), a2(1), a2(2),
04255                                a3(0), a3(1), a3(2));
04256                     g1 = std::sqrt(a1(0)*a1(0) + a2(0)*a2(0) + a3(0)*a3(0));
04257                     g2 = std::sqrt(a1(1)*a1(1) + a2(1)*a2(1) + a3(1)*a3(1));
04258                     g3 = std::sqrt(a1(2)*a1(2) + a2(2)*a2(2) + a3(2)*a3(2));
04259 
04260                     // need to keep data from previous cell
04261                     if ((std::abs(det) < eps*eps*eps*det_o) || (det < 0))
04262                       det = det_o;
04263 
04264                     if ((std::abs(g1) < eps*g1_o) || (g1 < 0))
04265                       g1 = g1_o;
04266 
04267                     if ((std::abs(g2) < eps*g2_o) || (g2 < 0))
04268                       g2 = g2_o;
04269 
04270                     if ((std::abs(g3) < eps*g3_o) || (g3 < 0))
04271                       g3 = g3_o;
04272 
04273                     // write to file
04274                     if (me == 2)
04275                       metric_file << 1./pow(det, 1./3.) << " "
04276                                   << 0.5/pow(det, 1./3.) << " "
04277                                   << 0.5/pow(det, 1./3.) << "\n0.000000e+00 "
04278                                   << 0.5*std::sqrt(3.)/pow(det, 1./3.) << " "
04279                                   << 0.5/(std::sqrt(3.)*pow(det, 1./3.)) << "\n0.000000e+00 0.000000e+00 "
04280                                   << std::sqrt(2/3.)/pow(det, 1./3.)
04281                                   << std::endl;
04282 
04283                     if (me == 3)
04284                       metric_file << 1./g1 << " "
04285                                   << 0.5/g2 << " "
04286                                   << 0.5/g3 << "\n0.000000e+00 "
04287                                   << 0.5*std::sqrt(3.)/g2 << " "
04288                                   << 0.5/(std::sqrt(3.)*g3) << "\n0.000000e+00 0.000000e+00 "
04289                                   << std::sqrt(2./3.)/g3
04290                                   << std::endl;
04291 
04292                     det_o = det;
04293                     g1_o = g1;
04294                     g2_o = g2;
04295                     g3_o = g3;
04296                     Ncells++;
04297                   } // end for ni
04298               } // end hex
04299           } // end dim==3
04300       }
04301 
04302   // Done with the metric file
04303   metric_file.close();
04304 
04305   std::ofstream grid_file(grid.c_str());
04306   if (!grid_file.good())
04307     libmesh_error_msg("Error opening file: " << grid);
04308 
04309   grid_file << _dim << "\n" << _n_nodes << "\n" << Ncells << "\n0" << std::endl;
04310 
04311   // Use scientific notation with 6 digits
04312   grid_file << std::scientific << std::setprecision(6);
04313 
04314   for (dof_id_type i=0; i<_n_nodes; i++)
04315     {
04316       // node coordinates
04317       for (unsigned j=0; j<_dim; j++)
04318         grid_file << R[i][j] << " ";
04319 
04320       grid_file << mask[i] << std::endl;
04321     }
04322 
04323   for (dof_id_type i=0; i<_n_cells; i++)
04324     if (mcells[i] >= 0)
04325       {
04326         // cell connectivity
04327         int nvert = 0;
04328         while (cells[i][nvert] >= 0)
04329           nvert++;
04330 
04331         if ((nvert == 3) || ((_dim == 3) && (nvert == 4)))
04332           {
04333             // tri & tetr
04334             for (int j=0; j<nvert; j++)
04335               grid_file << cells[i][j] << " ";
04336 
04337             for (unsigned j=nvert; j<3*_dim + _dim%2; j++)
04338               grid_file << "-1 ";
04339 
04340             grid_file << mcells[i] << std::endl;
04341           }
04342 
04343         if ((_dim == 2) && (nvert == 4))
04344           {
04345             // quad
04346             grid_file << cells[i][0] << " " << cells[i][1] << " " << cells[i][2] << " -1 -1 -1 0" << std::endl;
04347             grid_file << cells[i][1] << " " << cells[i][3] << " " << cells[i][0] << " -1 -1 -1 0" << std::endl;
04348             grid_file << cells[i][3] << " " << cells[i][2] << " " << cells[i][1] << " -1 -1 -1 0" << std::endl;
04349             grid_file << cells[i][2] << " " << cells[i][0] << " " << cells[i][3] << " -1 -1 -1 0" << std::endl;
04350           }
04351 
04352         if (nvert == 8)
04353           {
04354             // hex
04355             grid_file << cells[i][0] << " " << cells[i][1] << " " << cells[i][2] << " " << cells[i][4] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04356             grid_file << cells[i][1] << " " << cells[i][3] << " " << cells[i][0] << " " << cells[i][5] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04357             grid_file << cells[i][3] << " " << cells[i][2] << " " << cells[i][1] << " " << cells[i][7] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04358             grid_file << cells[i][2] << " " << cells[i][0] << " " << cells[i][3] << " " << cells[i][6] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04359             grid_file << cells[i][4] << " " << cells[i][6] << " " << cells[i][5] << " " << cells[i][0] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04360             grid_file << cells[i][5] << " " << cells[i][4] << " " << cells[i][7] << " " << cells[i][1] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04361             grid_file << cells[i][7] << " " << cells[i][5] << " " << cells[i][6] << " " << cells[i][3] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04362             grid_file << cells[i][6] << " " << cells[i][7] << " " << cells[i][4] << " " << cells[i][2] << " -1 -1 -1 -1 -1 -1 0" << std::endl;
04363           }
04364       }
04365 }
04366 
04367 } // namespace libMesh
04368 
04369 #endif // LIBMESH_ENABLE_VSMOOTHER