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); } }
/// 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); } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *v, *ans, s1, s2; double *ind; double *x; double *u, *tmpV, *tmpU, *tmpW; double up, mid, low, h_s1, lambda0, lambda; int n, grpNum; int i, j, k; if(nlhs != 1) mexErrMsgTxt("Error: Number of output parameter does not match."); if(nrhs !=4) mexErrMsgTxt("Error: Number of input parameter does not match."); /* * Input Parameter handle */ v = mxGetPr(prhs[0]); s1 = mxGetScalar(prhs[1]); s2 = mxGetScalar(prhs[2]); ind = mxGetPr(prhs[3]); n = (int)mxGetNumberOfElements(prhs[0]); grpNum = (int)mxGetNumberOfElements(prhs[3]) - 1; /* * Output Parameter handle */ plhs[0] = mxCreateDoubleMatrix(n, 1, mxREAL); ans = mxGetPr(plhs[0]); /* Temporary variables. */ lambda = lambda0 = .0; x = (double *)malloc(n * sizeof(double)); tmpV = (double *)malloc(n * sizeof(double)); tmpU = (double *)malloc(grpNum * sizeof(double)); tmpW = (double *)malloc(grpNum * sizeof(double)); if(l1Norm(v, n) <= s1 + 1e-12 && grpNorm(v, ind, grpNum) <= s2 + 1e-12) { for(i = 0; i < n; i++) ans[i] = v[i]; free(x); free(tmpV); free(tmpU); free(tmpW); return; } lambda0 = .0; eplb(x, &lambda, &k, v, n, s1, lambda0); if(grpNorm(x, ind, grpNum) < s2 - 1e-12) { for(i = 0; i < n; i++) ans[i] = x[i]; free(x); free(tmpV); free(tmpU); free(tmpW); return; } epglb(x, v, n, s2, ind, grpNum, tmpW, tmpU); if(l1Norm(x, n) < s1 - 1e-12) { for(i = 0; i < n; i++) ans[i] = x[i]; free(x); free(tmpV); free(tmpU); free(tmpW); return; } up = 1e15, low = 1e-12; while(up - low > 1e-7) { if(low > 1e6 && up - low < 1e-5) break; mid = (up + low) / 2; soft_thresholding(tmpV, v, n, mid); if(grpNorm(tmpV, ind, grpNum) < s2 - 1e-15) up = mid; else{ epglb(x, tmpV, n, s2, ind, grpNum, tmpW, tmpU); h_s1 = l1Norm(x, n); if(h_s1 < s1 + 1e-15) up = mid; else low = mid; } } soft_thresholding(tmpV, v, n, up); epglb(x, tmpV, n, s2, ind, grpNum, tmpW, tmpU); for(i = 0; i < n; i++) ans[i] = x[i]; free(x); free(tmpV); free(tmpU); free(tmpW); }