void TrilinearElementTypeSuite_TestShape( TrilinearElementTypeSuiteData* data ) { FeMesh* mesh = NULL; int nEls, nVerts, nDims; const int *verts; double* vert = NULL; double lCrd[3] = { 0.0, 0.0, 0.0 }; double basis[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; IArray* inc; int e_i, v_i, v_j; mesh = buildMesh(); pcu_check_true( mesh ); Stg_Component_Initialise( mesh, data, True ); nDims = Mesh_GetDimSize( mesh ); nEls = Mesh_GetDomainSize( mesh, nDims ); inc = IArray_New(); for( e_i = 0; e_i < nEls; e_i++ ) { Mesh_GetIncidence( mesh, nDims, e_i, 0, inc ); nVerts = IArray_GetSize( inc ); verts = IArray_GetPtr( inc ); for( v_i = 0; v_i < nVerts; v_i++ ) { vert = Mesh_GetVertex( mesh, verts[v_i] ); FeMesh_CoordGlobalToLocal( mesh, e_i, vert, lCrd ); FeMesh_EvalBasis( mesh, e_i, lCrd, basis ); for( v_j = 0; v_j < nVerts; v_j++ ) { if( (v_i == v_j && !Num_Approx( basis[v_j], 1.0 )) || (v_i != v_j && !Num_Approx( basis[v_j], 0.0 )) ) { break; } } if( v_j < nVerts ) break; } if( v_i < nVerts ) break; } pcu_check_true( e_i == nEls ); Stg_Class_Delete( inc ); _Stg_Component_Delete( mesh ); }
Fn::GradFeVariableFn::func Fn::GradFeVariableFn::getFunction( IOsptr sample_input ) { // setup output FeVariable* fevar = (FeVariable*)_fevariable; int numComponents = fevar->fieldComponentCount; FunctionIO::IOType iotype; std::shared_ptr<IO_double> _output; if (fevar->dim == 1) { iotype = FunctionIO::Vector; } else iotype = FunctionIO::Tensor; _output = std::make_shared<IO_double>(numComponents*fevar->dim, iotype); // if input is FEMCoordinate, eject appropriate lambda std::shared_ptr<const FEMCoordinate> femCoord = std::dynamic_pointer_cast<const FEMCoordinate>(sample_input); if ( femCoord ){ if( femCoord->mesh() == (void*) (fevar->feMesh->parentMesh ) ) return [_output,fevar](IOsptr input)->IOsptr { std::shared_ptr<const FEMCoordinate> femCoord = debug_dynamic_cast<const FEMCoordinate>(input); FeVariable_InterpolateDerivativesToElLocalCoord( fevar, femCoord->index(), femCoord->localCoord()->data(), _output->data() ); return debug_dynamic_cast<const FunctionIO>(_output); }; }; // if input is MeshCoordinate, eject appropriate lambda std::shared_ptr<const MeshCoordinate> meshCoord = std::dynamic_pointer_cast<const MeshCoordinate>(sample_input); if ( meshCoord ){ if( meshCoord->object() == (void*) (fevar->feMesh) ) // in this case, we need the identical mesh { std::shared_ptr<IArrayClass> inc = std::make_shared<IArrayClass>(); return [_output,fevar,inc](IOsptr input)->IOsptr { std::shared_ptr<const MeshCoordinate> meshCoord = debug_dynamic_cast<const MeshCoordinate>(input); unsigned index = meshCoord->index(); // from OperatorFeVariable.c /* Find the elements around the node and point to them via the nbrElList. */ FeMesh_GetNodeElements( (void*)fevar->feMesh, index, (IArray*)inc->inc ); unsigned nbrElCount = IArray_GetSize( inc->inc ); int* nbrElList = IArray_GetPtr( inc->inc ); Coord elLocalCoord; /* Use last element in list, get local coords then interpolate value. */ FeMesh_CoordGlobalToLocal( fevar->feMesh, nbrElList[nbrElCount-1], Mesh_GetVertex( fevar->feMesh, index ), elLocalCoord ); /* Get value at node for this element. */ FeVariable_InterpolateDerivativesToElLocalCoord( fevar, nbrElList[nbrElCount-1], elLocalCoord, _output->data() ); return debug_dynamic_cast<const FunctionIO>(_output); }; } } // if neither of the above worked, try plain old global coord std::shared_ptr<const IO_double> iodouble = std::dynamic_pointer_cast<const IO_double>(sample_input); if ( iodouble ){ return [_output,fevar](IOsptr input)->IOsptr { std::shared_ptr<const IO_double> iodouble = debug_dynamic_cast<const IO_double>(input); InterpolationResult retval = FeVariable_InterpolateDerivativesAt( (void*)fevar, (double*)iodouble->data(), (double*) _output->data() ); if (! ( (retval == LOCAL) || (retval == SHADOW) ) ){ std::stringstream streamguy; streamguy << "FeVariable derivative interpolation at location (" << iodouble->at(0); for (unsigned ii=1; ii<iodouble->size(); ii++) streamguy << ", "<< iodouble->at(ii); streamguy << ") does not appear to be valid.\nLocation is probably outside local domain."; throw std::runtime_error(streamguy.str()); } return debug_dynamic_cast<const FunctionIO>(_output); }; } // if we get here, something aint right throw std::invalid_argument("'GradFeVariableFn' does not appear to be compatible with provided input type."); }