/** fe_engine : * computes and assembles mass matrix, rhs vectors * initial conditions handled in atc_transfer */ /** field structure: a field is a dense matrix of numPoints X number of DOF in the field a gradient is a std::vector of fields of length numSpatialDimensions a set of fields is a map of fieldName->field of length numFields a set of gradients is a map of fieldName->gradient of length numFields Note: shape functions follow similar conventions with a shape function being a field of numPoints X numNodes and a shape function gradient being a std::vector of shape functions of length numSpatialDimensions, although this is modified in calls when numPoints = 1 Note: the convention between shape function format and field format allows for shape functions to matmat nodal fields, creating matrices of numPoints X numElementsInField for evaluating data at atomic/quadarture points */ /** current internal limitations: * 3 spatial dimensions * 8 node bricks * structured mesh * no stiffness matrix (i.e. no implicit integration or special treatment of linear problems) * lumped mass */ /** terminology: density rate = flux = Grad.FLUX(f,D_x f) + SOURCE(f,D_x f) + PRESCRIBED_SOURCE(x,t) + EXTRINSIC_SOURCE(f,D_x f,f_e,D_x f_e) */ #ifndef FE_ENGINE_H #define FE_ENGINE_H // Other headers #include #include // ATC_Transfer headers #include "Array.h" #include "Array2D.h" #include "FE_Mesh.h" #include "PhysicsModel.h" #include "OutputManager.h" using namespace std; namespace ATC { // Forward declarations class ATC_Transfer; class FE_Element; class XT_Function; class FE_Engine{ public: /** constructor/s */ FE_Engine(ATC_Transfer * atcTransfer); /** destructor */ ~FE_Engine(); /** initialize */ void initialize(); /** parser/modifier */ bool modify(int narg, char **arg); /** finish up */ void finish(); //---------------------------------------------------------------- /** \name output */ //---------------------------------------------------------------- /*@{*/ /** these assume the caller is handling the parallel collection */ void initialize_output(int rank, string outputPrefix, OutputType otype = ENSIGHT); /** write geometry */ void write_geometry(void); /** write data: data is arrayed over _unique_ nodes & then mapped by the engine */ void write_data(double time, FIELDS &soln, OUTPUT_LIST *data=NULL); void write_data(double time, OUTPUT_LIST *data); void write_restart_file(string fileName, OUTPUT_LIST *data) {outputManager_.write_restart_file(fileName,data);}; void read_restart_file(string fileName, OUTPUT_LIST *data) {outputManager_.read_restart_file(fileName,data);}; void delete_elements(const set & elementList); void add_global(string name, double value) {outputManager_.add_global(name,value);} void reset_globals() {outputManager_.reset_globals();} /** pass through to access output manager */ OutputManager* output_manager() {return &outputManager_;} /*@}*/ //---------------------------------------------------------------- /** \name assembled matrices and vectors */ //---------------------------------------------------------------- /*@{*/ /** compute a dimensionless stiffness matrix */ void compute_stiffness_matrix(SPAR_MAT &matrix) const; /** compute a dimensionless mass matrix */ void compute_mass_matrix(SPAR_MAT &mass_matrix) const; /** computes a dimensionless mass matrix for the given-quadrature */ void compute_mass_matrix(const DIAG_MAT &weights, const SPAR_MAT &N, SPAR_MAT &mass_matrix) const; /** compute a single dimensionless mass matrix */ void compute_lumped_mass_matrix(DIAG_MAT &lumped_mass_matrix) const; /** compute lumped mass matrix = diag (\int \rho N_I dV) */ void compute_lumped_mass_matrix(const Array &mask, const FIELDS &fields, const PhysicsModel * physicsModel, const Array & elementMaterials, map &mass_matrix, const Array *element_mask=NULL) const; /** compute dimensional lumped mass matrix using given quadrature */ void compute_lumped_mass_matrix(const Array &mask, const FIELDS &fields, const PhysicsModel * physicsModel, const Array > & pointMaterialGroups, const DIAG_MAT &weights, const SPAR_MAT &N, map &mass_matrix) const; /** compute an approximation to a finite difference gradient from mesh */ void compute_gradient_matrix(GRAD_SHPFCN &grad_matrix) const; /** compute energy */ void compute_energy(const Array &mask, const FIELDS &fields, const PhysicsModel * physicsModel, const Array & elementMaterials, FIELDS &energy, const Array *element_mask=NULL) const; /** compute residual or RHS of the dynamic weak eqn */ void compute_rhs_vector(const Array2D &rhs_mask, const FIELDS &fields, const PhysicsModel * physicsModel, const Array & elementMaterials, FIELDS &rhs, const Array *element_mask=NULL) const; /** compute RHS for given quadrature */ void compute_rhs_vector(const Array2D &rhs_mask, const FIELDS &fields, const PhysicsModel * physicsModel, const Array > & pointMaterialGroups, const DIAG_MAT &weights, const SPAR_MAT &N, const GRAD_SHPFCN &dN, FIELDS &rhs) const; /** compute flux in domain i.e. N^T B_integrand */ void compute_flux(const Array2D & rhs_mask, const FIELDS &fields, const PhysicsModel * physicsModel, const Array & elementMaterials, GRAD_FIELDS &flux, const Array *element_mask=NULL) const; /** compute the flux on the MD/FE boundary */ void compute_boundary_flux( const Array2D & rhs_mask, const FIELDS & fields, const PhysicsModel * physicsModel, const Array & elementMaterials, const set & faceSet, FIELDS & rhs) const; /** compute the flux on using an L2 interpolation of the flux */ void compute_boundary_flux( const Array2D & rhs_mask, const FIELDS & fields, const PhysicsModel * physicsModel, const Array & elementMaterials, const Array > & pointMaterialGroups, const DIAG_MAT & weights, const SPAR_MAT & N, const GRAD_SHPFCN & dN, const DIAG_MAT & flux_mask, FIELDS & rhs ) const; /** compute prescribed flux given an array of functions of x & t */ void add_fluxes(const Array &fieldMask, const double time, const SURFACE_SOURCE & sourceFunctions, FIELDS &nodalSources) const; /** compute nodal vector of volume based sources */ void add_sources(const Array &fieldMask, const double time, const VOLUME_SOURCE &sourceFunctions, FIELDS &nodalSources) const; /** compute surface flux of a nodal field */ void field_surface_flux(const DENS_MAT & field, const set &faceSet, DENS_MAT & values, const bool contour = false, const int axis = 2) const; /*@}*/ //---------------------------------------------------------------- /** \name shape functions */ //---------------------------------------------------------------- /*@{*/ /** evaluate shape function at a list of points in R^3 */ void evaluate_shape_functions(const MATRIX &coords, SPAR_MAT &N, Array & pointToEltMap) const; /** evaluate shape function & derivatives at a list of points in R^3 */ void evaluate_shape_functions( const MATRIX &coords, SPAR_MAT &N, GRAD_SHPFCN &dN, Array & pointToEltMap) const; /** evaluate all shape function & derivatives at a specific R^3 location */ void evaluate_shape_functions(const VECTOR & x, Array& node_index, DENS_VEC& shp, DENS_MAT& dshp, int & eltID) const; /** pass through */ void shape_functions(const VECTOR &x, DENS_VEC& shp, int & eltID, Array& node_list) const { feMesh_->shape_functions(x,shp,eltID,node_list); } void shape_functions(const VECTOR &x, DENS_VEC& shp, int & eltID, Array& node_list, const Array& periodicity) const { feMesh_->shape_functions(x,shp,eltID,node_list, periodicity); } /*@}*/ //---------------------------------------------------------------- /** \name accessors */ //---------------------------------------------------------------- /*@{*/ /** even though these are pass-throughs there is a necessary translation */ /** return number of unique nodes */ int get_nNodes() const { return feMesh_->get_nNodesUnique(); }; /** return number of total nodes */ int get_nNodesTotal() const { return feMesh_->get_nNodes(); }; /** return number of elements */ int get_nElements() const { return feMesh_->get_nElements(); }; /** return element connectivity */ void element_connectivity(const int eltID, Array & nodes) const { feMesh_->element_connectivity_unique(eltID, nodes); } /** return face connectivity */ void face_connectivity(const PAIR &faceID, Array &nodes) const { feMesh_->face_connectivity_unique(faceID, nodes); } /** in lieu of pass-throughs const accessors ... */ // return const ptr to mesh const FE_Mesh* get_feMesh() const { return feMesh_;} // return number of spatial dimensions int get_nsd() const { return feMesh_->get_nSpatialDimensions(); } // return if the FE mesh has been created int fe_mesh_exist() const { return feMesh_!=NULL; } // get nodal coordinates for a given element void element_coordinates(const int eltIdx, DENS_MAT &coords) { feMesh_->element_coordinates(eltIdx,coords); } // access list of elements to be deleted set & null_elements(void) { return nullElements_; } /*@}*/ private: //---------------------------------------------------------------- /** mesh setup commands (called from modify) */ //---------------------------------------------------------------- /*@{*/ /** initialized flag */ bool initialized_; /** create a uniform, structured mesh */ void create_mesh(int nx, int ny, int nz, char * regionName, int xperiodic, int yperiodic, int zperiodic); /*@}*/ /** ATC transfer object */ ATC_Transfer * atcTransfer_; /** finite element mesh */ FE_Mesh * feMesh_; /** data that can be used for a subset of original mesh */ set nullElements_; bool amendedMeshData_; const Array2D * connectivity_; const Array * nodeMap_; const DENS_MAT * coordinates_; /** workspace */ int nNodesPerElement_; int nIPsPerElement_; int nIPsPerFace_; int nSD_; int nElems_; /** output object */ OutputManager outputManager_; /** base name for output files */ string outputPrefix_; /** output frequency (NOTE will move to "Transfer") */ int outputFrequency_; /** list of output timesteps */ vector outputTimes_; }; }; // end namespace ATC #endif