Skip to content

Commit fab3550

Browse files
authored
Merge pull request #182 from SNLComputation/gradient_of_vector
Added GradientOfVectorPointEvaluation for several bases
2 parents 5d38aa3 + e047a7c commit fab3550

File tree

3 files changed

+147
-1
lines changed

3 files changed

+147
-1
lines changed

examples/GMLS_Tutorial.hpp

+40
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,46 @@ double trueDivergence(double x, double y, double z, int order, int dimension) {
142142
return ans;
143143
}
144144

145+
KOKKOS_INLINE_FUNCTION
146+
void trueHessian(double* ans, double x, double y, double z, int order, int dimension) {
147+
for (int i=0; i<order+1; i++) {
148+
for (int j=0; j<order+1; j++) {
149+
for (int k=0; k<order+1; k++) {
150+
if (i+j+k <= order) {
151+
// XX
152+
ans[0] += device_max(0,i)*device_max(0,i-1)*
153+
std::pow(x,device_max(0,i-2))*std::pow(y,j)*std::pow(z,k);
154+
if (dimension>1) {
155+
// XY
156+
ans[1] += device_max(0,i)*device_max(0,j)*
157+
std::pow(x,device_max(0,i-1))*std::pow(y,device_max(0,j-1))*std::pow(z,k);
158+
// YX = XY
159+
ans[1*dimension+0] = ans[1];
160+
// YY
161+
ans[1*dimension+1] += device_max(0,j)*device_max(0,j-1)*
162+
std::pow(x,i)*std::pow(y,device_max(0,j-2))*std::pow(z,k);
163+
}
164+
if (dimension>2) {
165+
// XZ
166+
ans[2] += device_max(0,i)*device_max(0,k)*
167+
std::pow(x,device_max(0,i-1))*std::pow(y,j)*std::pow(z,device_max(0,k-1));
168+
// YZ
169+
ans[1*dimension+2] += device_max(0,j)*device_max(0,k)*
170+
std::pow(x,i)*std::pow(y,device_max(0,j-1))*std::pow(z,device_max(0,k-1));
171+
// ZX = XZ
172+
ans[2*dimension+0] = ans[2];
173+
// ZY = YZ
174+
ans[2*dimension+1] = ans[1*dimension+2];
175+
// ZZ
176+
ans[2*dimension+2] += device_max(0,k)*device_max(0,k-1)*
177+
std::pow(x,i)*std::pow(y,j)*std::pow(z,device_max(0,k-2));
178+
}
179+
}
180+
}
181+
}
182+
}
183+
}
184+
145185
KOKKOS_INLINE_FUNCTION
146186
double divergenceTestSamples(double x, double y, double z, int component, int dimension) {
147187
// solution can be captured exactly by at least 2rd order

examples/GMLS_Vector.cpp

+60-1
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,12 @@ bool all_passed = true;
347347
my_GMLS.setProblemData(neighbor_lists_device, source_coords_device, target_coords_device, epsilon_device);
348348

349349
// create a vector of target operations
350-
std::vector<TargetOperation> lro(4);
350+
std::vector<TargetOperation> lro(5);
351351
lro[0] = ScalarPointEvaluation;
352352
lro[1] = DivergenceOfVectorPointEvaluation;
353353
lro[2] = CurlOfVectorPointEvaluation;
354354
lro[3] = VectorPointEvaluation;
355+
lro[4] = GradientOfVectorPointEvaluation;
355356

356357
// and then pass them to the GMLS class
357358
my_GMLS.addTargets(lro);
@@ -398,6 +399,9 @@ bool all_passed = true;
398399

399400
auto output_gradient = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
400401
(gradient_sampling_data_device, VectorPointEvaluation);
402+
403+
auto output_hessian = gmls_evaluator.applyAlphasToDataAllComponentsAllTargetSites<double**, Kokkos::HostSpace>
404+
(gradient_sampling_data_device, GradientOfVectorPointEvaluation);
401405

402406
// retrieves polynomial coefficients instead of remapped field
403407
auto scalar_coefficients = gmls_evaluator.applyFullPolynomialCoefficientsBasisToDataAllComponents<double**, Kokkos::HostSpace>
@@ -439,6 +443,16 @@ bool all_passed = true;
439443
double GMLS_CurlY = (dimension>1) ? output_curl(i,1) : 0;
440444
double GMLS_CurlZ = (dimension>2) ? output_curl(i,2) : 0;
441445

446+
// load hessian
447+
double GMLS_GradXX = output_hessian(i,0*dimension+0);
448+
double GMLS_GradXY = (dimension>1) ? output_hessian(i,0*dimension+1) : 0;
449+
double GMLS_GradXZ = (dimension>2) ? output_hessian(i,0*dimension+2) : 0;
450+
double GMLS_GradYX = (dimension>1) ? output_hessian(i,1*dimension+0) : 0;
451+
double GMLS_GradYY = (dimension>1) ? output_hessian(i,1*dimension+1) : 0;
452+
double GMLS_GradYZ = (dimension>2) ? output_hessian(i,1*dimension+2) : 0;
453+
double GMLS_GradZX = (dimension>2) ? output_hessian(i,2*dimension+0) : 0;
454+
double GMLS_GradZY = (dimension>2) ? output_hessian(i,2*dimension+1) : 0;
455+
double GMLS_GradZZ = (dimension>2) ? output_hessian(i,2*dimension+2) : 0;
442456

443457
// target site i's coordinate
444458
double xval = target_coords(i,0);
@@ -453,6 +467,9 @@ bool all_passed = true;
453467

454468
double actual_Divergence;
455469
actual_Divergence = trueLaplacian(xval, yval, zval, order, dimension);
470+
471+
double actual_Hessian[9] = {0,0,0,0,0,0,0,0,0}; // initialized for 3, but only filled up to dimension
472+
trueHessian(actual_Hessian, xval, yval, zval, order, dimension);
456473

457474
double actual_Curl[3] = {0,0,0}; // initialized for 3, but only filled up to dimension
458475
// (and not at all for dimimension = 1)
@@ -493,6 +510,48 @@ bool all_passed = true;
493510
all_passed = false;
494511
std::cout << i << " Failed Divergence by: " << std::abs(actual_Divergence - GMLS_Divergence) << std::endl;
495512
}
513+
514+
// check matrix (which is the hessian)
515+
if(std::abs(actual_Hessian[0] - GMLS_GradXX) > failure_tolerance) {
516+
all_passed = false;
517+
std::cout << i << " Failed GradXX by: " << std::abs(actual_Hessian[0] - GMLS_GradXX) << std::endl;
518+
if (dimension>1) {
519+
if(std::abs(actual_Hessian[1] - GMLS_GradXY) > failure_tolerance) {
520+
all_passed = false;
521+
std::cout << i << " Failed GradXY by: " << std::abs(actual_Hessian[1] - GMLS_GradXY) << std::endl;
522+
}
523+
if(std::abs(actual_Hessian[1*dimension+1] - GMLS_GradYY) > failure_tolerance) {
524+
all_passed = false;
525+
std::cout << i << " Failed GradYY by: " << std::abs(actual_Hessian[1*dimension+1] - GMLS_GradYY) << std::endl;
526+
}
527+
if(std::abs(actual_Hessian[1*dimension+0] - GMLS_GradYX) > failure_tolerance) {
528+
all_passed = false;
529+
std::cout << i << " Failed GradYX by: " << std::abs(actual_Hessian[1*dimension+0] - GMLS_GradYX) << std::endl;
530+
}
531+
}
532+
if (dimension>2) {
533+
if(std::abs(actual_Hessian[2] - GMLS_GradXZ) > failure_tolerance) {
534+
all_passed = false;
535+
std::cout << i << " Failed GradXZ by: " << std::abs(actual_Hessian[2] - GMLS_GradXZ) << std::endl;
536+
}
537+
if(std::abs(actual_Hessian[1*dimension+2] - GMLS_GradYZ) > failure_tolerance) {
538+
all_passed = false;
539+
std::cout << i << " Failed GradYZ by: " << std::abs(actual_Hessian[1*dimension+2] - GMLS_GradYZ) << std::endl;
540+
}
541+
if(std::abs(actual_Hessian[2*dimension+0] - GMLS_GradZX) > failure_tolerance) {
542+
all_passed = false;
543+
std::cout << i << " Failed GradZX by: " << std::abs(actual_Hessian[2*dimension+0] - GMLS_GradZX) << std::endl;
544+
}
545+
if(std::abs(actual_Hessian[2*dimension+1] - GMLS_GradZY) > failure_tolerance) {
546+
all_passed = false;
547+
std::cout << i << " Failed GradZY by: " << std::abs(actual_Hessian[2*dimension+1] - GMLS_GradZY) << std::endl;
548+
}
549+
if(std::abs(actual_Hessian[2*dimension+2] - GMLS_GradZZ) > failure_tolerance) {
550+
all_passed = false;
551+
std::cout << i << " Failed GradZZ by: " << std::abs(actual_Hessian[2*dimension+2] - GMLS_GradZZ) << std::endl;
552+
}
553+
}
554+
}
496555

