Actual source code: UFC.hh
petsc-3.4.2 2013-07-02

      1: /*

      3: Routines for linking UFC to Sieve and PETSc

      5: */

      7: #include "Mesh.hh"
      8: #include <petscmat.h>
      9: #include <ufc.h>

     11: //we SHOULD have some overlying "problem" object.  Let's do that here!

     13: #if 0

     15: namespace ALE {
     16:   class sieve_mesh_wrapper : ufc::mesh {

     18:   public:
     19:     Obj<PETSC_MESH_TYPE> m;
     20:     sieve_mesh_wrapper(Obj<PETSC_MESH_TYPE> mesh) {
     21:       m = mesh;
     22:       Obj<PETSC_MESH_TYPE::real_section_type> coordinates = m->getRealSection("coordinates");
     23:       int dim = m->getDimension();
     24:       topological_dimension = dim;
     25:       geometric_dimension = m->getFiberDimension(*m->depthStratum(0)->begin());
     26:       num_entities = new unsigned int[dim+1];
     27:       int depth = m->depth();
     28:       for (int i = 0; i < depth; i++) {
     29:         num_entities[i] = 0;
     30:       }
     31:       if (depth == 1) {
     32:         num_entities[0] = m->depthStratum(0);
     33:         num_entities[dim] = m->heightStratum(0);
     34:       } else {
     35:         if (depth != dim+1) throw Exception("Cannot handle partially interpolated sieves.");
     36:         for (int i = 0; i < dim+1; i++) {
     37:           num_entities[i] = m->getDepthStratum(i)->size();
     38:         }
     39:
     40:       }
     41:     }

     43:   };

     45:   class sieve_cell_wrapper : ufc::cell {
     46:   public:
     47:     Obj<PETSC_MESH_TYPE> m;                    // the presently associated mesh
     48:     int num_corners;                           //for the sake of clarity; the number of vertices
     49:     PETSC_MESH_TYPE::point_type current_point; // the presently associated sieve cell

     52:     sieve_cell_wrapper() {
     53:     }
     54:     sieve_cell_wrapper(ufc::finite_element finite_element) {
     55:       //properly initialize the cell from the form
     56:       int geometric_dimension = m->getRealSection("coordinates")->getFiberDimension(m->depthStratum(0)->begin());
     57:       if (finite_element->cell_shape() == ufc::interval) {
     58:         num_corners = 2;
     59:         topological_dimension = m->getDimension(); //we must clarify what this means in the mesh library
     60:         element_entities = new int *[2];
     61:         element_entities[0] = new int[2]; //vertices
     62:         element_entities[1] = new int[1]; //line
     63:         double * tmpcoords = new double[coorddim*2];
     64:         coordinates = new double *[2];
     65:         for (int i = 0; i < 2; i++) {
     66:           coordinates[i] = &tmpcoords[coorddim*i];
     67:         }
     68:       } else if (finite_element->cell_shape() == ufc::triangle) {
     69:         num_corners = 3;
     70:         element_entities = new int *[3];
     71:         element_entities[0] = new int[3]; //vertices
     72:         element_entities[1] = new int[3]; //edges
     73:         element_entities[2] = new int[1]; //cell
     74:         double * tmpcoords = new double[coorddim*3];
     75:         coordinates = new double *[3];
     76:         for (int i = 0; i < 3; i++) {
     77:           coordinates[i] = &tmpcoords[coorddim*i];
     78:         }
     79:       } else if (finite_element->cell_shape() == ufc::tetrahedron) {
     80:         num_corners = 4;
     81:         element_entities = new int *[2];
     82:         element_entities[0] = new int[4]; //vertices
     83:         element_entities[1] = new int[6]; //edges
     84:         element_entities[2] = new int[4]; //faces
     85:         element_entities[3] = new int[1]; //tetrahedron
     86:         double * tmpcoords = new double[coorddim*4];
     87:         coordinates = new double *[4];
     88:         for (int i = 0; i < 4; i++) {
     89:           coordinates[i] = &tmpcoords[coorddim*i];
     90:         }
     91:       } else throw Exception("Unsupported geometry");
     92:     }
     93:     ~sieve_cell_wrapper() {
     94:     }
     95:     void setMesh(Obj<PETSC_MESH_TYPE> mesh) {
     96:       m = mesh;
     97:     }
     98:     Obj<PETSC_MESH_TYPE> getMesh() {
     99:       return m;
    100:     }
    101:     void setCell(PETSC_MESH_TYPE::point_type p) {
    102:       if (m->height(p) != 0) throw Exception("sieve_cell_wrapper: the point must be a cell");
    103:       current_point = p;
    104:       //copy over the coordinates through the restrictClosure and copy
    105:       const double * coords = m->;
    106:       for (int i = 0; i < num_corners; i++) {
    107:         for (int j = 0; j < dim; j++) {
    108:           coordinates[i][j] = coords[i*coordim+j];
    109:         }
    110:       }
    111:       //copy over the entity indices such that they're consistent with the
    112:     }
    113:     void reorientSieveCell(PETSC_MESH_TYPE::point_type p) {
    114:       //changing the orientation will be hard; keep it the same for now as it should orient normals right
    115:       //this will not be so bad in the long run

    117:     }
    118:     Obj<PETSC_MESH_TYPE::sieve_type::oConeArray> reorderSieveClosure(PETSC_MESH_TYPE::point_type p) {
    119:       //return m->getSieve()->closure(p); //null reorder for now. NEI! the oriented closure!
    120:       return PETSC_MESH_TYPE::sieve_alg_type::orientedClosure(m, m->getArrowSection("orientation"), p);
    121:     }
    122:     void reorderSieveRestrictClosure(const double * coefficients) {
    123:       //order the restricted closure given in coefficients based upon the cell mapping here
    124:     }

    126:   };

    128:   class sieve_function_wrapper : ufc::function {
    129:   public:
    130:     (*_func)(double * values, const double * coords);  //the simple function that computes the value based on the coordinates.
    131:     int _rank;                                       //the number of values returned by the function

    133:     sieve_function_wrapper(){};
    134:     sieve_function_wrapper(const double * (*func)(const double * coords), int rank) {
    135:       _func = func;
    136:       _rank = rank;
    137:     }
    138:     const double * (*)(const double *) getFunction() {
    139:       return _func;
    140:     }
    141:     void setFunction(const double * (*func)(const double * coords), int rank) {
    142:       _func = func;
    143:     }
    144:     void evaluate(double * values, const double * coordinates, ufc::cell &cell) {
    145:       _func(values, coordinates);
    146:     }
    147:   };

    149:   //this class takes coordinates in a cell and produces output based upon those coordinates and the section over the mesh in that cell
    150:   //might come in handy for generalized MG, etc.
    151:   class section_wrapper_function : ufc::function {
    152:   public:

    154:     ALE::Obj<PETSC_MESH_TYPE> _m;
    155:     ALE::Obj<PETSC_MESH_TYPE::section_type> _s;
    156:     //PETSC_MESH_TYPE::point_type c;

    158:     ufc::form * _form;
    159:     ufc::finite_element * _finite_element;
    160:     ufc::cell_integral * _cell_integral;

    162:     section_wrapper_function(){};
    163:     section_wrapper_function(Obj<PETSC_MESH_TYPE> m, Obj<PETSC_MESH_TYPE::section_type> s, ufc::form form, ufc::finite_element finite_element, ufc::cell_integral::cell_integral){
    164:       _m = m;
    165:       _s = s;
    166:       _form = form;
    167:       _finite_element = finite_element;
    168:       _cell_integral = cell_integral;
    169:     }

    171:     void evaluate(double * values, const double * coordinates, ufc::cell &cell)
    172:     {
    173:       //evaluate the degrees of freedom on the interior of the given cell; note that this requires that coordinates be within the cell to really make sense.
    174:       //note for the future: we could wrap this easily into the multigrid routines
    175:       //we need an additional aggregation array of size value_rank;
    176:       const double * coefficients = m->restrictClosure(_s, cell->current_point);
    177:       const double * tmp_values = new double[_finite_element->value_rank()];
    178:       for (int i = 0; i < _finite_element->value_rank(); i++) {
    179:         values[i] = 0.;
    180:       }
    181:       for (int i = 0; i < _finite_element->value_dimension(); i++) { //loop over basis functions
    182:         _finite_element->evaluate_basis(i, tmp_values, coordinates, cell);
    183:         for (int j = 0; j < _finite_element->value_rank()+1; i++) {
    184:           values[i] += coefficients[i*(finite_element->value_rank()+1)+j]*tmp_values[j];
    185:         }
    186:       }
    187:       delete tmp_values;
    188:     }
    189:   };

    191:   class boundary_condition {
    192:   public:
    193:     PetscBool  (*_func)(PETSC_MESH_TYPE::point_type, const double *);
    194:     int marker;
    195:     int cellmarker;

    197:     boundary_condition(){};
    198:     boundary_condition (PetscBool  (*func)(PETSC_MESH_TYPE::point_type, const double *), int mark = 1, int cellmark = 2) {

    200:     }
    201:     void applyBC(Obj<PETSC_MESH_TYPE> m) {
    202:     }
    203:   };

    205:   PetscBool  Scalar_Dirichlet_Pred(PETSC_MESH_TYPE::point_type p, const double * coords) {
    206:     //set up the marker
    207:     //if anything in the star of the thing has support size 1 but not height 0 then the thing's on the boundary! mark it!
    208:     Obj<PETSC_MESH_TYPE::sieve_type::supportArray> star =
    209:   }

    211:   class UFCProblem : ALE::ParallelObject {
    212:   public:
    213:     //sieve parts
    214:     Obj<PETSC_MESH_TYPE> _mesh;

    216:     //UFC parts
    217:     //Forms:
    218:     ufc::form * _bform;
    219:     ufc::form * _lform;
    220:     //Coefficients:
    221:     int _num_bcoefficients;
    222:     double * b_w;
    223:     int _num_lcoefficients;
    224:     double * l_w;
    225:     //Finite Elements:
    226:     int _num_finite_elements;
    227:     ufc::finite_element ** _finite_elements;
    228:     //"Coefficient" elements from the RHS linear forms
    229:     int _num_coefficient_elements;
    230:     ufc::finite_element ** _coefficient_elements;
    231:     //Cell types; perhaps not
    232:     int _num_cell_types;
    233:     ufc::cell ** _cell;
    234:     //Cell integrals
    235:     int _num_cell_integrals;
    236:     ufc::cell_integral * _cell_integrals;
    237:     //Functions:
    238:     // - The RHS Function
    239:     ufc::function * _rhs_funct;
    240:     // - The "Exact Solution"
    241:     ufc::function * _exact_solution;
    242:     //We also need to define some sort of predicate system for the boundary like dolfin;
    243:     //This will involve some setting of the boundary marker, not necessarily based upon the topological boundary, but usually that.
    244:     //Initialization
    245:     UFCProblem(){};
    246:     //give it a mesh, give it a form, mark boundary segments through some f
    247:     UFCProblem(Obj<PETSC_MESH_TYPE> m, ufc::form * bform, ufc::form * lform){
    248:       _mesh = m;
    249:       _bform = bform;
    250:       _lform = lform;
    251:       //set up the bilinear form finite elements, and cell integral.
    252:       _num_finite_elements = bform->num_finite_elements();
    253:       _finite_elements = new ufc::finite_element *[_num_finite_elements];
    254:       for (int i = 0; i < _num_finite_elements; i++) {
    255:
    256:       }
    257:       //set up the linear form finite elements and cell integrals.

    259:       //set up the

    261:     }
    262:     ~UFCProblem(){};
    263:     //Accessors
    264:     void setMesh(Obj<PETSC_MESH_TYPE> m){mesh = m;}
    265:     Obj<PETSC_MESH_TYPE> getMesh() {return mesh;}
    266:     Mesh getPetscMesh() {
    267:       return NULL;
    268:     }
    269:     void setForm(ufc::form * f) {form = f;}
    270:     ufc::form * getForm() {}
    271:     void setRHSFunction(ufc::function * f){rhs_funct = f;}
    272:     ufc::function * getRHSFunction();
    273:     void setExactSolution(ufc::function * f) {exact_solution = f;}
    274:     ufc::function * getExactSolution() {
    275:       return exact_solution;
    276:     }

    279:     //Misc
    280:     void setupUFC(){
    281:       //initialize the cell, function, and finite element structures for this given problem
    282:       finite_element = form->create_finite_element(0);
    283:       dof_map = form->create_dof_map(0);
    284:       cell_integrals = form->create_cell_integral(0);

    286:       cell = new ();

    288:     };
    289:     void setCell(PETSC_MESH_TYPE::point_type c) {

    291:     }
    292:     void setupFields(Obj<PETSC_MESH_TYPE> m, Obj<PETSC_MESH_TYPE::real_section_type> s, ufc::form form, ufc::function function){
    293:       setCell
    294:     };
    295:     void assembleMatrix() {
    296:       //use the bform to create the matrix

    298:       //partial assembly?
    299:     }
    300:     void assembleRHS() {
    301:       //use the lform on the interior and the bform on the boundaries to assemble the RHS

    303:     }
    304:     void setFieldfromFunction(Obj<PETSC_MESH_TYPE> m, Obj<PETSC_MESH_TYPE::real_section_type> s, ufc::form form, ufc::function function) {

    306:     }
    307:   };
    308: }

    310: #endif

    313: /*
    314: Wrapper to ufc::function for double * func(double * coords)
    315:  */

    317: class function_wrapper_scalar : public ufc::function {
    318: private:
    319:   PetscScalar (*function)(const double * coords);

    321: public:
    322:   void setFunction(PetscScalar (*func)(const double *)) {
    323:     function = func;
    324:   }
    325:   virtual void evaluate(double * values, const double * coordinates, const ufc::cell &c) const {
    326:     values[0] = (*function)(coordinates);
    327:   }
    328: };

    330: /*
    331: Do we even need this one if we're not going to be assembling ourselves?
    332: */

    337: void Map_SieveCell_UFCCell(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type c, ufc::form * form, ufc::cell * cell, const PETSC_MESH_TYPE::point_type * _oPoints = NULL, const int _num_oPoints= -1) {
    338:   //set up the ufc cell to be equivalent to the sieve cell given by c;  Assume that the # of dofs is constant

    341:   const ALE::Obj<PETSC_MESH_TYPE::sieve_type> s = m->getSieve();
    342:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> coordinates = m->getRealSection("coordinates");
    343:   int dim = m->getDimension();
    344:   PetscPrintf(m->comm(), "cell of dimension: %d\n", cell->topological_dimension);
    345:   if ((int)cell->topological_dimension != m->getDimension() - m->height(c)) throw ALE::Exception("Wrong element dimension for this UFC form");
    346:   //  ALE::Obj<PETSC_MESH_TYPE::oConeArray> cell_closure = PETSC_MESH_TYPE::sieve_alg_type::orientedClosure(m, m->getArrowSection("orientation"), c);
    347:   const PETSC_MESH_TYPE::point_type * oPoints = _oPoints;
    348:   int num_oPoints = _num_oPoints;
    349:   if (oPoints == NULL) {
    350:     ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> oC((int) pow(m->getSieve()->getMaxConeSize(), m->depth())+1, true);
    351:     ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*s, c, oC);
    352:     PetscPrintf(m->comm(), "Got the orientedClosure\n");
    353:     oPoints = oC.getPoints();
    354:     num_oPoints = oC.getSize();
    355:   }

    357:   //PETSC_MESH_TYPE::oConeArray::iterator cc_iter = cell_closure->begin();
    358:   //PETSC_MESH_TYPE::oConeArray::iterator cc_iter_end = cell_closure->end();
    359:   int vertex_index = 0;

    361:   for (int t = 0; t < num_oPoints; t++) {
    362:     //PetscPrintf(PETSC_COMM_WORLD, "%d is in the closure\n", oPoints[t]);
    363:   //while (cc_iter != cc_iter_end) {
    364:     //FOR NOW: first order lagrange; if you have vertices then put 'em in.  This should be ordered
    365:     // (and declare victory!)
    366:     if (m->depth(oPoints[t]) == 0) {
    367:       //"entities"
    368:       //PetscPrintf(m->comm(), "%d is vertex %d\n", cc_iter->first, vertex_index);
    369:       cell->entity_indices[0][vertex_index] = oPoints[t];
    370:       //PetscPrintf(m->comm(), "%d: ", cc_iter->first);
    371:       //and coordinates
    372:       const double * tmpcoords = coordinates->restrictPoint(oPoints[t]);
    373:       for (int i = 0; i < dim; i++) {
    374:         cell->coordinates[vertex_index][i] = tmpcoords[i];
    375:       }
    376:       vertex_index++;
    377:     }
    378:   }
    379:   PetscPrintf(m->comm(), "done with cell map\n");
    380: }

    386: PetscErrorCode Assemble_Mat_UFC(Mesh mesh, SectionReal section, Mat A, ufc::form * form) {
    388:   //get, from the mesh, the assorted structures we need to do this. (numberings)

    391:   Obj<PETSC_MESH_TYPE::real_section_type> s;
    392:   SectionRealGetSection(section, s);

    394:   Obj<PETSC_MESH_TYPE> m;
    395:   MeshGetMesh(mesh, m);

    397:   PetscPrintf(m->comm(), "Beginning Matrix assembly.\n");

    399:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> coordinates = m->getRealSection("coordinates");
    400:   ALE::Obj<PETSC_MESH_TYPE::label_sequence> cells = m->heightStratum(0);
    401:   const Obj<PETSC_MESH_TYPE::order_type>& order = m->getFactory()->getGlobalOrder(m, "default", s);
    402:   int dim = m->getDimension();

    404:   ufc::cell cell;
    405:   ufc::finite_element * finite_element = form->create_finite_element(0);

    407:   //initialize the ufc infrastructure
    408:   cell.geometric_dimension = dim; //might be different; check the fiberdimension of the coordinates
    409:   cell.topological_dimension = dim;
    410:   cell.entity_indices = new unsigned int *[dim+1];
    411:   cell.entity_indices[0] = new unsigned int[dim+1];
    412:   double * tmpcellcoords = new double [(dim+1)*dim];
    413:   int space_dimension = finite_element->space_dimension();
    414:   //allow both our functions and theirs to use it!
    415:   double * localTensor = new double[space_dimension*space_dimension];
    416:   //double ** localTensor = new double*[space_dimension];
    417:   //for(int i = 0; i < space_dimension; i++) {
    418:   //  localTensor[i] = &localTensor_pointer[space_dimension*i];
    419:   //}
    420:   cell.coordinates = new double *[dim+1];

    422:   for (int i = 0; i < dim+1; i++) {
    423:     cell.coordinates[i] = &tmpcellcoords[i*dim];
    424:   }
    425:   ufc::cell_integral** cell_integrals;
    426:   cell_integrals = new ufc::cell_integral*[form->num_cell_integrals()];
    427:   if (form->num_cell_integrals() <= 0) throw ALE::Exception("Number of cell integrals in UFC form is 0.");
    428:   for (unsigned int i = 0; i < form->num_cell_integrals(); i++){
    429:     cell_integrals[i] = form->create_cell_integral(i);
    430:   }
    431:   MatZeroEntries(A);
    432:   PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin();
    433:   PETSC_MESH_TYPE::label_sequence::iterator c_iter_end = cells->end();
    434:   while (c_iter != c_iter_end) {
    435:     Map_SieveCell_UFCCell(m, *c_iter, form, &cell);
    436:     //for now just do the first cell integral.  Fix when you talk to someone about what exactly having more than one means.
    437:     //todo: coefficients.... ask if they're global and if yes ask why.
    438:     cell_integrals[0]->tabulate_tensor(localTensor, (double * const *)NULL, cell);
    439:     //see what the local tensor coming out looks like:
    440:     if (1) {
    441:       //maybe print the local tensor?
    442:     }
    443:     updateOperator(A, m, s, order, *c_iter, localTensor, ADD_VALUES);
    444:     c_iter++;
    445:   }
    446:   MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
    447:   MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
    448:   if (1) {
    449:     MatView(A, PETSC_VIEWER_STDOUT_WORLD);
    450:   }
    451:   //throw ALE::Exception("Finished the jacobian assembly for UFC; aborting for now in case it's messed up.");
    452:   return(0);
    453: }

    456: #if 0
    457: //GET THE NEW RHS_UNSTRUCTURED FOR THIS

    460: PetscErrorCode Assemble_RHS_UFC(Mesh mesh, ufc::form * bform, ufc::form * lform, SectionReal X, SectionReal section, PetscScalar (*exactFunc)(const double *)) {
    461:   Obj<PETSC_MESH_TYPE> m;

    465:   MeshGetMesh(mesh, m);

    467:   //const Obj<PETSC_MESH_TYPE::real_section_type>& coordinates   = m->getRealSection("coordinates");
    468:   const Obj<PETSC_MESH_TYPE::label_sequence>&    cells         = m->heightStratum(0);
    469:   const int                                dim           = m->getDimension();
    470:   ufc::finite_element * finite_element = lform->create_finite_element(0);
    471:   ufc::cell cell;
    472:   cell.geometric_dimension = dim;
    473:   cell.topological_dimension = dim;
    474:   cell.entity_indices = new unsigned int *[dim+1];
    475:   cell.entity_indices[0] = new unsigned int[dim];
    476:   cell.coordinates = new double *[dim+1];
    477:   double * tmpcellcoords = new double[dim*(dim+1)];
    478:   for (int i = 0; i < dim+1; i++) {
    479:     cell.coordinates[i] = &tmpcellcoords[i*dim];
    480:   }
    481:   ufc::cell_integral** cell_integrals;
    482:   cell_integrals = new ufc::cell_integral*[bform->num_cell_integrals()];
    483:   if (bform->num_cell_integrals() <= 0) throw ALE::Exception("Number of cell integrals in UFC form is 0.");
    484:   for (unsigned int i = 0; i < bform->num_cell_integrals(); i++){
    485:     cell_integrals[i] = bform->create_cell_integral(i);
    486:   }

    488:   ufc::cell_integral** cell_integrals_linear = new ufc::cell_integral*[lform->num_cell_integrals()];
    489:   for (unsigned int i = 0; i < lform->num_cell_integrals(); i++) {
    490:     cell_integrals_linear[i] = lform->create_cell_integral(i);
    491:   }

    493:   const int numBasisFuncs = finite_element->space_dimension();

    495:   //double      *t_der, *b_der, *coords, *v0, *J, *invJ, detJ;
    496:   PetscScalar *elemVec, *elemMat;

    498:   SectionRealZero(section);
    499:   PetscMalloc2(numBasisFuncs,PetscScalar,&elemVec,numBasisFuncs*numBasisFuncs,PetscScalar,&elemMat);
    500:   //  PetscMalloc6(dim,double,&t_der,dim,double,&b_der,dim,double,&coords,dim,double,&v0,dim*dim,double,&J,dim*dim,double,&invJ);
    501:   // Loop over cells
    502:   Obj<PETSC_MESH_TYPE::real_section_type> xSection;
    503:   Obj<PETSC_MESH_TYPE::real_section_type> fSection;
    504:   int c = 0;
    505:   double ** w = new double *[lform->num_coefficients()];
    506:   function_wrapper_scalar sf;
    507:   sf.setFunction(exactFunc);

    509:   for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter, ++c) {
    510:     PetscMemzero(elemVec, numBasisFuncs * sizeof(PetscScalar));
    511:     PetscMemzero(elemMat, numBasisFuncs*numBasisFuncs * sizeof(PetscScalar));
    512:     //set up the weight vector to be 0.
    513:     //three steps for this:

    515:     //build B in the finite element space
    516:     //  involves calling the
    517:     //construct A local to the boundary
    518:     //subtract AX from the boundary

    520:     //create the "neumann" RHS and put it in the vector
    521:     //m->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
    522:     Map_SieveCell_UFCCell(m, *c_iter, bform, &cell);

    524:     PetscScalar *x;

    526:     SectionRealRestrict(X, *c_iter, &x);

    528:     for (int f = 0; f < numBasisFuncs; f++) {
    529:        elemVec[f] = 0. - finite_element->evaluate_dof(f, sf, cell);
    530:        //PetscPrintf(m->comm(), "Elemvec[f](before): %f\n", elemVec[f]);
    531:     }
    532:     for(unsigned int i = 0; i < lform->num_coefficients(); i++) {
    533:       w[i] = new double[numBasisFuncs];
    534:       for (int j = 0; j < numBasisFuncs; j++){
    535:         w[i][j] = elemVec[j];
    536:       }
    537:     }

    539:     cell_integrals_linear[0]->tabulate_tensor(elemVec, w, cell);
    540:     cell_integrals[0]->tabulate_tensor(elemMat, w, cell);

    542:     for(int f = 0; f < numBasisFuncs; ++f) {
    543:       for(int g = 0; g < numBasisFuncs; ++g) {
    544:         elemVec[f] += elemMat[f*numBasisFuncs+g]*x[g];
    545:       }
    546:       //PetscPrintf(m->comm(), "x[f]: %f\n", x[f]);
    547:       //PetscPrintf(m->comm(), "elemVec[f]: %f\n", elemVec[f]);
    548:     }
    549:     SectionRealUpdateAdd(section, *c_iter, elemVec);
    550:     //m->updateAdd(fSection, c, elemVec);
    551:   }
    552:   PetscFree2(elemVec,elemMat);
    553:   //PetscFree6(t_der,b_der,coords,v0,J,invJ);
    554:   // Exchange neighbors
    555:   SectionRealComplete(section);
    556:   // Subtract the constant
    557:   if (m->hasRealSection("constant")) {
    558:     const Obj<PETSC_MESH_TYPE::real_section_type>& constant = m->getRealSection("constant");
    559:     Obj<PETSC_MESH_TYPE::real_section_type>        s;

    561:     SectionRealGetSection(section, s);
    562:     s->axpy(-1.0, constant);
    563:   }
    564:   return(0);
    565: }

    567: #endif

    570: PetscErrorCode Assemble_RHS_UFC(Mesh mesh, ufc::form * bform, ufc::form * lform, SectionReal X, SectionReal section, PetscScalar (*exactFunc)(const double *)) {

    572:   Obj<PETSC_MESH_TYPE> m;

    576:   MeshGetMesh(mesh, m);
    577:   const Obj<ALE::Discretization>&          disc          = m->getDiscretization("u");
    578:   const Obj<PETSC_MESH_TYPE::label_sequence>&    cells         = m->heightStratum(0);
    579:   const int                                dim           = m->getDimension();
    580:   PetscScalar *elemVec, *elemMat;

    582:   ufc::finite_element * finite_element = lform->create_finite_element(0);
    583:   ufc::cell cell;
    584:   cell.geometric_dimension = dim;
    585:   cell.topological_dimension = dim;
    586:   cell.entity_indices = new unsigned int *[dim+1];
    587:   cell.entity_indices[0] = new unsigned int[dim];
    588:   cell.coordinates = new double *[dim+1];
    589:   double * tmpcellcoords = new double[dim*(dim+1)];
    590:   for (int i = 0; i < dim+1; i++) {
    591:     cell.coordinates[i] = &tmpcellcoords[i*dim];
    592:   }
    593:   ufc::cell_integral** cell_integrals;
    594:   cell_integrals = new ufc::cell_integral*[bform->num_cell_integrals()];
    595:   if (bform->num_cell_integrals() <= 0) throw ALE::Exception("Number of cell integrals in UFC form is 0.");
    596:   for (unsigned int i = 0; i < bform->num_cell_integrals(); i++){
    597:     cell_integrals[i] = bform->create_cell_integral(i);
    598:   }

    600:   ufc::cell_integral** cell_integrals_linear = new ufc::cell_integral*[lform->num_cell_integrals()];
    601:   for (unsigned int i = 0; i < lform->num_cell_integrals(); i++) {
    602:     cell_integrals_linear[i] = lform->create_cell_integral(i);
    603:   }
    604:   double ** w = new double *[lform->num_coefficients()];
    605:   function_wrapper_scalar sf;
    606:     sf.setFunction(exactFunc);
    607:   const int numBasisFuncs = finite_element->space_dimension();

    610:   SectionRealZero(section);
    611:   PetscMalloc2(numBasisFuncs,PetscScalar,&elemVec,numBasisFuncs*numBasisFuncs,PetscScalar,&elemMat);
    612:   //PetscMalloc6(dim,double,&t_der,dim,double,&b_der,dim,double,&coords,dim,double,&v0,dim*dim,double,&J,dim*dim,double,&invJ);
    613:   // Loop over cells
    614:   for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
    615:     PetscMemzero(elemVec, numBasisFuncs * sizeof(PetscScalar));
    616:     PetscMemzero(elemMat, numBasisFuncs*numBasisFuncs * sizeof(PetscScalar));
    617:     //m->computeElementGeometry(coordinates, *c_iter, v0, J, invJ, detJ);
    618:     Map_SieveCell_UFCCell(m, *c_iter, bform, &cell);
    619:     //if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, *c_iter);

    621:     PetscScalar *x;

    623:     SectionRealRestrict(X, *c_iter, &x);

    625:     for (int f = 0; f < numBasisFuncs; f++) {
    626:        elemVec[f] = 0. - finite_element->evaluate_dof(f, sf, cell);
    627:        //PetscPrintf(m->comm(), "Elemvec[f](before): %f\n", elemVec[f]);
    628:     }
    629:     for(unsigned int i = 0; i < lform->num_coefficients(); i++) {
    630:       w[i] = new double[numBasisFuncs];
    631:       for (int j = 0; j < numBasisFuncs; j++){
    632:         w[i][j] = elemVec[j];
    633:       }
    634:     }

    636:     cell_integrals_linear[0]->tabulate_tensor(elemVec, w, cell);
    637:     cell_integrals[0]->tabulate_tensor(elemMat, w, cell);

    639:     for(int f = 0; f < numBasisFuncs; ++f) {
    640:       for(int g = 0; g < numBasisFuncs; ++g) {
    641:         elemVec[f] += elemMat[f*numBasisFuncs+g]*x[g];
    642:       }
    643:       //PetscPrintf(m->comm(), "x[f]: %f\n", x[f]);
    644:       //PetscPrintf(m->comm(), "elemVec[f]: %f\n", elemVec[f]);
    645:     }

    647:     SectionRealUpdateAdd(section, *c_iter, elemVec);
    648:   }
    649:   PetscFree2(elemVec,elemMat);
    650:   //PetscFree6(t_der,b_der,coords,v0,J,invJ);
    651:   // Exchange neighbors
    652:   SectionRealComplete(section);
    653:   // Subtract the constant
    654:   if (m->hasRealSection("constant")) {
    655:     const Obj<PETSC_MESH_TYPE::real_section_type>& constant = m->getRealSection("constant");
    656:     Obj<PETSC_MESH_TYPE::real_section_type>        s;

    658:     SectionRealGetSection(section, s);
    659:     s->axpy(-1.0, constant);
    660:   }
    661:   return(0);
    662: }

    665: //Integrator function based upon a given UFC:
    666: //Takes a mesh, cell, and a UFC and integrate for all the unknowns on the cell

    672: PetscErrorCode IntegrateDualBasis_UFC(ALE::Obj<PETSC_MESH_TYPE> m, PETSC_MESH_TYPE::point_type c, ufc::form & f) {

    674: }

    676: //you still have to wrap this one as the fields are set up on the basis of the discretizations; you have to set up the discretization as it would be from the form, so we have to at least fill in the fiberdimension parts of the discretization type such that setupFields can do its work.  This will be equivalent to the CreateProblem_gen_0 stuff that FIAT + Generator spits out.

    678: //CreateProblem_UFC
    679: //Takes a UFC form and generates the entire problem from it.  This involves building a discretization object within the mesh corresponding to what is sent to UFC.  Unfortunately UFC handles all the element/vectorish stuff on its own, but
    680: PetscErrorCode CreateProblem_UFC(DM dm, const char * name, ufc::form * form,  const int numBC, const int *markers, double (**bcFuncs)(const double * coords), double(*exactFunc)(const double * coords)) {
    681:   Mesh mesh = (Mesh) dm;
    682:   ALE::Obj<PETSC_MESH_TYPE> m;
    683:   PetscErrorCode 0;
    684:   //you need some finite element information from the form.
    685:   ufc::finite_element * finite_element = form->create_finite_element(0);
    686:   //needed information from the form.
    688:   MeshGetMesh(mesh, m);
    689:   //int dim = m->getDimension();
    690:   const ALE::Obj<ALE::Discretization>& d = new ALE::Discretization(m->comm(), m->debug()); //create the UFC
    691:   //for now handle only vertex unknowns; complain about the fact that Dofs per dimension isn't in the release version of UFC.
    692:   d->setNumDof(0, 1);
    693:   /*
    694:     for (int i = 0; i < dim+1; i++) {
    695:     //for each element level; find the fiberdimension from the discretization and set it in the discretization.
    696:     d->setNumDof(
    697:     }
    698:   */
    699:   d->setQuadratureSize(finite_element->space_dimension());
    700:   //boundary conditions
    701:   for (int c = 0; c < numBC; c++) {
    702:     const ALE::Obj<ALE::BoundaryCondition>& b = new ALE::BoundaryCondition(m->comm(), m->debug());
    703:     ostringstream n;
    704:     b->setLabelName("marker");
    705:     b->setMarker(markers[c]);
    706:     b->setFunction(bcFuncs[c]);
    707:     //b->setDualIntegrator(IntegrateDualBasis_gen_2);
    708:     n << c;
    709:     d->setBoundaryCondition(n.str(), b);
    710:     if (exactFunc) {
    711:       const ALE::Obj<ALE::BoundaryCondition>& e = new ALE::BoundaryCondition(m->comm(), m->debug());
    712:       e->setLabelName("marker");
    713:       e->setFunction(exactFunc);
    714:       e->setDualIntegrator(NULL); //TODO
    715:       d->setExactSolution(e);
    716:     }
    717:   }
    718:   m->setDiscretization(name, d);
    719:   return(0);
    720: }

    725: void SetupDiscretization_UFC(ALE::Obj<PETSC_MESH_TYPE> m, ufc::form * form) {
    726:   ALE::Obj<PETSC_MESH_TYPE::sieve_type> s = m->getSieve();
    727:   //we will treat the thing arising from the UFC form as a SINGLE discretization such that the separation of forms is handled transparent of sieve;
    728:   //watch out if this screws up stuff involving the eventual output of a solution; we may have to reprocess or something silly like that.
    729:   //also, where there are multiple forms what should we do?
    730:   ALE::Obj<ALE::Discretization> d = m->getDiscretization("ufc_u");

    732: }

    734: //Comment: we shouldn't need to do this!  Tie this in properly with the discretization object and then setupfield with noupdate; write a separate routine for setting the boundary values given a wrapped function.

    739: /*
    740:   This is essentially a copy of m->setupField(s) such that it can use the UFC dualintegrator from the associated form.
    741:  */

    743: #if 0

    745:  void SetupField_UFC(ALE::Obj<PETSC_MESH_TYPE> m, const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& s, ufc::form * form, const int cellMarker = 2, const bool noUpdate = false){

    747:    const ALE::Obj<PETSC_MESH_TYPE::names_type>& discs  = m->getDiscretizations();
    748:    const int              debug  = s->debug();
    749:    PETSC_MESH_TYPE::names_type  bcLabels;
    750:    int                    maxDof;

    752:    //setup the necessary UFC structures here
    753:    ufc::finite_element * finite_element = form->create_finite_element(0);
    754:    function_wrapper_scalar sf;
    755:    ufc::cell cell;
    756:    int dim = m->getDimension();
    757:    int embeddim = m->getRealSection("coordinates")->getFiberDimension(*m->depthStratum(0)->begin());
    758:    cell.geometric_dimension = embeddim;
    759:    cell.topological_dimension = dim;
    760:    cell.entity_indices = new unsigned int *[dim+1];
    761:    cell.entity_indices[0] = new unsigned int[dim];
    762:    cell.coordinates = new double *[dim+1];

    764:    double * coordpointer = new double[(dim+1)*dim];
    765:    for (int i = 0; i < dim+1; i++) {
    766:      cell.coordinates[i] = &coordpointer[dim*i];
    767:    }

    769:    s->setChart(m->getSieve()->getChart());
    770:    PetscPrintf(m->comm(), "Set the chart\n");
    771:    maxDof = m->setFiberDimensions(s, discs, bcLabels);
    772:    PetscPrintf(m->comm(), "Set the max dof\n");
    773:    m->calculateIndices();
    774:    PetscPrintf(m->comm(), "Calculated the indices\n");
    775:    m->calculateIndicesExcluded(s, discs);
    776:    PetscPrintf(m->comm(), "Calculated the excluded indices\n");
    777:    m->allocate(s);
    778:    PetscPrintf(m->comm(), "Allocated\n");
    779:    s->defaultConstraintDof();
    780:    PetscPrintf(m->comm(), "Set the default constraint DOF");
    781:    const ALE::Obj<PETSC_MESH_TYPE::label_type>& cellExclusion = m->getLabel("cellExclusion");
    782:    PetscPrintf(m->comm(), "Cell exclusion\n");
    783:    if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
    784:    PetscPrintf(m->comm(), "At the boundary condition loop\n");
    785:    for(PETSC_MESH_TYPE::names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
    786:      const ALE::Obj<PETSC_MESH_TYPE::label_sequence>&     boundaryCells = m->getLabelStratum(*n_iter, cellMarker);
    787:      //     const ALE::Obj<PETSC_MESH_TYPE::real_section_type>&  coordinates   = m->getRealSection("coordinates");
    788:      const ALE::Obj<PETSC_MESH_TYPE::names_type>&         discs         = m->getDiscretizations();
    789:      ALE::Obj<PETSC_MESH_TYPE::sieve_type> sieve = m->getSieve();
    790:      const PETSC_MESH_TYPE::point_type               firstCell     = *boundaryCells->begin();
    791:      const int                      numFields     = discs->size();
    792:      PETSC_MESH_TYPE::real_section_type::value_type *values        = new PETSC_MESH_TYPE::real_section_type::value_type[m->sizeWithBC(s, firstCell)];
    793:      int                           *dofs          = new int[maxDof];
    794:      int                           *v             = new int[numFields];
    795:      //double                        *v0            = new double[m->getDimension()];
    796:      //double                        *J             = new double[m->getDimension()*m->getDimension()];
    797:      //double                         detJ;
    798:      ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> oC((int) pow(m->getSieve()->getMaxConeSize(), m->depth())+1, true);

    800:      for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {

    802:        //const Obj<PETSC_MESH_TYPE::coneArray>      closure = PETSC_MESH_TYPE::sieve_alg_type::closure(m, m->getArrowSection("orientation"), *c_iter);
    803:        //const PETSC_MESH_TYPE::coneArray::iterator end     = closure->end();

    805:        if (debug > 1) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
    806:        ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(sieve, *c_iter, oC);
    807:        const PETSC_MESH_TYPE::point_type * oPoints = oC.getPoints();
    808:        const int num_oPoints = oC.getSize();
    809:        Map_SieveCell_UFCCell(m, *c_iter, form, &cell, oPoints, num_oPoints);
    810:        PetscPrintf(m->comm(), "successfully quit the cell map\n");
    811:        //m->computeElementGeometry(coordinates, *c_iter, v0, J, NULL, detJ);
    812:        for(int f = 0; f < numFields; ++f) v[f] = 0;
    813:        for(int t = 0; t < num_oPoints; t++) {
    814:          const int cDim = s->getConstraintDimension(oPoints[t]);
    815:          int       off  = 0;
    816:          int       f    = 0;
    817:          int       i    = -1;
    818:          if (debug > 1) {std::cout << "    point " << oPoints[t] << std::endl;}
    819:          if (cDim) {
    820:            if (debug > 1) {std::cout << "      constrained excMarker: " << m->getValue(cellExclusion, *c_iter) << std::endl;}
    821:            for(PETSC_MESH_TYPE::names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
    822:              const ALE::Obj<ALE::Discretization>& disc    = m->getDiscretization(*f_iter);
    823:              const ALE::Obj<PETSC_MESH_TYPE::names_type> bcs = disc->getBoundaryConditions();
    824:              const int                       fDim    = s->getFiberDimension(oPoints[t], f);//disc->getNumDof(m->depth(*cl_iter));
    825:              const int                      *indices = disc->getIndices(m->getValue(cellExclusion, *c_iter));
    826:              int                             b       = 0;
    827:
    828:              for(PETSC_MESH_TYPE::names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
    829:                const ALE::Obj<ALE::BoundaryCondition>& bc    = disc->getBoundaryCondition(*bc_iter);
    830:                const int                          value = m->getValue(m->getLabel(bc->getLabelName()), oPoints[t]);
    831:
    832:                if (b > 0) v[f] -= fDim;
    833:
    834:                if (value == bc->getMarker()) {
    835:                  if (debug > 1) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
    836:                  //instead, we use the form's dual integrator (evaluation
    837:                  sf.setFunction(bc->getFunction());
    838:                  /*
    839:                    for(int d = 0; d < fDim; ++d, ++v[f]) {
    840:                    dofs[++i] = off+d;
    841:                    if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
    842:                    if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    843:                    }
    844:                  */
    845:
    846:                  for (int d = 0; d < fDim; ++d, ++v[f]) {
    847:                    dofs[++i] = off+d;
    848:                    if (!noUpdate) {
    849:                      values[indices[v[f]]] = finite_element->evaluate_dof(v[f], sf, cell);
    850:                      PetscPrintf(m->comm(), "evaluated DOF %d\n", f);
    851:                    }
    852:
    853:                  }
    854:                  ++b;
    855:                  break;
    856:                } else {
    857:                  if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
    858:                  for(int d = 0; d < fDim; ++d, ++v[f]) {
    859:                    values[indices[v[f]]] = 0.0;
    860:                    if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    861:                  }
    862:                }
    863:              }
    864:              if (b == 0) {
    865:                if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
    866:                for(int d = 0; d < fDim; ++d, ++v[f]) {
    867:                  values[indices[v[f]]] = 0.0;
    868:                  if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    869:                }
    870:              }
    871:              off += fDim;
    872:            }
    873:            if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
    874:            s->setConstraintDof(oPoints[t], dofs);
    875:          } else {
    876:            if (debug > 1) {std::cout << "      unconstrained" << std::endl;}
    877:            for(PETSC_MESH_TYPE::names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
    878:              const Obj<ALE::Discretization>& disc    = m->getDiscretization(*f_iter);
    879:              const int                       fDim    = s->getFiberDimension(oPoints[t], f);//disc->getNumDof(m->depth(*cl_iter));
    880:              const int                      *indices = disc->getIndices(m->getValue(cellExclusion, *c_iter));
    881:
    882:              if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
    883:              for(int d = 0; d < fDim; ++d, ++v[f]) {
    884:                values[indices[v[f]]] = 0.0;
    885:                if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    886:              }
    887:            }
    888:          }
    889:        }
    890: #if 0
    891:        if (debug > 1) {
    892:          const Obj<PETSC_MESH_TYPE::sieve_type::coneArray>      closure = PETSC_MESH_TYPE::sieve_alg_type::closure(m, m->getArrowSection("orientation"), *c_iter);
    893:          const PETSC_MESH_TYPE::sieve_type::coneArray::iterator end     = closure->end();
    894:
    895:          for(int f = 0; f < numFields; ++f) v[f] = 0;
    896:          for(PETSC_MESH_TYPE::sieve_type::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
    897:            int f = 0;
    898:            for(PETSC_MESH_TYPE::names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
    899:              const Obj<ALE::Discretization>& disc    = m->getDiscretization(*f_iter);
    900:              const int                       fDim    = s->getFiberDimension(*cl_iter, f);
    901:              const int                      *indices = disc->getIndices(m->getValue(cellExclusion, *c_iter));
    902:
    903:              for(int d = 0; d < fDim; ++d, ++v[f]) {
    904:                std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
    905:              }
    906:            }
    907:          }
    908:        }
    909: #endif
    910:        if (!noUpdate) {
    911:          m->updateAll(s, *c_iter, values);
    912:        }
    913:      }
    914:      PetscPrintf(m->comm(), "Done with the cell loop.\n");
    915:      delete [] dofs;
    916:      delete [] values;
    917:    }
    918:    if (debug > 1) {s->view("");}
    919:  }

    921: #endif

    923: void SetupField_UFC(ALE::Obj<PETSC_MESH_TYPE> m, const ALE::Obj<PETSC_MESH_TYPE::real_section_type>& s, ufc::form * form, const int cellMarker = 2, const bool noUpdate = false) {
    924:   typedef ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> Visitor;
    925:   const ALE::Obj<PETSC_MESH_TYPE::names_type>& discs  = m->getDiscretizations();
    926:   const int              debug  = s->debug();
    927:   PETSC_MESH_TYPE::names_type             bcLabels;

    929:   s->setChart(m->getSieve()->getChart());
    930:   int maxdof = m->setFiberDimensions(s, discs, bcLabels);
    931:   m->calculateIndices();
    932:   m->calculateIndicesExcluded(s, discs);
    933:   m->allocate(s);
    934:   s->defaultConstraintDof();
    935:   const ALE::Obj<PETSC_MESH_TYPE::label_type>& cellExclusion = m->getLabel("cellExclusion");

    937:    ufc::finite_element * finite_element = form->create_finite_element(0);
    938:    function_wrapper_scalar sf;
    939:    ufc::cell cell;
    940:    int dim = m->getDimension();
    941:    int embeddim = m->getRealSection("coordinates")->getFiberDimension(*m->depthStratum(0)->begin());
    942:    cell.geometric_dimension = embeddim;
    943:    cell.topological_dimension = dim;
    944:    cell.entity_indices = new unsigned int *[dim+1];
    945:    cell.entity_indices[0] = new unsigned int[dim];
    946:    cell.coordinates = new double *[dim+1];

    948:    double * coordpointer = new double[(dim+1)*dim];
    949:    for (int i = 0; i < dim+1; i++) {
    950:      cell.coordinates[i] = &coordpointer[dim*i];
    951:    }

    954:   if (debug > 1) {std::cout << "Setting boundary values" << std::endl;}
    955:   for(PETSC_MESH_TYPE::names_type::const_iterator n_iter = bcLabels.begin(); n_iter != bcLabels.end(); ++n_iter) {
    956:     function_wrapper_scalar sf;
    957:     const ALE::Obj<PETSC_MESH_TYPE::label_sequence>&     boundaryCells = m->getLabelStratum(*n_iter, cellMarker);
    958:     const ALE::Obj<PETSC_MESH_TYPE::real_section_type>&  coordinates   = m->getRealSection("coordinates");
    959:     const ALE::Obj<PETSC_MESH_TYPE::names_type>&         discs         = m->getDiscretizations();
    960:     const PETSC_MESH_TYPE::point_type               firstCell     = *boundaryCells->begin();
    961:     const int                      numFields     = discs->size();
    962:     PETSC_MESH_TYPE::real_section_type::value_type *values        = new PETSC_MESH_TYPE::real_section_type::value_type[m->sizeWithBC(s, firstCell)];
    963:     int                           *dofs          = new int[maxdof];
    964:     int                           *v             = new int[numFields];
    965:     double                        *v0            = new double[m->getDimension()];
    966:     double                        *J             = new double[m->getDimension()*m->getDimension()];
    967:     double                         detJ;
    968:     Visitor pV((int) pow(m->getSieve()->getMaxConeSize(), m->depth())+1, true);

    970:     for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = boundaryCells->begin(); c_iter != boundaryCells->end(); ++c_iter) {
    971:       ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*m->getSieve(), *c_iter, pV);
    972:       const Visitor::point_type *oPoints = pV.getPoints();
    973:       const int                  oSize   = pV.getSize();

    975:       if (debug > 1) {std::cout << "  Boundary cell " << *c_iter << std::endl;}
    976:       m->computeElementGeometry(coordinates, *c_iter, v0, J, NULL, detJ);
    977:       for(int f = 0; f < numFields; ++f) v[f] = 0;
    978:       for(int cl = 0; cl < oSize; ++cl) {
    979:         const int cDim = s->getConstraintDimension(oPoints[cl]);
    980:         int       off  = 0;
    981:         int       f    = 0;
    982:         int       i    = -1;
    983:
    984:         if (debug > 1) {std::cout << "    point " << oPoints[cl] << std::endl;}
    985:         if (cDim) {
    986:           if (debug > 1) {std::cout << "      constrained excMarker: " << m->getValue(cellExclusion, *c_iter) << std::endl;}
    987:           for(PETSC_MESH_TYPE::names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
    988:             const Obj<ALE::Discretization>& disc    = m->getDiscretization(*f_iter);
    989:             const Obj<PETSC_MESH_TYPE::names_type>           bcs     = disc->getBoundaryConditions();
    990:             const int                       fDim    = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
    991:             const int                      *indices = disc->getIndices(m->getValue(cellExclusion, *c_iter));
    992:             int                             b       = 0;
    993:
    994:             for(PETSC_MESH_TYPE::names_type::const_iterator bc_iter = bcs->begin(); bc_iter != bcs->end(); ++bc_iter, ++b) {
    995:               const Obj<ALE::BoundaryCondition>& bc    = disc->getBoundaryCondition(*bc_iter);
    996:               const int                          value = m->getValue(m->getLabel(bc->getLabelName()), oPoints[cl]);
    997:               sf.setFunction(bc->getFunction());
    998:               if (b > 0) v[f] -= fDim;
    999:               if (value == bc->getMarker()) {
    1000:                 if (debug > 1) {std::cout << "      field " << *f_iter << " marker " << value << std::endl;}
    1001:                 for (int d = 0; d < fDim; ++d, ++v[f]) {
    1002:                   dofs[++i] = off+d;
    1003:                   if (!noUpdate) {
    1004:                     values[indices[v[f]]] = finite_element->evaluate_dof(v[f], sf, cell);
    1005:                     PetscPrintf(m->comm(), "evaluated DOF %d\n", f);
    1006:                   }
    1007:                 }
    1008:                 /*
    1009:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
    1010:                   dofs[++i] = off+d;
    1011:                   if (!noUpdate) values[indices[v[f]]] = (*bc->getDualIntegrator())(v0, J, v[f], bc->getFunction());
    1012:                   if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    1013:                 }
    1014:                 */
    1015:                 // Allow only one condition per point
    1016:                 ++b;
    1017:                 break;
    1018:               } else {
    1019:                 if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
    1020:                 for(int d = 0; d < fDim; ++d, ++v[f]) {
    1021:                   values[indices[v[f]]] = 0.0;
    1022:                   if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    1023:                 }
    1024:               }
    1025:             }
    1026:             if (b == 0) {
    1027:               if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
    1028:               for(int d = 0; d < fDim; ++d, ++v[f]) {
    1029:                 values[indices[v[f]]] = 0.0;
    1030:                 if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    1031:               }
    1032:             }
    1033:             off += fDim;
    1034:           }
    1035:           if (i != cDim-1) {throw ALE::Exception("Invalid constraint initialization");}
    1036:           s->setConstraintDof(oPoints[cl], dofs);
    1037:         } else {
    1038:           if (debug > 1) {std::cout << "      unconstrained" << std::endl;}
    1039:           for(PETSC_MESH_TYPE::names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
    1040:             const Obj<ALE::Discretization>& disc    = m->getDiscretization(*f_iter);
    1041:             const int                       fDim    = s->getFiberDimension(oPoints[cl], f);//disc->getNumDof(this->depth(oPoints[cl]));
    1042:             const int                      *indices = disc->getIndices(m->getValue(cellExclusion, *c_iter));
    1043:
    1044:             if (debug > 1) {std::cout << "      field " << *f_iter << std::endl;}
    1045:             for(int d = 0; d < fDim; ++d, ++v[f]) {
    1046:               values[indices[v[f]]] = 0.0;
    1047:               if (debug > 1) {std::cout << "      setting values["<<indices[v[f]]<<"] = " << values[indices[v[f]]] << std::endl;}
    1048:             }
    1049:           }
    1050:         }
    1051:       }
    1052:       if (debug > 1) {
    1053:         for(int f = 0; f < numFields; ++f) v[f] = 0;
    1054:         for(int cl = 0; cl < oSize; ++cl) {
    1055:           int f = 0;
    1056:           for(PETSC_MESH_TYPE::names_type::const_iterator f_iter = discs->begin(); f_iter != discs->end(); ++f_iter, ++f) {
    1057:             const Obj<ALE::Discretization>& disc    = m->getDiscretization(*f_iter);
    1058:             const int                       fDim    = s->getFiberDimension(oPoints[cl], f);
    1059:             const int                      *indices = disc->getIndices(m->getValue(cellExclusion, *c_iter));
    1060:
    1061:             for(int d = 0; d < fDim; ++d, ++v[f]) {
    1062:               std::cout << "    "<<*f_iter<<"-value["<<indices[v[f]]<<"] " << values[indices[v[f]]] << std::endl;
    1063:             }
    1064:           }
    1065:         }
    1066:       }
    1067:       if (!noUpdate) {
    1068:         m->updateAll(s, *c_iter, values);
    1069:       }
    1070:       pV.clear();
    1071:     }
    1072:     delete [] dofs;
    1073:     delete [] values;
    1074:     delete [] v0;
    1075:     delete [] J;
    1076:   }
    1077:   if (debug > 1) {s->view("");}
    1078: }

    1083:  PetscErrorCode CreateExactSolution_UFC(Obj<PETSC_MESH_TYPE> m, Obj<PETSC_MESH_TYPE::real_section_type> s, ufc::form * form, PetscScalar (*exactSolution)(const double *))
    1084:  {
    1085:    const int      dim = m->getDimension();
    1086:    //PetscBool      flag;

    1090:    SetupField_UFC(m, s, form);
    1091:    ufc::finite_element * finite_element = form->create_finite_element(0);
    1092:    ufc::cell cell;
    1093:    cell.geometric_dimension = dim;
    1094:    cell.topological_dimension = dim;
    1095:    cell.entity_indices = new unsigned int *[dim+1];
    1096:    cell.entity_indices[0] = new unsigned int[dim];
    1097:    cell.coordinates = new double *[dim+1];
    1098:    double * tmpcellcoords = new double[dim*(dim+1)];
    1099:    for (int i = 0; i < dim+1; i++) {
    1100:     cell.coordinates[i] = &tmpcellcoords[i*dim];
    1101:   }
    1102:    const Obj<PETSC_MESH_TYPE::label_sequence>&     cells       = m->heightStratum(0);
    1103:    //const Obj<PETSC_MESH_TYPE::real_section_type>&  coordinates = m->getRealSection("coordinates");
    1104:    const int                                 localDof    = m->sizeWithBC(s, *cells->begin());
    1105:    PETSC_MESH_TYPE::real_section_type::value_type *values      = new PETSC_MESH_TYPE::real_section_type::value_type[localDof];
    1106:    function_wrapper_scalar sf;
    1107:    sf.setFunction(exactSolution);
    1108:    for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
    1109:      const Obj<PETSC_MESH_TYPE::coneArray>      closure = ALE::SieveAlg<ALE::Mesh>::closure(m, *c_iter);
    1110:      const PETSC_MESH_TYPE::coneArray::iterator end     = closure->end();
    1111:      int                                  v       = 0;

    1113:      //m->computeElementGeometry(coordinates, *c_iter, v0, J, NULL, detJ);
    1114:      Map_SieveCell_UFCCell(m, *c_iter, form, &cell);
    1115:      for(PETSC_MESH_TYPE::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
    1116:        const int pointDim = s->getFiberDimension(*cl_iter);
    1117:        //FOR NOW: keep this, only get rid of the integration routine.
    1118:        if (pointDim) {
    1119:          for(int d = 0; d < pointDim; ++d, ++v) {
    1120:            values[v] = finite_element->evaluate_dof(v, sf, cell);
    1121:            //values[v] = (*options->integrate)(v0, J, v, options->exactFunc);
    1122:          }
    1123:        }
    1124:      }
    1125:      m->updateAll(s, *c_iter, values);
    1126:    }
    1127:    s->view("setup field");
    1128:    return(0);
    1129:  }