void
TestInterpolationHDiv<Dim>::testInterpolation()
{
    // expr to interpolate
    int is3D = 0;
    if( Dim == 3 )
        is3D = 1;

    auto myexpr = unitX() + unitY() + is3D*unitZ() ; //(1,1)

    auto mesh = loadMesh( _mesh=new Mesh<Simplex<Dim>> );
    space_ptrtype Xh = space_type::New( mesh ); // RT function space

    auto u_on = Xh->element();
    auto u_proj = Xh->element();

    //test on keyword
    u_on.on(_range=elements(mesh), _expr=myexpr);
    //test project keyword
    u_proj = vf::project(_space=Xh, _range=elements(mesh), _expr=myexpr);

    //L2 norm of error
    auto error_on = vf::project(_space=Xh, _range=elements(mesh), _expr=myexpr - idv(u_on) );
    double L2error_on = error_on.l2Norm();
    std::cout << "[on] L2 error  = " << L2error_on << std::endl;

    auto error_proj = vf::project(_space=Xh, _range=elements(mesh), _expr=myexpr - idv(u_proj) );
    double L2error_proj = error_proj.l2Norm();
    std::cout << "[proj] L2 error  = " << L2error_proj << std::endl;
}
STKUNIT_UNIT_TEST(norm, string_function_1)
{
  EXCEPTWATCH;
  LocalFixture     fix(4);
  mesh::fem::FEMMetaData&        metaData     = fix.metaData;
  mesh::BulkData&        bulkData     = fix.bulkData;
  //PerceptMesh&        eMesh     = fix.eMesh;
  //mesh::FieldBase*       coords_field = fix.coords_field;
  StringFunction   sfx          = fix.sfx;
  ConstantFunction sfx_res      = fix.sfx_res;

  /// Create the operator that will do the work
  /// get the l2 norm
  Norm<2> l2Norm(bulkData, &metaData.universal_part(), TURBO_NONE);
  if (0) l2Norm(sfx, sfx_res);

  /// the function to be integrated:  sqrt(Integral[(x*y*z)^2, dxdydz]) =?= (see unitTest1.py)
  StringFunction sfxyz("x*y*z", Name("sfxyz"), Dimensions(3), Dimensions(1) );
  //l2Norm(sfxyz, sfx_res);
  //sfx_expect = 0.0240562612162344;
  //STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());

  /// indirection
  std::cout << "tmp srk start..." << std::endl;
  StringFunction sfxyz_first("sfxyz", Name("sfxyz_first"), Dimensions(3), Dimensions(1) );
  l2Norm(sfxyz_first, sfx_res);
  double sfx_expect = 0.0240562612162344;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());
}
void
TestInterpolationHCurl::testInterpolation( std::string one_element_mesh )
{
    // expr to interpolate
    auto myexpr = unitX() + unitY(); //(1,1)

    // one element mesh
    auto mesh_name = one_element_mesh + ".msh"; //create the mesh and load it
    fs::path mesh_path( mesh_name );

    mesh_ptrtype oneelement_mesh = loadMesh( _mesh=new mesh_type,
                                             _filename=mesh_name);

    // refined mesh (export)
    auto refine_level = std::floor(1 - math::log( 0.1 )); //Deduce refine level from meshSize (option)
    mesh_ptrtype mesh = loadMesh( _mesh=new mesh_type,
                                  _filename=mesh_name,
                                  _refine=( int )refine_level);

    space_ptrtype Xh = space_type::New( oneelement_mesh );
    std::vector<std::string> faces, edges; //list of edges
    edges = {"hypo","vert","hor"};

    element_type U_h_int = Xh->element();
    element_type U_h_on = Xh->element();
    element_type U_h_on_boundary = Xh->element();

    // handly computed interpolant coeff (in hcurl basis)
    for ( int i = 0; i < Xh->nLocalDof(); ++i )
        {
            CHECK( oneelement_mesh->hasMarkers( {edges[i]} ) );
            U_h_int(i) = integrate( markedfaces( oneelement_mesh, edges[i] ), trans( T() )*myexpr ).evaluate()(0,0);
        }

    // nedelec interpolant using on
    U_h_on.zero();
    U_h_on.on(_range=elements(oneelement_mesh), _expr=myexpr);
    U_h_on_boundary.on(_range=boundaryfaces(oneelement_mesh), _expr=myexpr);

    auto exporter_proj = exporter( _mesh=mesh, _name=( boost::format( "%1%" ) % this->about().appName() ).str() );
    exporter_proj->step( 0 )->add( "U_interpolation_handly_"+mesh_path.stem().string(), U_h_int );
    exporter_proj->step( 0 )->add( "U_interpolation_on_"+mesh_path.stem().string(), U_h_on );
    exporter_proj->save();

    // print coefficient only for reference element
    U_h_int.printMatlab( "U_h_int_" + mesh_path.stem().string() + ".m" );
    U_h_on.printMatlab( "U_h_on_" + mesh_path.stem().string() + ".m" );
    U_h_on_boundary.printMatlab( "U_h_on_boundary_" + mesh_path.stem().string() + ".m" );

    //L2 norm of error
    auto error = vf::project(_space=Xh, _range=elements(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on) );
    double L2error = error.l2Norm();
    std::cout << "L2 error (elements)  = " << L2error << std::endl;

    auto error_boundary = vf::project(_space=Xh, _range=boundaryfaces(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on_boundary) );
    double L2error_boundary = error_boundary.l2Norm();
    std::cout << "L2 error (boundary)  = " << L2error_boundary << std::endl;
    BOOST_CHECK_SMALL( L2error_boundary - L2error, 1e-13 );
}
tarch::la::Vector<DIMENSIONS, double> particles::pit::myfunctions::CoordinatesRepresentationChange::computeL2Norm( const particles::pit::Cell& fineGridCell ) {

  const int cellIndex = fineGridCell.getCellIndex();
  const int NumberOfParticles = ParticleHeap::getInstance().getData(cellIndex).size();
  const ParticleHeap::HeapEntries& currentParticles = ParticleHeap::getInstance().getData(cellIndex);
  const ParticleCompressedHeap::HeapEntries& compressedParticles = ParticleCompressedHeap::getInstance().getData(cellIndex);

  tarch::la::Vector<DIMENSIONS, double> l2Norm(0);
  tarch::la::Vector<DIMENSIONS, double> MeanCoordinate(0);

  if ( NumberOfParticles > 0 ) {
    // Compute the mean value of the coordinate for each axes
    MeanCoordinate = computeMeanCoordinate(currentParticles, NumberOfParticles);


    for (int i=0; i<NumberOfParticles; i++) {
	  for(int d=0; d < DIMENSIONS; d++) {
	    l2Norm[d] += std::abs(compressedParticles.at(i).getX()[d]);
	  }
    }
    for (int d =0; d<DIMENSIONS; d++) {
      l2Norm[d] /= NumberOfParticles;
    }
  }


  return l2Norm;
}
void
TestInterpolationHDiv<Dim>::testInterpolationOneElt( std::string one_element_mesh )
{
    // expr to interpolate
    int is3D = 0;
    if( Dim == 3 )
        is3D = 1;

    auto myexpr = unitX() + unitY() + is3D*unitZ() ; //(1,1)

    // one element mesh
    auto mesh_name = one_element_mesh + ".msh"; //create the mesh and load it
    fs::path mesh_path( mesh_name );

    mesh_ptrtype oneelement_mesh = loadMesh( _mesh=new mesh_type,
                                             _filename=mesh_name);

    // refined mesh (export)
    auto refine_level = std::floor(1 - math::log( 0.1 )); //Deduce refine level from meshSize (option)
    mesh_ptrtype mesh = loadMesh( _mesh=new mesh_type,
                                  _filename=mesh_name,
                                  _refine=( int )refine_level);

    space_ptrtype Xh = space_type::New( oneelement_mesh );
    //std::cout << "nb dof = " << Xh->nDof() << std::endl;

    std::vector<std::string> faces;
    if(Dim == 2)
        faces = { "hypo","vert","hor"};
    else if (Dim == 3)
        faces = {"xzFace","xyFace","xyzFace","yzFace"};

    element_type U_h_int = Xh->element();
    element_type U_h_on = Xh->element();

    // handly computed interpolant coeff (in hdiv basis)
    for ( int i = 0; i < Xh->nLocalDof(); ++i )
        {
            CHECK( mesh->hasMarkers( {faces[i]} ) );
            U_h_int(i) = integrate( markedfaces( oneelement_mesh, faces[i] ), trans( N() )*myexpr ).evaluate()(0,0);
        }

    // raviart-thomas interpolant using on
    U_h_on.zero();
    U_h_on.on(_range=elements(oneelement_mesh), _expr=myexpr);

    auto exporter_proj = exporter( _mesh=mesh, _name=( boost::format( "%1%-%2%" ) % this->about().appName() %mesh_path.stem().string() ).str() );
    exporter_proj->step( 0 )->add( "U_interpolation_handly-" + mesh_path.stem().string(), U_h_int );
    exporter_proj->step( 0 )->add( "U_interpolation_on-" + mesh_path.stem().string(), U_h_on );
    exporter_proj->save();

    U_h_int.printMatlab( "U_h_int_" + mesh_path.stem().string() + ".m" );
    U_h_on.printMatlab( "U_h_on_" + mesh_path.stem().string() + ".m" );

    //L2 norm of error
    auto error = vf::project(_space=Xh, _range=elements(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on) );
    double L2error = error.l2Norm();
    std::cout << "L2 error  = " << L2error << std::endl;
}
Exemple #6
0
int main(int argc, char**argv){


  std::vector<double> vertices, BBmin, BBmax;
  std::vector<unsigned> triangles;

  if(!readObj(argv[1], vertices, triangles, BBmin, BBmax)){
    std::cout << "couldn't read OBJ" << std::endl;
    exit(1);
  }

  std::cout << "bbmin: " << BBmin[0] << " " << BBmin[1] << " " << BBmin[2] << std::endl;
  std::cout << "bbmax: " << BBmax[0] << " " << BBmax[1] << " " << BBmax[2] << std::endl;

  for(auto i : range(vertices.size()/3)){
    vertices[3*i + 1] += 5;
  }

  std::cout << "vertices size: " << vertices.size() << std::endl;

  
  std::set<Edge> edgesSet;

  for(auto i : range(triangles.size()/3)){

    auto t = 3*i;

    for( auto j : range(3)){
      auto e1 = triangles[t + j];
      auto e2 = triangles[t + ((j +1)%3)];

      if( e2 < e1){
	std::swap(e1, e2);
      }

      auto e = Edge(e1, e2, triangles[t + ((j + 2)%3)]);
      auto it = edgesSet.find(e);

      if(it == edgesSet.end()){
	edgesSet.insert(it, e);
      } else {
	e.t2 = it->t1;
	edgesSet.erase(it);
	edgesSet.insert(e);
	
      }

    }
  }





  std::vector<Edge> edges(edgesSet.begin(), edgesSet.end());

  //  for(const auto& e : edges){
  // std::cout << "e1: " << e.e1 << " e2: " << e.e2 << " t1 " << e.t1 << " t2 : " << e.t2 << " e length " << e.edgeLength << " d length : " << e.dihedralLength << std::endl;
  // }

  std::cout << "about to set edge lengths" << std::endl;

  for(auto& e : edges){
    e.edgeLength = l2Norm(vertices.begin() + 3*e.e1,
			  vertices.begin() + 3*e.e2);
    
    if(e.t1 < vertices.size() && e.t2 < vertices.size()){
      e.dihedralLength = l2Norm(vertices.begin() + 3*e.t1,
				vertices.begin() + 3*e.t2);
    }
  }

  //for(auto i : range (vertices.size()/3)){
  //  std::cout << "vertex: " << i << " " << vertices[i*3] << " " << vertices[i*3 + 1] << " " << vertices[i*3 + 2] << std::endl;
  // }

  //for(const auto& e : edges){
  // std::cout << "e1: " << e.e1 << " e2: " << e.e2 << " t1 " << e.t1 << " t2 : " << e.t2 << " e length " << e.edgeLength << " d length : " << e.dihedralLength << std::endl;
  //}


  std::cout << "computed edge rest lengths" << std::endl;

  if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
    std::cout << "couldn't init SDL" << std::endl;
    exit(1);
  }
  
  if((surface = SDL_CreateWindow("3.2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,                
				 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN)) == NULL){
    std::cout << "couldn't create SDL surface" << std::endl;
    exit(1);
  }

  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  auto* context = SDL_GL_CreateContext(surface);




  double dt = atof(argv[2]);
  
  std::cout << "about to loop" << std::endl;

  simulationLoop(vertices, edges, dt);
  

  return 0;
}
Exemple #7
0
void simulateFrame(std::vector<double>& vertices, std::vector<double>& velocities, std::vector<Edge>& edges, double dt){

  
  //gravity
  //assume everything has mass 1

  forces.assign(vertices.size(), 0.0);

  for(auto i : range(vertices.size()/3)){
    forces[3*i +1] -= 9.81;
  }

  double kStretch = 20000;
  double kDamp = 100;
  double kBend = 20000;

  for(auto& e : edges){
    
    double direction[3];
    auto currentDistance = l2Norm(vertices.begin() + 3*e.e1, vertices.begin() + 3*e.e2);
    
    direction[0] = vertices[3*e.e1] - vertices[3*e.e2];
    direction[1] = vertices[3*e.e1 + 1] - vertices[3*e.e2 + 1];
    direction[2] = vertices[3*e.e1 + 2] - vertices[3*e.e2 + 2];
    
    direction[0] /= currentDistance;
    direction[1] /= currentDistance;
    direction[2] /= currentDistance;

    auto magnitude = kStretch*(e.edgeLength - currentDistance);
    forces[3*e.e1] += direction[0]*magnitude;
    forces[3*e.e1 + 1] += direction[1]*magnitude;
    forces[3*e.e1 + 2] += direction[2]*magnitude;

    forces[3*e.e2] -= direction[0]*magnitude;
    forces[3*e.e2 + 1] -= direction[1]*magnitude;
    forces[3*e.e2 + 2] -= direction[2]*magnitude;


    //damping forces:
    
    double deltaV[3];
    deltaV[0] = velocities[3*e.e1] - velocities[3*e.e2];
    deltaV[1] = velocities[3*e.e1 + 1] - velocities[3*e.e2 + 1];
    deltaV[2] = velocities[3*e.e1 + 2] - velocities[3*e.e2 + 2];
    
    magnitude = -kDamp*(deltaV[0]*direction[0] + deltaV[1]*direction[1] + deltaV[2]*direction[2]);
    
    //forces[3*e.e1] += deltaV[0]*directio 

    //magnitude = -kDamp*velocityMag;
    forces[3*e.e1] += direction[0]*magnitude;
    forces[3*e.e1 + 1] += direction[1]*magnitude;
    forces[3*e.e1 + 2] += direction[2]*magnitude;
    
    forces[3*e.e2] -= direction[0]*magnitude;
    forces[3*e.e2 + 1] -= direction[1]*magnitude;
    forces[3*e.e2 + 2] -= direction[2]*magnitude;
    

    //bending forces:
    if(e.t1 < (vertices.size()/3) && e.t2 < (vertices.size()/3)){
      
      currentDistance = l2Norm(vertices.begin() + 3*e.t1, vertices.begin() + 3*e.t2);
    
      direction[0] = vertices[3*e.t1] - vertices[3*e.t2];
      direction[1] = vertices[3*e.t1 + 1] - vertices[3*e.t2 + 1];
      direction[2] = vertices[3*e.t1 + 2] - vertices[3*e.t2 + 2];
    
      direction[0] /= currentDistance;
      direction[1] /= currentDistance;
      direction[2] /= currentDistance;
      
      auto magnitude = kBend*(e.dihedralLength - currentDistance);
      forces[3*e.t1] += direction[0]*magnitude;
      forces[3*e.t1 + 1] += direction[1]*magnitude;
      forces[3*e.t1 + 2] += direction[2]*magnitude;
      
      forces[3*e.t2] -= direction[0]*magnitude;
      forces[3*e.t2 + 1] -= direction[1]*magnitude;
      forces[3*e.t2 + 2] -= direction[2]*magnitude;


    }
    
    

  }

  



  //timestep velocities
  for(auto i : range(velocities.size())){
    velocities[i] += forces[i]*dt;
  }
  //timestep positions
  for(auto i : range(vertices.size())){
    vertices[i] += velocities[i]*dt;
  }
  for(auto i : range(vertices.size()/3)){
    if(vertices[3*i +1] < 0){
      vertices[3*i +1] = 0;
      velocities[3*i + 1] = 0;
    }
  }

}
void
TestInterpolationHCurl3D::testInterpolation( std::string one_element_mesh )
{
    //auto myexpr = unitX() + unitY() + unitZ() ; //(1,1,1)
    auto myexpr = vec( cst(1.), cst(1.), cst(1.));

    // one element mesh
    auto mesh_name = one_element_mesh + ".msh"; //create the mesh and load it
    fs::path mesh_path( mesh_name );

    mesh_ptrtype oneelement_mesh = loadMesh( _mesh=new mesh_type,
                                             _filename=mesh_name);

    // refined mesh (export)
    auto refine_level = std::floor(1 - math::log( 0.1 )); //Deduce refine level from meshSize (option)
    mesh_ptrtype mesh = loadMesh( _mesh=new mesh_type,
                                  _filename=mesh_name,
                                  _refine=( int )refine_level);

    space_ptrtype Xh = space_type::New( oneelement_mesh );

    std::vector<std::string> faces = {"yzFace","xyzFace","xyFace"};
    std::vector<std::string> edges = {"zAxis","yAxis","yzAxis","xyAxis","xzAxis","xAxis"};

    element_type U_h_int = Xh->element();
    element_type U_h_on = Xh->element();
    element_type U_h_on_boundary = Xh->element();

    submesh1d_ptrtype edgeMesh( new submesh1d_type );
    edgeMesh = createSubmesh(oneelement_mesh, boundaryedges(oneelement_mesh) ); //submesh of edges

    // Tangents on ref element
    auto t0 = vec(cst(0.),cst(0.),cst(-2.));
    auto t1 = vec(cst(0.),cst(2.),cst(0.));
    auto t2 = vec(cst(0.),cst(-2.),cst(2.));
    auto t3 = vec(cst(2.),cst(-2.),cst(0.));
    auto t4 = vec(cst(2.),cst(0.),cst(-2.));
    auto t5 = vec(cst(2.),cst(0.),cst(0.));

    // Jacobian of geometrical transforms
    std::string jac;
    if(mesh_path.stem().string() == "one-elt-ref-3d" || mesh_path.stem().string() == "one-elt-real-h**o-3d" )
        jac = "{1,0,0,0,1,0,0,0,1}:x:y:z";
    else if(mesh_path.stem().string() == "one-elt-real-rotx" )
        jac = "{1,0,0,0,0,-1,0,1,0}:x:y:z";
    else if(mesh_path.stem().string() == "one-elt-real-roty" )
        jac = "{0,0,1,0,1,0,-1,0,0}:x:y:z";
    else if(mesh_path.stem().string() == "one-elt-real-rotz" )
        jac = "{0,-1,0,1,0,0,0,0,1}:x:y:z";

    U_h_int(0) = integrate( markedelements(edgeMesh, edges[0]), trans(expr<3,3>(jac)*t0)*myexpr ).evaluate()(0,0);
    U_h_int(1) = integrate( markedelements(edgeMesh, edges[1]), trans(expr<3,3>(jac)*t1)*myexpr ).evaluate()(0,0);
    U_h_int(2) = integrate( markedelements(edgeMesh, edges[2]), trans(expr<3,3>(jac)*t2)*myexpr ).evaluate()(0,0);
    U_h_int(3) = integrate( markedelements(edgeMesh, edges[3]), trans(expr<3,3>(jac)*t3)*myexpr ).evaluate()(0,0);
    U_h_int(4) = integrate( markedelements(edgeMesh, edges[4]), trans(expr<3,3>(jac)*t4)*myexpr ).evaluate()(0,0);
    U_h_int(5) = integrate( markedelements(edgeMesh, edges[5]), trans(expr<3,3>(jac)*t5)*myexpr ).evaluate()(0,0);

    for(int i=0; i<edges.size(); i++)
        {
            double edgeLength = integrate( markedelements(edgeMesh, edges[i]), cst(1.) ).evaluate()(0,0);
            U_h_int(i) /= edgeLength;
        }

#if 0 //Doesn't work for now
    for(int i=0; i<Xh->nLocalDof(); i++)
        {
            CHECK( edgeMesh->hasMarkers( {edges[i]} ) );
            U_h_int(i) = integrate( markedelements(edgeMesh, edges[i]), trans( print(T(),"T=") )*myexpr ).evaluate()(0,0);
            std::cout << "U_h_int(" << i << ")= " << U_h_int(i) << std::endl;
        }
#endif

    // nedelec interpolant using on keyword
    // interpolate on element
    U_h_on.zero();
    U_h_on.on(_range=elements(oneelement_mesh), _expr=myexpr);
    U_h_on_boundary.on(_range=boundaryfaces(oneelement_mesh), _expr=myexpr);

    auto exporter_proj = exporter( _mesh=mesh, _name=( boost::format( "%1%" ) % this->about().appName() ).str() );
    exporter_proj->step( 0 )->add( "U_interpolation_handly_"+mesh_path.stem().string(), U_h_int );
    exporter_proj->step( 0 )->add( "U_interpolation_on_"+mesh_path.stem().string(), U_h_on );
    exporter_proj->save();

    // print coefficient only for reference element
    U_h_int.printMatlab( "U_h_int_" + mesh_path.stem().string() + ".m" );
    U_h_on.printMatlab( "U_h_on_" + mesh_path.stem().string() + ".m" );
    U_h_on_boundary.printMatlab( "U_h_on_boundary_" + mesh_path.stem().string() + ".m" );

    //L2 norm of error
    auto error = vf::project(_space=Xh, _range=elements(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on) );
    double L2error = error.l2Norm();
    std::cout << "L2 error (elements) = " << L2error << std::endl;

    auto error_boundary = vf::project(_space=Xh, _range=elements(oneelement_mesh), _expr=idv(U_h_int) - idv(U_h_on_boundary) );
    double L2error_boundary = error_boundary.l2Norm();
    std::cout << "L2 error (boundary) = " << L2error_boundary << std::endl;
    BOOST_CHECK_SMALL( L2error_boundary - L2error, 1e-13 );
}
/// This test uses a back door to the function that passes in the element to avoid the lookup of the element when the
///  StringFunction contains references to FieldFunctions
void TEST_norm_string_function_turbo_timings(TurboOption turboOpt)
{
  EXCEPTWATCH;
  //stk::diag::WriterThrowSafe _write_throw_safe(dw());
  //dw().setPrintMask(dw_option_mask.parse(vm["dw"].as<std::string>().c_str()));
  //dw().setPrintMask(LOG_NORM+LOG_ALWAYS);

  dw().m(LOG_NORM) << "TEST.norm.string_function " << stk::diag::dendl;

  /// create a meta data/bulk data empty pair
  PerceptMesh eMesh(3u);

  if (1)
  {
    // Need a symmetric mesh around the origin for some of the tests below to work correctly (i.e. have analytic solutions)
    const size_t nxyz = 4;
    const size_t num_x = nxyz;
    const size_t num_y = nxyz;
    const size_t num_z = nxyz;
    std::string config_mesh =
      Ioss::Utils::to_string(num_x) + "x" +
      Ioss::Utils::to_string(num_y) + "x" +
      Ioss::Utils::to_string(num_z) + "|bbox:-0.5,-0.5,-0.5,0.5,0.5,0.5";
	
    eMesh.new_mesh(GMeshSpec(config_mesh));

    eMesh.commit();
  }

  mesh::fem::FEMMetaData& metaData = *eMesh.get_fem_meta_data();
  mesh::BulkData& bulkData = *eMesh.get_bulk_data();

  /// the coordinates field is always created by the PerceptMesh read operation, here we just get the field
  mesh::FieldBase *coords_field = metaData.get_field<mesh::FieldBase>("coordinates");

  /// create a field function from the existing coordinates field
  FieldFunction ff_coords("ff_coords", coords_field, &bulkData,
                          Dimensions(3), Dimensions(3), FieldFunction::SIMPLE_SEARCH );

  /// the function to be integrated:  sqrt(Integral[x^2, dxdydz]) =?= sqrt(x^3/3 @ [-0.5, 0.5]) ==> sqrt(0.25/3)
  StringFunction sfx("x", Name("sfx"), Dimensions(3), Dimensions(1) );

  ff_coords.add_alias("mc");
  //StringFunction sfcm("sqrt(mc[0]*mc[0]+mc[1]*mc[1]+mc[2]*mc[2])", Name("sfcm"), Dimensions(3), Dimensions(1));
  StringFunction sfx_mc("mc[0]", Name("sfx_mc"), Dimensions(3), Dimensions(1) );

  /// the function to be integrated:  sqrt(Integral[x^2, dxdydz]) =?= sqrt(x^3/3 @ [-0.5, 0.5]) ==> sqrt(0.25/3)

  /// A place to hold the result.
  /// This is a "writable" function (we may want to make this explicit - StringFunctions are not writable; FieldFunctions are
  /// since we interpolate values to them from other functions).
  ConstantFunction sfx_res(0.0, "sfx_res");
  ConstantFunction sfx_res_turbo(0.0, "sfx_res_turbo");
  ConstantFunction sfx_res_slow(0.0, "sfx_res_slow");
  ConstantFunction sfx_res_fast(0.0, "sfx_res_fast");

#define COL_SEP "|"
#define EXPR_CELL_WIDTH (80)

#define TIME_IT2(expr_none,expr_turbo,msg,topt)                         \
  {                                                                     \
    double TURBO_NONE_time    = 0;                                      \
    double TURBO_ON_time = 0;                                           \
    TIME_IT(expr_none,TURBO_NONE_time);                                 \
    TIME_IT(expr_turbo,TURBO_ON_time);                                  \
    if (1) std::cout << msg << #topt << "for expression= " << QUOTE(expr_none) << " timings= " << std::endl; \
    if (1) std::cout << "TURBO_NONE_time= " << TURBO_NONE_time << " "   \
                     << ( turboOpt==TURBO_ELEMENT?"TURBO_ELEMENT_time":"TURBO_BUCKET_time") <<"= " << TURBO_ON_time \
                     << " ratio= " << TURBO_NONE_time/TURBO_ON_time << std::endl; \
  }

  int numIter = 1;
  for (int iter = 0; iter < numIter; iter++)
  {
    /// Create the operator that will do the work
    /// get the l2 norm
    Norm<2> l2Norm      (bulkData, &metaData.universal_part(), TURBO_NONE);
    Norm<2> l2Norm_turbo(bulkData, &metaData.universal_part(), turboOpt);

    //double TURBO_ELEMENT_time=0;
    TIME_IT2(l2Norm(sfx, sfx_res); , l2Norm_turbo(sfx, sfx_res_turbo);, "Should be the same turboOpt= ", turboOpt );
Exemple #10
0
/// This test uses a back door to the function that passes in the element to avoid the lookup of the element when the
///  StringFunction contains references to FieldFunctions
void TEST_norm_string_function_turbo_verify_correctness(TurboOption turboOpt)
{
  EXCEPTWATCH;
  //stk::diag::WriterThrowSafe _write_throw_safe(dw());
  //dw().setPrintMask(dw_option_mask.parse(vm["dw"].as<std::string>().c_str()));
  //dw().setPrintMask(LOG_NORM+LOG_ALWAYS);

  dw().m(LOG_NORM) << "TEST.norm.string_function " << stk::diag::dendl;

  LocalFixture     fix(4);
  mesh::fem::FEMMetaData&        metaData     = fix.metaData;
  mesh::BulkData&        bulkData     = fix.bulkData;
  PerceptMesh&        eMesh     = fix.eMesh;
  mesh::FieldBase*       coords_field = fix.coords_field;
  StringFunction   sfx          = fix.sfx;
  ConstantFunction sfx_res      = fix.sfx_res;

  /// create a field function from the existing coordinates field
  FieldFunction ff_coords("ff_coords", coords_field, &bulkData,
                          Dimensions(3), Dimensions(3), FieldFunction::SIMPLE_SEARCH );

  /// the function to be integrated:  sqrt(Integral[x^2, dxdydz]) =?= sqrt(x^3/3 @ [-0.5, 0.5]) ==> sqrt(0.25/3)
  //StringFunction sfx("x", Name("sfx"), Dimensions(3), Dimensions(1) );

  ff_coords.add_alias("mc");
  //StringFunction sfcm("sqrt(mc[0]*mc[0]+mc[1]*mc[1]+mc[2]*mc[2])", Name("sfcm"), Dimensions(3), Dimensions(1));
  StringFunction sfx_mc("mc[0]", Name("sfx_mc"), Dimensions(3), Dimensions(1) );
  StringFunction sfx_mc1("mc[0]", Name("sfx_mc1"), Dimensions(3), Dimensions(1) );

  if (1)
  {


    double x = -0.49+0.98*Math::random01();
    double y = -0.49+0.98*Math::random01();
    double z = -0.49+0.98*Math::random01();

    STKUNIT_EXPECT_DOUBLE_EQ_APPROX(eval(x,y,z,0.0, sfx), eval(x,y,z,0.0, sfx_mc));
    STKUNIT_EXPECT_DOUBLE_EQ_APPROX(eval(.034,0,0,0.0, sfx), eval(.034,0,0,0.0, sfx_mc));
  }

  /// A place to hold the result.
  /// This is a "writable" function (we may want to make this explicit - StringFunctions are not writable; FieldFunctions are
  /// since we interpolate values to them from other functions).
  ConstantFunction sfx_res_turbo(0.0, "sfx_res_turbo");
  ConstantFunction sfx_res_slow(0.0, "sfx_res_slow");
  ConstantFunction sfx_res_fast(0.0, "sfx_res_fast");
  ConstantFunction sfx_res_bucket(0.0, "sfx_res_bucket");

  // STATE m_element....

  /// Create the operator that will do the work
  /// get the l2 norm
  Norm<2> l2Norm(bulkData, &metaData.universal_part(), TURBO_NONE);
  l2Norm(sfx, sfx_res);

  Norm<2> l2Norm_turbo(bulkData, &metaData.universal_part(), turboOpt);
  Norm<2> l2Norm_turbo_bucket(bulkData, &metaData.universal_part(), TURBO_BUCKET);
  Norm<2> l2Norm_turbo1(bulkData, &metaData.universal_part(), turboOpt);
  l2Norm_turbo(sfx, sfx_res_turbo);

  l2Norm_turbo1(sfx_mc1, sfx_res_fast);
  l2Norm_turbo_bucket(sfx_mc1, sfx_res_bucket);

  l2Norm(sfx_mc, sfx_res_slow);
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(eval(.023,0,0,0.0, sfx), eval(.023,0,0,0.0, sfx_mc));

  double sfx_expect = std::sqrt(0.25/3.);
  std::cout << "sfx_expect= " << sfx_expect << std::endl;

  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res_bucket.getValue());

  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res.getValue());

  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res_turbo.getValue());
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res_slow.getValue());
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res_fast.getValue()); //!
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res.getValue());

  //Util::pause(true, "13a");
  //STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_res_turbo.getValue(), sfx_expect);
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX_TOL(sfx_expect, sfx_res_turbo.getValue(),  1.e-8);
  //Util::pause(true, "13");

  /// the function to be integrated:  (Integral[ abs(x), dxdydz]) =?= (2 * |x|^2/2 @ [0, 0.5]) ==> .25)
  Norm<1> l1Norm(bulkData, &metaData.universal_part(), TURBO_NONE);
  l1Norm(sfx, sfx_res);

  Norm<1> l1Norm_turbo(bulkData, &metaData.universal_part(), TURBO_NONE);
  l1Norm_turbo(sfx, sfx_res_turbo);
  l1Norm_turbo(sfx_mc, sfx_res_fast);
  l1Norm(sfx_mc, sfx_res_slow);

  sfx_expect = 0.25;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res_turbo.getValue());

  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res_slow.getValue());
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res_fast.getValue());

  //// ----- here
  /// the function to be integrated:  sqrt(Integral[(x*y*z)^2, dxdydz]) =?= (see unitTest1.py)
  StringFunction sfxyz("x*y*z", Name("sfxyz"), Dimensions(3), Dimensions(1) );
  l2Norm(sfxyz, sfx_res);
  l2Norm_turbo(sfxyz, sfx_res_turbo);
  sfx_expect = 0.0240562612162344;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res_turbo.getValue());


  /// the function to be integrated (but over a rotated domain):  sqrt(Integral[(x*y*z)^2, dxdydz]) =?= (see unitTest2.py)
  /// now rotate the mesh
  Math::Matrix rmz = Math::rotationMatrix(2, 30);
  Math::Matrix rm = rmz;
  eMesh.transform_mesh(rm);

  l2Norm(sfxyz, sfx_res);
  l2Norm_turbo(sfxyz, sfx_res_turbo);
  sfx_expect = 0.0178406008037016;
  // NOTE: we need extra quadrature accuracy to reproduce this result (cubDegree==4 in IntegratedOp almost gets it right)
  //   for now, we are satisfied with 3 digits
  //STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_res.getValue(), sfx_expect);
  if (std::fabs(sfx_res.getValue()-sfx_expect) > 0.01*sfx_expect)
  {
    STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());
    STKUNIT_EXPECT_TRUE(false);
  }
  if (std::fabs(sfx_res_turbo.getValue()-sfx_expect) > 0.01*sfx_expect)
  {
    STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res_turbo.getValue());
    STKUNIT_EXPECT_TRUE(false);
  }
}
Exemple #11
0
STKUNIT_UNIT_TEST(norm, string_function)
{
  EXCEPTWATCH;
  //stk::diag::WriterThrowSafe _write_throw_safe(dw());
  //dw().setPrintMask(dw_option_mask.parse(vm["dw"].as<std::string>().c_str()));
  //dw().setPrintMask(LOG_NORM+LOG_ALWAYS);

  dw().m(LOG_NORM) << "TEST.norm.string_function " << stk::diag::dendl;

  LocalFixture     fix(4);
  mesh::fem::FEMMetaData&        metaData     = fix.metaData;
  mesh::BulkData&        bulkData     = fix.bulkData;
  PerceptMesh&        eMesh     = fix.eMesh;
  //mesh::FieldBase*       coords_field = fix.coords_field;
  StringFunction   sfx          = fix.sfx;
  ConstantFunction sfx_res      = fix.sfx_res;

  /// Create the operator that will do the work
  /// get the l2 norm
  Norm<2> l2Norm(bulkData, &metaData.universal_part(), TURBO_NONE);
  l2Norm(sfx, sfx_res);

  double sfx_expect = std::sqrt(0.25/3.);
  Teuchos::ScalarTraits<double>::seedrandom(12345);
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX(sfx_expect, sfx_res.getValue());

  int niter=1;
  for (int iter=0; iter < niter; iter++)
  {
    STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, eval(Math::random01(), Math::random01(), Math::random01(), 0.0, sfx_res));
  }

  /// the function to be integrated:  (Integral[ abs(x), dxdydz]) =?= (2 * |x|^2/2 @ [0, 0.5]) ==> .25)
  Norm<1> l1Norm(bulkData, &metaData.universal_part(), TURBO_NONE);
  l1Norm(sfx, sfx_res);

  sfx_expect = 0.25;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());

  /// the function to be integrated:  (Max[ x^2+y^3+z^4, dxdydz]) =?= (@ [-0.5, 0.5]^3 ) ==> .5^2+.5^3+.5^4)
  StringFunction sfmax("x^2 + y^3 + z^4", Name("sfmax"), Dimensions(3), Dimensions(1) );
  Norm<-1> lInfNorm(bulkData, &metaData.universal_part(), TURBO_NONE);
  lInfNorm.setCubDegree(10);
  lInfNorm(sfmax, sfx_res);
  double sf1=eval(.5,.5,.5,0.0, sfmax);
  sfx_expect = 0.5*0.5 + 0.5*0.5*0.5 + 0.5*0.5*0.5*0.5;
  std::cout << "sfmax= " << sf1 << " sfx_expect= " << sfx_expect << " sfx_res= " << sfx_res.getValue() << std::endl;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());

  /// indirection
  StringFunction sfmax_1("sfmax", Name("sfmax_1"), Dimensions(3), Dimensions(1) );
  double sf1_1=eval(.5,.5,.5,0.0, sfmax_1);
  std::cout << "sfmax_1= " << sf1_1 << " sfx_expect= " << sfx_expect << std::endl;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sf1_1);

  /// the function to be integrated:  sqrt(Integral[(x*y*z)^2, dxdydz]) =?= (see unitTest1.py)
  StringFunction sfxyz("x*y*z", Name("sfxyz"), Dimensions(3), Dimensions(1) );
  l2Norm(sfxyz, sfx_res);
  sfx_expect = 0.0240562612162344;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());

  /// indirection
  std::cout << "tmp srk start..." << std::endl;
  StringFunction sfxyz_2("sfxyz", Name("sfxyz_2"), Dimensions(3), Dimensions(1) );
  l2Norm(sfxyz_2, sfx_res);
  sfx_expect = 0.0240562612162344;
  STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());

  /// the function to be integrated (but over a rotated domain):  sqrt(Integral[(x*y*z)^2, dxdydz]) =?= (see unitTest2.py)
  /// now rotate the mesh
  Math::Matrix rmz = Math::rotationMatrix(2, 30);
  Math::Matrix rm = rmz;
  eMesh.transform_mesh(rm);

  l2Norm(sfxyz, sfx_res);
  sfx_expect = 0.0178406008037016;
  // NOTE: we need extra quadrature accuracy to reproduce this result (cubDegree==4 in IntegratedOp almost gets it right)
  //   for now, we are satisfied with 2-3 digits
  //STKUNIT_EXPECT_DOUBLE_EQ(sfx_res.getValue(), sfx_expect);
  if (std::fabs(sfx_res.getValue()-sfx_expect) > 0.01*sfx_expect)
  {
    STKUNIT_EXPECT_DOUBLE_EQ_APPROX( sfx_expect, sfx_res.getValue());
    STKUNIT_EXPECT_TRUE(false);
  }
}
Exemple #12
0
int main(int argc, char** argv) 
{
	int dim_n = DIM_N;
	int dim_m = DIM_M;
	int dim_k = DIM_K;
	//      
	if (argc == 4)
	{
		dim_n = atoi(argv[1]);
		dim_m = atoi(argv[2]);
		dim_k = atoi(argv[3]);
	}
	int local_k;
	//
#ifdef MPI
	MPI_Init(&argc, &argv);
	int num_tasks;
	int my_rank;
	MPI_Comm_size(MPI_COMM_WORLD, &num_tasks);
	MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
	local_k = dim_k/num_tasks; 
#endif
	//
	double* restrict storage1 = (double*)malloc(dim_n*dim_m*dim_k*sizeof(double));
	double* restrict storage2 = (double*)malloc(dim_n*dim_m*dim_k*sizeof(double));

	printf("3x3 stencil: M=%d N=%d K=%d global.\n", dim_n, dim_m, dim_k);

	printf("array size = %f MB\n", (double) dim_n*dim_m*dim_k*sizeof(double)/1024/1024);

	double alloctime = -myseconds();
	init (storage1, dim_n, dim_m, dim_k);
	init (storage2, dim_n, dim_m, dim_k);
	alloctime += myseconds();
	printf("Allocation time = %f s.\n\n", alloctime);

	int n_iters = 0;
	int nrep    = NREP;
	int ii;

	double * st_read  = storage2;
	double * st_write = storage1;

	double phi;
	double norminf, norml2;
	double time = - myseconds();

	//
	do 
	{
		// swaping the solutions
		double *tmp = st_read;
		st_read     = st_write;
		st_write    = tmp;
		//
		++n_iters;
		//
		double ftime = -myseconds();
		//PAPI_START;
		unsigned long long c0 = cycles();
		//
		for (ii = 0; ii < nrep; ++ii)
		{
			laplacian(st_read, st_write, dim_m, dim_n, dim_k);
		}
		//
		unsigned long long c1 = cycles();
		//unsigned long long cycles = (c1 - c0)/((unsigned long long) (dim_m - 1)*(dim_n - 1));
		unsigned long long cycles = (c1 - c0)/nrep;
		//
		//PAPI_STOP;
		ftime += myseconds();
		ftime /= nrep;
		//print(st_write + dim_n*dim_m, dim_m, dim_n);
		//PAPI_PRINT;
		//
		norminf = maxNorm(st_write, st_read, dim_n*dim_m*dim_k);
		norml2   = l2Norm(st_write, st_read, dim_n*dim_m*dim_k);
		double flops = (dim_m - 2)*(dim_n - 2)*(dim_k - 2)*6.;
		//
		printf("iter = %d, %f s. %ld c., linf = %g l2 = %g, %d flops, %ld c, %f F/c, %f GF/s\n", n_iters, ftime, cycles, norminf, norml2, (long long int) flops, flops/cycles, (double) flops/ftime/1e9); 
	} while (norminf > EPSI);
	time += myseconds();
	//
	printf("\n# iter= %d time= %g residual= %g\n", n_iters, time, norml2); 
	//
	free(storage1);
	free(storage2);
	//
#ifdef MPI
	MPI_Finalize();
#endif
	return 0;
}
Exemple #13
0
void calHog(uint startR, uint startC)
/*该函数用于在像素点的梯度的幅度
和角度值所属于的Bin已知的情况下求hog特征向量*/
{
	assert(BlockR % CellR == 0 && BlockC % CellC == 0 &&
		(winC - BlockC) % BlockStrideC == 0 &&
		(winR - BlockR) % BlockStrideR == 0);
	assert(NumOfHogFeatureTest == NumOfHogFeature);

	uchar br, bc, cc, cr; // br,bc 分别表示行和列上第几个Block; cc、cr则是Cell的
	uchar bin = 0;  uint i = 0;
	//uchar pixelCount = 0;
	uint cellCountBin = 0; //cellCount*Bin
	uint blockCount = 0;
	//uint bccb = 0; uchar y, x;	
	int byOfs, bxOfs, xOfs, yOfs, k;

	int pos1R, pos1C;
	int pos2R, pos2C;
	int pos3R, pos3C;
	int pos4R, pos4C;

	/*获取hog特征*/
	for (br = 0; br < NumberOfBlockR; br++){ //y方向上第br个block
		for (bc = 0; bc < NumberOfBlockC; bc++) //x方向上第bc个block
		{
			cellCountBin = 0;
			byOfs = br*BlockStrideR + startR;
			bxOfs = bc*BlockStrideC + startC;
			for (cr = 1; cr <= CellNumR; cr++){ //第cr个cell
				for (cc = 1; cc <= CellNumC; cc++) //第cc个cell
				{
					yOfs = byOfs + (cr - 1)*CellR;
					xOfs = bxOfs + (cc - 1)*CellC;

					pos1R = yOfs; pos1C = xOfs;
					pos2R = yOfs; pos2C = xOfs + CellC;
					pos3R = yOfs + CellR; pos3C = xOfs;
					pos4R = yOfs + CellR; pos4C = xOfs + CellC;

					for (k = 0; k < Bin; k++){
						CellHog[k] = intHist[pos1R][pos1C][k] + intHist[pos4R][pos4C][k] -
							intHist[pos2R][pos2C][k] - intHist[pos3R][pos3C][k];
						assert(CellHog[k]>=0);
					}
			
					// merge cellHog to blockHog
					memcpy(BlockHog + cellCountBin, CellHog, sizeof(CellHog));
					cellCountBin += Bin;
				}
			}
			/*for (int i = 0; i < NumOfBlockFeature; i++){
				cout << BlockHog[i] << " " << endl;
			}
			cout << endl;*/

			/*归一化一个block内的hog特征*/
			l2Norm(BlockHog, NumOfBlockFeature);
			/*获取所有的Hog特征*/
			memcpy(HogFeature + blockCount, BlockHog, sizeof(BlockHog));
			blockCount += NumOfBlockFeature;
		}
	}
}
Exemple #14
0
void
oldTWOnewDelta(TWOdevice *pDevice, BOOLEAN tranAnalysis, TWOtranInfo *info)
{
  int index;
  double newNorm, fib, lambda, fibn, fibp;
  BOOLEAN acceptable = FALSE;
  lambda = 1.0;
  fibn = 1.0;
  fibp = 1.0;

  /*
   * copy the contents of dcSolution into copiedSolution and modify
   * dcSolution by adding the deltaSolution
   */

  for (index = 1; index <= pDevice->numEqns; ++index) {
    pDevice->copiedSolution[index] = pDevice->dcSolution[index];
    pDevice->dcSolution[index] += pDevice->dcDeltaSolution[index];
  }

  /* compute L2 norm of the deltaX vector */
  pDevice->rhsNorm = l2Norm(pDevice->dcDeltaSolution, pDevice->numEqns);

  if (pDevice->poissonOnly) {
    TWOQrhsLoad(pDevice);
  } else if (!OneCarrier) {
    TWO_rhsLoad(pDevice, tranAnalysis, info);
  } else if (OneCarrier == N_TYPE) {
    TWONrhsLoad(pDevice, tranAnalysis, info);
  } else if (OneCarrier == P_TYPE) {
    TWOPrhsLoad(pDevice, tranAnalysis, info);
  }
  newNorm = TWOnuNorm(pDevice);
  if (newNorm <= pDevice->rhsNorm) {
    acceptable = TRUE;
  } else {
    /* chop the step size so that deltax is acceptable */
    for (; !acceptable;) {
      fib = fibp;
      fibp = fibn;
      fibn += fib;
      lambda *= (fibp / fibn);

      for (index = 1; index <= pDevice->numEqns; index++) {
	pDevice->dcSolution[index] = pDevice->copiedSolution[index]
	    + lambda * pDevice->dcDeltaSolution[index];
      }
      if (pDevice->poissonOnly) {
	TWOQrhsLoad(pDevice);
      } else if (!OneCarrier) {
	TWO_rhsLoad(pDevice, tranAnalysis, info);
      } else if (OneCarrier == N_TYPE) {
	TWONrhsLoad(pDevice, tranAnalysis, info);
      } else if (OneCarrier == P_TYPE) {
	TWOPrhsLoad(pDevice, tranAnalysis, info);
      }
      newNorm = TWOnuNorm(pDevice);
      if (newNorm <= pDevice->rhsNorm) {
	acceptable = TRUE;
      }
    }
  }
  /* restore the previous dcSolution and the new deltaSolution */
  pDevice->rhsNorm = newNorm;
  for (index = 1; index <= pDevice->numEqns; index++) {
    pDevice->dcSolution[index] = pDevice->copiedSolution[index];
    pDevice->dcDeltaSolution[index] *= lambda;
  }
}