497556
// check curl
498557
if (order > 2) { // reconstructed solution not in basis unless order greater than 2 used

src/Compadre_GMLS_Targets.hpp

+47
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,38 @@ void GMLS::computeTargetFunctionals(const member_type& teamMember, scratch_vecto
289289
}
290290
});
291291
additional_evaluation_sites_handled = true; // additional non-target site evaluations handled
292+
} else if (_operations(i) == TargetOperation::GradientOfScalarPointEvaluation) {
293+
Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
294+
for (int e=0; e<num_evaluation_sites; ++e) {
295+
int output_components = _basis_multiplier;
296+
for (int m2=0; m2<output_components; ++m2) { // output components 2
297+
int offset = getTargetOffsetIndexDevice(i, 0 /*in*/, m2 /*out*/, e);
298+
this->calcGradientPij(teamMember, t1.data(), target_index, -1 /* target is neighbor */, 1 /*alpha*/, m2 /*partial_direction*/, _dimensions, _poly_order, false /*specific order only*/, NULL /*&V*/, ReconstructionSpace::ScalarTaylorPolynomial, PointSample, e);
299+
for (int j=0; j<target_NP; ++j) {
300+
P_target_row(offset, j) = t1(j);
301+
}
302+
}
303+
}
304+
});
305+
additional_evaluation_sites_handled = true; // additional non-target site evaluations handled
306+
} else if (_operations(i) == TargetOperation::GradientOfVectorPointEvaluation) {
307+
Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
308+
for (int e=0; e<num_evaluation_sites; ++e) {
309+
for (int m0=0; m0<_sampling_multiplier; ++m0) { // input components
310+
int output_components = _basis_multiplier;
311+
for (int m1=0; m1<output_components; ++m1) { // output components 1
312+
for (int m2=0; m2<output_components; ++m2) { // output components 2
313+
int offset = getTargetOffsetIndexDevice(i, m0 /*in*/, m1*output_components+m2 /*out*/, e);
314+
this->calcGradientPij(teamMember, t1.data(), target_index, -1 /* target is neighbor */, 1 /*alpha*/, m2 /*partial_direction*/, _dimensions, _poly_order, false /*specific order only*/, NULL /*&V*/, ReconstructionSpace::ScalarTaylorPolynomial, PointSample, e);
315+
for (int j=0; j<target_NP; ++j) {
316+
P_target_row(offset, m1*target_NP + j) = t1(j);
317+
}
318+
}
319+
}
320+
}
321+
}
322+
});
323+
additional_evaluation_sites_handled = true; // additional non-target site evaluations handled
292324
} else if (_operations(i) == TargetOperation::DivergenceOfVectorPointEvaluation) {
293325
if (_polynomial_sampling_functional == StaggeredEdgeIntegralSample) {
294326
Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
@@ -478,6 +510,21 @@ void GMLS::computeTargetFunctionals(const member_type& teamMember, scratch_vecto
478510
}
479511
});
480512
additional_evaluation_sites_handled = true; // additional non-target site evaluations handled
513+
} else if (_operations(i) == TargetOperation::GradientOfVectorPointEvaluation) {
514+
Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {
515+
for (int j=0; j<num_evaluation_sites; ++j) {
516+
for (int m0=0; m0<_dimensions; ++m0) { // input components
517+
for (int m1=0; m1<_dimensions; ++m1) { // output components 1
518+
for (int m2=0; m2<_dimensions; ++m2) { // output componets 2
519+
int offset = getTargetOffsetIndexDevice(i, m0 /*in*/, m1*_dimensions+m2 /*out*/, j);
520+
auto row = Kokkos::subview(P_target_row, offset, Kokkos::ALL());
521+
this->calcGradientPij(teamMember, row.data(), target_index, -1 /* target is neighbor */, 1 /*alpha*/, m2 /*partial_direction*/, _dimensions, _poly_order, false /*specific order only*/, NULL /*&V*/, ReconstructionSpace::ScalarTaylorPolynomial, PointSample, j);
522+
}
523+
}
524+
}
525+
}
526+
});
527+
additional_evaluation_sites_handled = true; // additional non-target site evaluations handled
481528
} else if (_operations(i) == TargetOperation::PartialXOfScalarPointEvaluation) {
482529
// copied from ScalarTaylorPolynomial
483530
Kokkos::single(Kokkos::PerTeam(teamMember), [&] () {

0 commit comments

Comments
 (0)