ContinuationSystem Class Reference
#include <continuation_system.h>

Public Types | |
| enum | Predictor { Euler, AB2, Invalid_Predictor } |
| typedef ContinuationSystem | sys_type |
| typedef FEMSystem | Parent |
| typedef std::map< std::string, SparseMatrix< Number > * >::iterator | matrices_iterator |
| typedef std::map< std::string, SparseMatrix< Number > * >::const_iterator | const_matrices_iterator |
| typedef std::map< std::string, NumericVector< Number > * >::iterator | vectors_iterator |
| typedef std::map< std::string, NumericVector< Number > * >::const_iterator | const_vectors_iterator |
Public Member Functions | |
| ContinuationSystem (EquationSystems &es, const std::string &name, const unsigned int number) | |
| virtual | ~ContinuationSystem () |
| virtual void | clear () |
| virtual void | solve () |
| void | continuation_solve () |
| void | advance_arcstep () |
| void | set_max_arclength_stepsize (Real maxds) |
| void | save_current_solution () |
| virtual void | assembly (bool get_residual, bool get_jacobian) |
| virtual void | time_evolving (unsigned int var) |
| virtual void | mesh_x_position (unsigned int sysnum, unsigned int var) |
| virtual void | mesh_y_position (unsigned int sysnum, unsigned int var) |
| virtual void | mesh_z_position (unsigned int sysnum, unsigned int var) |
| void | mesh_position_get () |
| void | mesh_position_set () |
| virtual bool | eulerian_residual (bool request_jacobian, DiffContext &context) |
| virtual bool | mass_residual (bool request_jacobian, DiffContext &context) |
| virtual AutoPtr< DiffContext > | build_context () |
| virtual void | init_context (DiffContext &) |
| virtual void | postprocess () |
| virtual void | assemble_qoi (const QoISet &indices=QoISet()) |
| virtual void | assemble_qoi_derivative (const QoISet &indices=QoISet()) |
| virtual void | reinit () |
| virtual void | assemble () |
| virtual LinearSolver< Number > * | get_linear_solver () const |
| virtual std::pair< unsigned int, Real > | get_linear_solve_parameters () const |
| virtual void | release_linear_solver (LinearSolver< Number > *) const |
| virtual bool | element_time_derivative (bool request_jacobian, DiffContext &) |
| virtual bool | element_constraint (bool request_jacobian, DiffContext &) |
| virtual bool | side_time_derivative (bool request_jacobian, DiffContext &) |
| virtual bool | side_constraint (bool request_jacobian, DiffContext &) |
| virtual void | element_postprocess (DiffContext &) |
| virtual void | side_postprocess (DiffContext &) |
| virtual void | element_qoi (DiffContext &, const QoISet &) |
| virtual void | element_qoi_derivative (DiffContext &, const QoISet &) |
| virtual void | side_qoi (DiffContext &, const QoISet &) |
| virtual void | side_qoi_derivative (DiffContext &, const QoISet &) |
| virtual bool | side_mass_residual (bool request_jacobian, DiffContext &) |
| sys_type & | system () |
| virtual std::string | system_type () const |
| virtual void | assemble_residual_derivatives (const ParameterVector ¶meters) |
| virtual std::pair< unsigned int, Real > | sensitivity_solve (const ParameterVector ¶meters) |
| virtual std::pair< unsigned int, Real > | weighted_sensitivity_solve (const ParameterVector ¶meters, const ParameterVector &weights) |
| virtual std::pair< unsigned int, Real > | adjoint_solve (const QoISet &qoi_indices=QoISet()) |
| virtual std::pair< unsigned int, Real > | weighted_sensitivity_adjoint_solve (const ParameterVector ¶meters, const ParameterVector &weights, const QoISet &qoi_indices=QoISet()) |
| virtual void | adjoint_qoi_parameter_sensitivity (const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &sensitivities) |
| virtual void | forward_qoi_parameter_sensitivity (const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &sensitivities) |
| virtual void | qoi_parameter_hessian (const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &hessian) |
| virtual void | qoi_parameter_hessian_vector_product (const QoISet &qoi_indices, const ParameterVector ¶meters, const ParameterVector &vector, SensitivityData &product) |
| SparseMatrix< Number > & | add_matrix (const std::string &mat_name) |
| bool | have_matrix (const std::string &mat_name) const |
| const SparseMatrix< Number > * | request_matrix (const std::string &mat_name) const |
| SparseMatrix< Number > * | request_matrix (const std::string &mat_name) |
| const SparseMatrix< Number > & | get_matrix (const std::string &mat_name) const |
| SparseMatrix< Number > & | get_matrix (const std::string &mat_name) |
| unsigned int | n_matrices () const |
| void | init () |
| virtual void | update () |
| virtual void | qoi_parameter_sensitivity (const QoISet &qoi_indices, const ParameterVector ¶meters, SensitivityData &sensitivities) |
| virtual bool | compare (const System &other_system, const Real threshold, const bool verbose) const |
| const std::string & | name () const |
| void | project_solution (Number fptr(const Point &p, const Parameters ¶meters, const std::string &sys_name, const std::string &unknown_name), Gradient gptr(const Point &p, const Parameters ¶meters, const std::string &sys_name, const std::string &unknown_name), Parameters ¶meters) const |
| void | project_vector (Number fptr(const Point &p, const Parameters ¶meters, const std::string &sys_name, const std::string &unknown_name), Gradient gptr(const Point &p, const Parameters ¶meters, const std::string &sys_name, const std::string &unknown_name), Parameters ¶meters, NumericVector< Number > &new_vector) const |
| unsigned int | number () const |
| void | update_global_solution (std::vector< Number > &global_soln) const |
| void | update_global_solution (std::vector< Number > &global_soln, const unsigned int dest_proc) const |
| const MeshBase & | get_mesh () const |
| MeshBase & | get_mesh () |
| const DofMap & | get_dof_map () const |
| DofMap & | get_dof_map () |
| const EquationSystems & | get_equation_systems () const |
| EquationSystems & | get_equation_systems () |
| bool | active () const |
| void | activate () |
| void | deactivate () |
| vectors_iterator | vectors_begin () |
| const_vectors_iterator | vectors_begin () const |
| vectors_iterator | vectors_end () |
| const_vectors_iterator | vectors_end () const |
| NumericVector< Number > & | add_vector (const std::string &vec_name, const bool projections=true) |
| bool & | project_solution_on_reinit (void) |
| bool | have_vector (const std::string &vec_name) const |
| const NumericVector< Number > * | request_vector (const std::string &vec_name) const |
| NumericVector< Number > * | request_vector (const std::string &vec_name) |
| const NumericVector< Number > * | request_vector (const unsigned int vec_num) const |
| NumericVector< Number > * | request_vector (const unsigned int vec_num) |
| const NumericVector< Number > & | get_vector (const std::string &vec_name) const |
| NumericVector< Number > & | get_vector (const std::string &vec_name) |
| const NumericVector< Number > & | get_vector (const unsigned int vec_num) const |
| NumericVector< Number > & | get_vector (const unsigned int vec_num) |
| const std::string & | vector_name (const unsigned int vec_num) |
| NumericVector< Number > & | add_adjoint_solution (unsigned int i=0) |
| NumericVector< Number > & | get_adjoint_solution (unsigned int i=0) |
| const NumericVector< Number > & | get_adjoint_solution (unsigned int i=0) const |
| NumericVector< Number > & | add_sensitivity_solution (unsigned int i=0) |
| NumericVector< Number > & | get_sensitivity_solution (unsigned int i=0) |
| const NumericVector< Number > & | get_sensitivity_solution (unsigned int i=0) const |
| NumericVector< Number > & | add_weighted_sensitivity_adjoint_solution (unsigned int i=0) |
| NumericVector< Number > & | get_weighted_sensitivity_adjoint_solution (unsigned int i=0) |
| const NumericVector< Number > & | get_weighted_sensitivity_adjoint_solution (unsigned int i=0) const |
| NumericVector< Number > & | add_weighted_sensitivity_solution () |
| NumericVector< Number > & | get_weighted_sensitivity_solution () |
| const NumericVector< Number > & | get_weighted_sensitivity_solution () const |
| NumericVector< Number > & | add_adjoint_rhs (unsigned int i=0) |
| NumericVector< Number > & | get_adjoint_rhs (unsigned int i=0) |
| const NumericVector< Number > & | get_adjoint_rhs (unsigned int i=0) const |
| NumericVector< Number > & | add_sensitivity_rhs (unsigned int i=0) |
| NumericVector< Number > & | get_sensitivity_rhs (unsigned int i=0) |
| const NumericVector< Number > & | get_sensitivity_rhs (unsigned int i=0) const |
| unsigned int | n_vectors () const |
| unsigned int | n_vars () const |
| unsigned int | n_dofs () const |
| unsigned int | n_active_dofs () const |
| unsigned int | n_constrained_dofs () const |
| unsigned int | n_local_dofs () const |
| unsigned int | add_variable (const std::string &var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=NULL) |
| unsigned int | add_variable (const std::string &var, const Order order=FIRST, const FEFamily=LAGRANGE, const std::set< subdomain_id_type > *const active_subdomains=NULL) |
| const Variable & | variable (unsigned int var) const |
| bool | has_variable (const std::string &var) const |
| const std::string & | variable_name (const unsigned int i) const |
| unsigned short int | variable_number (const std::string &var) const |
| const FEType & | variable_type (const unsigned int i) const |
| const FEType & | variable_type (const std::string &var) const |
| Real | calculate_norm (NumericVector< Number > &v, unsigned int var=0, FEMNormType norm_type=L2) const |
| Real | calculate_norm (NumericVector< Number > &v, const SystemNorm &norm) const |
| void | read_header (Xdr &io, const std::string &version, const bool read_header=true, const bool read_additional_data=true, const bool read_legacy_format=false) |
| void | read_legacy_data (Xdr &io, const bool read_additional_data=true) |
| void | read_serialized_data (Xdr &io, const bool read_additional_data=true) |
| void | read_parallel_data (Xdr &io, const bool read_additional_data) |
| void | write_header (Xdr &io, const std::string &version, const bool write_additional_data) const |
| void | write_serialized_data (Xdr &io, const bool write_additional_data=true) const |
| void | write_parallel_data (Xdr &io, const bool write_additional_data) const |
| std::string | get_info () const |
| void | attach_init_function (void fptr(EquationSystems &es, const std::string &name)) |
| void | attach_assemble_function (void fptr(EquationSystems &es, const std::string &name)) |
| void | attach_constraint_function (void fptr(EquationSystems &es, const std::string &name)) |
| void | attach_QOI_function (void fptr(EquationSystems &es, const std::string &name, const QoISet &qoi_indices)) |
| void | attach_QOI_derivative (void fptr(EquationSystems &es, const std::string &name, const QoISet &qoi_indices)) |
| virtual void | user_initialization () |
| virtual void | user_assembly () |
| virtual void | user_constrain () |
| virtual void | user_QOI (const QoISet &qoi_indices) |
| virtual void | user_QOI_derivative (const QoISet &qoi_indices) |
| virtual void | re_update () |
| virtual void | restrict_vectors () |
| virtual void | prolong_vectors () |
| Number | current_solution (const unsigned int global_dof_number) const |
| void | local_dof_indices (const unsigned int var, std::set< unsigned int > &var_indices) const |
| void | zero_variable (NumericVector< Number > &v, unsigned int var_num) const |
Static Public Member Functions | |
| static std::string | get_info () |
| static void | print_info () |
| static unsigned int | n_objects () |
Public Attributes | |
| Real * | continuation_parameter |
| bool | quiet |
| Real | continuation_parameter_tolerance |
| Real | solution_tolerance |
| Real | initial_newton_tolerance |
| Real | old_continuation_parameter |
| Real | min_continuation_parameter |
| Real | max_continuation_parameter |
| Real | Theta |
| Real | Theta_LOCA |
| unsigned int | n_backtrack_steps |
| unsigned int | n_arclength_reductions |
| Real | ds_min |
| Predictor | predictor |
| Real | newton_stepgrowth_aggressiveness |
| bool | newton_progress_check |
| bool | fe_reinit_during_postprocess |
| int | extra_quadrature_order |
| Real | numerical_jacobian_h |
| Real | verify_analytic_jacobians |
| bool | compute_internal_sides |
| bool | postprocess_sides |
| bool | assemble_qoi_sides |
| AutoPtr< TimeSolver > | time_solver |
| Real | time |
| Real | deltat |
| bool | print_solution_norms |
| bool | print_solutions |
| bool | print_residual_norms |
| bool | print_residuals |
| bool | print_jacobian_norms |
| bool | print_jacobians |
| bool | print_element_jacobians |
| bool | use_fixed_solution |
| SparseMatrix< Number > * | matrix |
| NumericVector< Number > * | rhs |
| bool | assemble_before_solve |
| AutoPtr< NumericVector< Number > > | solution |
| AutoPtr< NumericVector< Number > > | current_local_solution |
| std::vector< Number > | qoi |
Protected Types | |
| enum | RHS_Mode { Residual, G_Lambda } |
| typedef bool(TimeSolver::* | TimeSolverResPtr )(bool, DiffContext &) |
| typedef std::map< std::string, std::pair< unsigned int, unsigned int > > | Counts |
Protected Member Functions | |
| virtual void | init_data () |
| void | numerical_jacobian (TimeSolverResPtr res, FEMContext &context) |
| void | numerical_elem_jacobian (FEMContext &context) |
| void | numerical_side_jacobian (FEMContext &context) |
| virtual void | init_matrices () |
| void | project_vector (NumericVector< Number > &) const |
| void | project_vector (const NumericVector< Number > &, NumericVector< Number > &) const |
| void | increment_constructor_count (const std::string &name) |
| void | increment_destructor_count (const std::string &name) |
Protected Attributes | |
| RHS_Mode | rhs_mode |
| unsigned int | _mesh_sys |
| unsigned int | _mesh_x_var |
| unsigned int | _mesh_y_var |
| unsigned int | _mesh_z_var |
| std::vector< bool > | _time_evolving |
Static Protected Attributes | |
| static Counts | _counts |
| static Threads::atomic < unsigned int > | _n_objects |
| static Threads::spin_mutex | _mutex |
Private Member Functions | |
| void | initialize_tangent () |
| void | solve_tangent () |
| void | update_solution () |
| void | set_Theta () |
| void | set_Theta_LOCA () |
| void | apply_predictor () |
Private Attributes | |
| NumericVector< Number > * | du_ds |
| NumericVector< Number > * | previous_du_ds |
| NumericVector< Number > * | previous_u |
| NumericVector< Number > * | y |
| NumericVector< Number > * | y_old |
| NumericVector< Number > * | z |
| NumericVector< Number > * | delta_u |
| AutoPtr< LinearSolver< Number > > | linear_solver |
| bool | tangent_initialized |
| NewtonSolver * | newton_solver |
| Real | dlambda_ds |
| Real | ds |
| Real | ds_current |
| Real | previous_dlambda_ds |
| Real | previous_ds |
| unsigned int | newton_step |
Detailed Description
This class inherits from the FEMSystem. It can be used to do arclength continuation. Most of the ideas and the notation here come from HB Keller's 1977 paper:
@InProceedings{Kell-1977,
author = {H.~B.~Keller},
title = {{Numerical solution of bifurcation and nonlinear eigenvalue problems}},
booktitle = {Applications of Bifurcation Theory, P.~H.~Rabinowitz (ed.)},
year = 1977,
publisher = {Academic Press},
pages = {359--389},
notes = {QA 3 U45 No.\ 38 (PMA)}
}
Definition at line 56 of file continuation_system.h.
Member Typedef Documentation
typedef std::map<std::string, SparseMatrix<Number>* >::const_iterator ImplicitSystem::const_matrices_iterator [inherited] |
Definition at line 268 of file implicit_system.h.
typedef std::map<std::string, NumericVector<Number>* >::const_iterator System::const_vectors_iterator [inherited] |
typedef std::map<std::string, std::pair<unsigned int, unsigned int> > ReferenceCounter::Counts [protected, inherited] |
Data structure to log the information. The log is identified by the class name.
Definition at line 105 of file reference_counter.h.
typedef std::map<std::string, SparseMatrix<Number>* >::iterator ImplicitSystem::matrices_iterator [inherited] |
Matrix iterator typedefs.
Definition at line 267 of file implicit_system.h.
| typedef FEMSystem ContinuationSystem::Parent |
The type of the parent.
Reimplemented from FEMSystem.
Definition at line 80 of file continuation_system.h.
The type of system.
Reimplemented from FEMSystem.
Definition at line 75 of file continuation_system.h.
typedef bool(TimeSolver::* FEMSystem::TimeSolverResPtr)(bool, DiffContext &) [protected, inherited] |
Syntax sugar to make numerical_jacobian() declaration easier.
typedef std::map<std::string, NumericVector<Number>* >::iterator System::vectors_iterator [inherited] |
Member Enumeration Documentation
The code provides the ability to select from different predictor schemes for getting the initial guess for the solution at the next point on the solution arc.
- Enumerator:
-
Euler First-order Euler predictor AB2 Second-order explicit Adams-Bashforth predictor Invalid_Predictor Invalid predictor
Definition at line 222 of file continuation_system.h.
00222 { 00226 Euler, 00227 00231 AB2, 00232 00236 Invalid_Predictor 00237 };
enum ContinuationSystem::RHS_Mode [protected] |
There are (so far) two different vectors which may be assembled using the assembly routine: 1.) The Residual = the normal PDE weighted residual 2.) G_Lambda = the derivative wrt the parameter lambda of the PDE weighted residual
It is up to the derived class to handle writing separate assembly code for the different cases. Usually something like: switch (rhs_mode) { case Residual: { Fu(i) += ... // normal PDE residual break; }
case G_Lambda: { Fu(i) += ... // derivative wrt control parameter break; }
Definition at line 287 of file continuation_system.h.
Constructor & Destructor Documentation
| ContinuationSystem::ContinuationSystem | ( | EquationSystems & | es, | |
| const std::string & | name, | |||
| const unsigned int | number | |||
| ) |
Constructor. Optionally initializes required data structures.
Definition at line 27 of file continuation_system.C.
00030 : Parent(es, name, number), 00031 continuation_parameter(NULL), 00032 quiet(true), 00033 continuation_parameter_tolerance(1.e-6), 00034 solution_tolerance(1.e-6), 00035 initial_newton_tolerance(0.01), 00036 old_continuation_parameter(0.), 00037 min_continuation_parameter(0.), 00038 max_continuation_parameter(0.), 00039 Theta(1.), 00040 Theta_LOCA(1.), 00041 //tau(1.), 00042 n_backtrack_steps(5), 00043 n_arclength_reductions(5), 00044 ds_min(1.e-8), 00045 predictor(Euler), 00046 newton_stepgrowth_aggressiveness(1.), 00047 newton_progress_check(true), 00048 rhs_mode(Residual), 00049 linear_solver(LinearSolver<Number>::build()), 00050 tangent_initialized(false), 00051 newton_solver(NULL), 00052 dlambda_ds(0.707), 00053 ds(0.1), 00054 ds_current(0.1), 00055 previous_dlambda_ds(0.), 00056 previous_ds(0.), 00057 newton_step(0) 00058 { 00059 // Warn about using untested code 00060 libmesh_experimental(); 00061 }
| ContinuationSystem::~ContinuationSystem | ( | ) | [virtual] |
Destructor.
Definition at line 66 of file continuation_system.C.
References clear().
00067 { 00068 this->clear(); 00069 }
Member Function Documentation
| void System::activate | ( | ) | [inline, inherited] |
Activates the system. Only active systems are solved.
Definition at line 1380 of file system.h.
References System::_active.
01381 { 01382 _active = true; 01383 }
| bool System::active | ( | ) | const [inline, inherited] |
- Returns:
trueif the system is active,falseotherwise. An active system will be solved.
Definition at line 1372 of file system.h.
References System::_active.
01373 { 01374 return _active; 01375 }
| NumericVector< Number > & System::add_adjoint_rhs | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's adjoint rhs vectors, by default the one corresponding to the first qoi. Creates the vector if it doesn't already exist.
Definition at line 824 of file system.C.
References System::add_vector().
Referenced by FEMSystem::assemble_qoi_derivative(), and ExplicitSystem::assemble_qoi_derivative().
00825 { 00826 OStringStream adjoint_rhs_name; 00827 adjoint_rhs_name << "adjoint_rhs" << i; 00828 00829 return this->add_vector(adjoint_rhs_name.str()); 00830 }
| NumericVector< Number > & System::add_adjoint_solution | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's adjoint solution vectors, by default the one corresponding to the first qoi. Creates the vector if it doesn't already exist.
Definition at line 764 of file system.C.
References System::add_vector().
Referenced by ImplicitSystem::adjoint_solve().
00765 { 00766 OStringStream adjoint_name; 00767 adjoint_name << "adjoint_solution" << i; 00768 00769 return this->add_vector(adjoint_name.str()); 00770 }
| SparseMatrix< Number > & ImplicitSystem::add_matrix | ( | const std::string & | mat_name | ) | [inherited] |
Adds the additional matrix mat_name to this system. Only allowed prior to assemble(). All additional matrices have the same sparsity pattern as the matrix used during solution. When not System but the user wants to initialize the mayor matrix, then all the additional matrices, if existent, have to be initialized by the user, too.
Definition at line 175 of file implicit_system.C.
References ImplicitSystem::_can_add_matrices, ImplicitSystem::_matrices, and ImplicitSystem::have_matrix().
Referenced by ImplicitSystem::add_system_matrix(), EigenTimeSolver::init(), and NewmarkSystem::NewmarkSystem().
00176 { 00177 // only add matrices before initializing... 00178 if (!_can_add_matrices) 00179 { 00180 std::cerr << "ERROR: Too late. Cannot add matrices to the system after initialization" 00181 << std::endl 00182 << " any more. You should have done this earlier." 00183 << std::endl; 00184 libmesh_error(); 00185 } 00186 00187 // Return the matrix if it is already there. 00188 if (this->have_matrix(mat_name)) 00189 return *(_matrices[mat_name]); 00190 00191 // Otherwise build the matrix and return it. 00192 SparseMatrix<Number>* buf = SparseMatrix<Number>::build().release(); 00193 _matrices.insert (std::make_pair (mat_name, buf)); 00194 00195 return *buf; 00196 }
| NumericVector< Number > & System::add_sensitivity_rhs | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's sensitivity rhs vectors, by default the one corresponding to the first parameter. Creates the vector if it doesn't already exist.
Definition at line 854 of file system.C.
References System::add_vector().
Referenced by ImplicitSystem::assemble_residual_derivatives().
00855 { 00856 OStringStream sensitivity_rhs_name; 00857 sensitivity_rhs_name << "sensitivity_rhs" << i; 00858 00859 return this->add_vector(sensitivity_rhs_name.str()); 00860 }
| NumericVector< Number > & System::add_sensitivity_solution | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's solution sensitivity vectors, by default the one corresponding to the first parameter. Creates the vector if it doesn't already exist.
Definition at line 714 of file system.C.
References System::add_vector().
00715 { 00716 OStringStream sensitivity_name; 00717 sensitivity_name << "sensitivity_solution" << i; 00718 00719 return this->add_vector(sensitivity_name.str()); 00720 }
| unsigned int System::add_variable | ( | const std::string & | var, | |
| const Order | order = FIRST, |
|||
| const FEFamily | family = LAGRANGE, |
|||
| const std::set< subdomain_id_type > *const | active_subdomains = NULL | |||
| ) | [inherited] |
Adds the variable var to the list of variables for this system. Same as before, but assumes LAGRANGE as default value for FEType.family.
Definition at line 923 of file system.C.
References System::add_variable().
00927 { 00928 return this->add_variable(var, 00929 FEType(order, family), 00930 active_subdomains); 00931 }
| unsigned int System::add_variable | ( | const std::string & | var, | |
| const FEType & | type, | |||
| const std::set< subdomain_id_type > *const | active_subdomains = NULL | |||
| ) | [inherited] |
Adds the variable var to the list of variables for this system. Returns the index number for the new variable.
Definition at line 884 of file system.C.
References System::_dof_map, System::_variable_numbers, System::_variables, System::n_vars(), System::number(), System::variable_name(), and System::variable_type().
Referenced by System::add_variable(), ErrorVector::plot_error(), and System::read_header().
00887 { 00888 // Make sure the variable isn't there already 00889 // or if it is, that it's the type we want 00890 for (unsigned int v=0; v<this->n_vars(); v++) 00891 if (this->variable_name(v) == var) 00892 { 00893 if (this->variable_type(v) == type) 00894 return _variables[v].number(); 00895 00896 std::cerr << "ERROR: incompatible variable " 00897 << var 00898 << " has already been added for this system!" 00899 << std::endl; 00900 libmesh_error(); 00901 } 00902 00903 const unsigned int curr_n_vars = this->n_vars(); 00904 00905 // Add the variable to the list 00906 _variables.push_back((active_subdomains == NULL) ? 00907 Variable(var, curr_n_vars, type) : 00908 Variable(var, curr_n_vars, type, *active_subdomains)); 00909 00910 libmesh_assert ((curr_n_vars+1) == this->n_vars()); 00911 00912 _variable_numbers[var] = curr_n_vars; 00913 00914 // Add the variable to the _dof_map 00915 _dof_map->add_variable (_variables.back()); 00916 00917 // Return the number of the new variable 00918 return curr_n_vars; 00919 }
| NumericVector< Number > & System::add_vector | ( | const std::string & | vec_name, | |
| const bool | projections = true | |||
| ) | [inherited] |
Adds the additional vector vec_name to this system. Only allowed prior to init(). All the additional vectors are similarly distributed, like the solution, and inititialized to zero.
By default vectors added by add_vector are projected to changed grids by reinit(). To zero them instead (more efficient), pass "false" as the second argument
Definition at line 549 of file system.C.
References System::_can_add_vectors, System::_vector_projections, System::_vectors, System::have_vector(), NumericVector< T >::init(), System::n_dofs(), System::n_local_dofs(), and libMeshEnums::PARALLEL.
Referenced by System::add_adjoint_rhs(), System::add_adjoint_solution(), System::add_sensitivity_rhs(), System::add_sensitivity_solution(), ExplicitSystem::add_system_rhs(), System::add_weighted_sensitivity_solution(), UnsteadySolver::init(), init_data(), NewmarkSystem::NewmarkSystem(), System::read_header(), FrequencySystem::set_frequencies(), FrequencySystem::set_frequencies_by_range(), and FrequencySystem::set_frequencies_by_steps().
00551 { 00552 // Return the vector if it is already there. 00553 if (this->have_vector(vec_name)) 00554 return *(_vectors[vec_name]); 00555 00556 // Otherwise build the vector 00557 NumericVector<Number>* buf = NumericVector<Number>::build().release(); 00558 _vectors.insert (std::make_pair (vec_name, buf)); 00559 _vector_projections.insert (std::make_pair (vec_name, projections)); 00560 00561 // Initialize it if necessary 00562 if (!_can_add_vectors) 00563 buf->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL); 00564 00565 return *buf; 00566 }
| NumericVector< Number > & System::add_weighted_sensitivity_adjoint_solution | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's weighted sensitivity adjoint solution vectors, by default the one corresponding to the first qoi. Creates the vector if it doesn't already exist.
Definition at line 794 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::weighted_sensitivity_adjoint_solve().
00795 { 00796 OStringStream adjoint_name; 00797 adjoint_name << "weighted_sensitivity_adjoint_solution" << i; 00798 00799 return this->get_vector(adjoint_name.str()); 00800 }
| NumericVector< Number > & System::add_weighted_sensitivity_solution | ( | ) | [inherited] |
- Returns:
- a reference to the solution of the last weighted sensitivity solve Creates the vector if it doesn't already exist.
Definition at line 743 of file system.C.
References System::add_vector().
Referenced by ImplicitSystem::weighted_sensitivity_solve().
00744 { 00745 return this->add_vector("weighted_sensitivity_solution"); 00746 }
| void ImplicitSystem::adjoint_qoi_parameter_sensitivity | ( | const QoISet & | qoi_indices, | |
| const ParameterVector & | parameters, | |||
| SensitivityData & | sensitivities | |||
| ) | [virtual, inherited] |
Solves for the derivative of each of the system's quantities of interest q in qoi[qoi_indices] with respect to each parameter in parameters, placing the result for qoi i and parameter j into sensitivities[i][j].
Uses adjoint_solve() and the adjoint sensitivity method.
Currently uses finite differenced derivatives (partial q / partial p) and (partial R / partial p).
Reimplemented from System.
Definition at line 657 of file implicit_system.C.
References SensitivityData::allocate_data(), QoISet::has_index(), and ParameterVector::size().
00660 { 00661 const unsigned int Np = parameters.size(); 00662 const unsigned int Nq = qoi.size(); 00663 00664 // We currently get partial derivatives via central differencing 00665 const Real delta_p = TOLERANCE; 00666 00667 // An introduction to the problem: 00668 // 00669 // Residual R(u(p),p) = 0 00670 // partial R / partial u = J = system matrix 00671 // 00672 // This implies that: 00673 // d/dp(R) = 0 00674 // (partial R / partial p) + 00675 // (partial R / partial u) * (partial u / partial p) = 0 00676 00677 // We first do an adjoint solve: 00678 // J^T * z = (partial q / partial u) 00679 00680 this->adjoint_solve(qoi_indices); 00681 00682 // Get ready to fill in senstivities: 00683 sensitivities.allocate_data(qoi_indices, *this, parameters); 00684 00685 // We use the identities: 00686 // dq/dp = (partial q / partial p) + (partial q / partial u) * 00687 // (partial u / partial p) 00688 // dq/dp = (partial q / partial p) + (J^T * z) * 00689 // (partial u / partial p) 00690 // dq/dp = (partial q / partial p) + z * J * 00691 // (partial u / partial p) 00692 00693 // Leading to our final formula: 00694 // dq/dp = (partial q / partial p) - z * (partial R / partial p) 00695 00696 for (unsigned int j=0; j != Np; ++j) 00697 { 00698 // (partial q / partial p) ~= (q(p+dp)-q(p-dp))/(2*dp) 00699 // (partial R / partial p) ~= (rhs(p+dp) - rhs(p-dp))/(2*dp) 00700 00701 Number old_parameter = *parameters[j]; 00702 // Number old_qoi = this->qoi; 00703 00704 *parameters[j] = old_parameter - delta_p; 00705 this->assemble_qoi(qoi_indices); 00706 std::vector<Number> qoi_minus = this->qoi; 00707 00708 this->assembly(true, false); 00709 this->rhs->close(); 00710 AutoPtr<NumericVector<Number> > partialR_partialp = this->rhs->clone(); 00711 *partialR_partialp *= -1; 00712 00713 *parameters[j] = old_parameter + delta_p; 00714 this->assemble_qoi(qoi_indices); 00715 std::vector<Number>& qoi_plus = this->qoi; 00716 00717 std::vector<Number> partialq_partialp(Nq, 0); 00718 for (unsigned int i=0; i != Nq; ++i) 00719 if (qoi_indices.has_index(i)) 00720 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p); 00721 00722 this->assembly(true, false); 00723 this->rhs->close(); 00724 *partialR_partialp += *this->rhs; 00725 *partialR_partialp /= (2.*delta_p); 00726 00727 // Don't leave the parameter changed 00728 *parameters[j] = old_parameter; 00729 00730 for (unsigned int i=0; i != Nq; ++i) 00731 if (qoi_indices.has_index(i)) 00732 sensitivities[i][j] = partialq_partialp[i] - 00733 partialR_partialp->dot(this->get_adjoint_solution(i)); 00734 } 00735 00736 // All parameters have been reset. 00737 // We didn't cache the original rhs or matrix for memory reasons, 00738 // but we can restore them to a state consistent solution - 00739 // principle of least surprise. 00740 this->assembly(true, true); 00741 this->rhs->close(); 00742 this->matrix->close(); 00743 this->assemble_qoi(qoi_indices); 00744 }
| std::pair< unsigned int, Real > ImplicitSystem::adjoint_solve | ( | const QoISet & | qoi_indices = QoISet() |
) | [virtual, inherited] |
Assembles & solves the linear system (dR/du)^T*z = dq/du, for those quantities of interest q specified by qoi_indices.
Leave qoi_indices empty to solve all adjoint problems.
Returns a pair with the total number of linear iterations performed and the (sum of the) final residual norms
Reimplemented from System.
Definition at line 342 of file implicit_system.C.
References System::add_adjoint_solution(), System::assemble_before_solve, ExplicitSystem::assemble_qoi_derivative(), ImplicitSystem::assembly(), DofMap::enforce_constraints_exactly(), System::get_adjoint_rhs(), System::get_adjoint_solution(), System::get_dof_map(), ImplicitSystem::get_linear_solve_parameters(), ImplicitSystem::get_linear_solver(), QoISet::has_index(), ImplicitSystem::matrix, System::qoi, ImplicitSystem::release_linear_solver(), and LinearSolver< T >::solve().
00343 { 00344 // Log how long the linear solve takes. 00345 START_LOG("adjoint_solve()", "ImplicitSystem"); 00346 00347 // The forward system should now already be solved. 00348 // Now assemble it's adjoint. 00349 00350 if (this->assemble_before_solve) 00351 { 00352 // Build the Jacobian 00353 this->assembly(false, true); 00354 this->matrix->close(); 00355 00356 // Take the discrete adjoint 00357 matrix->get_transpose(*matrix); 00358 00359 // Reset and build the RHS from the QOI derivative 00360 this->assemble_qoi_derivative(qoi_indices); 00361 } 00362 00363 // The adjoint problem is linear 00364 LinearSolver<Number> *linear_solver = this->get_linear_solver(); 00365 00366 // Our iteration counts and residuals will be sums of the individual 00367 // results 00368 std::pair<unsigned int, Real> solver_params = 00369 this->get_linear_solve_parameters(); 00370 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0); 00371 00372 for (unsigned int i=0; i != this->qoi.size(); ++i) 00373 if (qoi_indices.has_index(i)) 00374 { 00375 const std::pair<unsigned int, Real> rval = 00376 linear_solver->solve (*matrix, this->add_adjoint_solution(i), 00377 this->get_adjoint_rhs(i), 00378 solver_params.second, 00379 solver_params.first); 00380 00381 totalrval.first += rval.first; 00382 totalrval.second += rval.second; 00383 } 00384 00385 this->release_linear_solver(linear_solver); 00386 00387 // The linear solver may not have fit our constraints exactly 00388 #ifdef LIBMESH_ENABLE_AMR 00389 for (unsigned int i=0; i != this->qoi.size(); ++i) 00390 if (qoi_indices.has_index(i)) 00391 this->get_dof_map().enforce_constraints_exactly 00392 (*this, &this->get_adjoint_solution(i)); 00393 #endif 00394 00395 // Stop logging the nonlinear solve 00396 STOP_LOG("adjoint_solve()", "ImplicitSystem"); 00397 00398 return totalrval; 00399 }
| void ContinuationSystem::advance_arcstep | ( | ) |
Call this function after a continuation solve to compute the tangent and get the next initial guess.
Definition at line 945 of file continuation_system.C.
References solve_tangent(), and update_solution().
00946 { 00947 // Solve for the updated tangent du1/ds, d(lambda1)/ds 00948 solve_tangent(); 00949 00950 // Advance the solution and the parameter to the next value. 00951 update_solution(); 00952 }
| void ContinuationSystem::apply_predictor | ( | ) | [private] |
Applies the predictor to the current solution to get a guess for the next solution.
Definition at line 1384 of file continuation_system.C.
References AB2, continuation_parameter, dlambda_ds, ds_current, du_ds, Euler, predictor, previous_dlambda_ds, previous_ds, previous_du_ds, and System::solution.
Referenced by continuation_solve(), and update_solution().
01385 { 01386 if (predictor == Euler) 01387 { 01388 // 1.) Euler Predictor 01389 // Predict next the solution 01390 solution->add(ds_current, *du_ds); 01391 solution->close(); 01392 01393 // Predict next parameter value 01394 *continuation_parameter += ds_current*dlambda_ds; 01395 } 01396 01397 01398 else if (predictor == AB2) 01399 { 01400 // 2.) 2nd-order explicit AB predictor 01401 libmesh_assert(previous_ds != 0.0); 01402 const Real stepratio = ds_current/previous_ds; 01403 01404 // Build up next solution value. 01405 solution->add( 0.5*ds_current*(2.+stepratio), *du_ds); 01406 solution->add(-0.5*ds_current*stepratio , *previous_du_ds); 01407 solution->close(); 01408 01409 // Next parameter value 01410 *continuation_parameter += 01411 0.5*ds_current*((2.+stepratio)*dlambda_ds - 01412 stepratio*previous_dlambda_ds); 01413 } 01414 01415 else 01416 { 01417 // Unknown predictor 01418 libmesh_error(); 01419 } 01420 01421 }
| void DifferentiableSystem::assemble | ( | ) | [virtual, inherited] |
Prepares matrix and rhs for matrix assembly. Users should not reimplement this
Reimplemented from ImplicitSystem.
Definition at line 102 of file diff_system.C.
References DifferentiableSystem::assembly().
00103 { 00104 this->assembly(true, true); 00105 }
Runs a qoi assembly loop over all elements, and if assemble_qoi_sides is true over all sides.
Users may have to override this function for quantities of interest that are not expressible as a sum of element qois.
Reimplemented from ExplicitSystem.
Definition at line 486 of file fem_system.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), DifferentiableSystem::assemble_qoi_sides, FEMSystem::build_context(), DifferentiableSystem::compute_internal_sides, FEMContext::elem, DiffContext::elem_qoi, DifferentiableSystem::element_qoi(), System::get_mesh(), QoISet::has_index(), mesh, Elem::n_sides(), Elem::neighbor(), System::qoi, FEMContext::reinit(), FEMContext::side, FEMContext::side_fe, DifferentiableSystem::side_qoi(), and System::update().
00487 { 00488 START_LOG("assemble_qoi()", "FEMSystem"); 00489 00490 const MeshBase& mesh = this->get_mesh(); 00491 00492 this->update(); 00493 00494 AutoPtr<DiffContext> con = this->build_context(); 00495 FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con); 00496 00497 // the quantity of interest is assumed to be a sum of element and 00498 // side terms 00499 for (unsigned int i=0; i != qoi.size(); ++i) 00500 if (qoi_indices.has_index(i)) 00501 qoi[i] = 0; 00502 00503 // Loop over every active mesh element on this processor 00504 MeshBase::const_element_iterator el = 00505 mesh.active_local_elements_begin(); 00506 const MeshBase::const_element_iterator end_el = 00507 mesh.active_local_elements_end(); 00508 00509 for ( ; el != end_el; ++el) 00510 { 00511 _femcontext.reinit(*this, *el); 00512 00513 this->element_qoi(_femcontext, qoi_indices); 00514 00515 for (_femcontext.side = 0; 00516 _femcontext.side != _femcontext.elem->n_sides(); 00517 ++_femcontext.side) 00518 { 00519 // Don't compute on non-boundary sides unless requested 00520 if (!assemble_qoi_sides || 00521 (!compute_internal_sides && 00522 _femcontext.elem->neighbor(_femcontext.side) != NULL)) 00523 continue; 00524 00525 std::map<FEType, FEBase *>::iterator fe_end = 00526 _femcontext.side_fe.end(); 00527 for (std::map<FEType, FEBase *>::iterator i = 00528 _femcontext.side_fe.begin(); 00529 i != fe_end; ++i) 00530 { 00531 i->second->reinit(_femcontext.elem, _femcontext.side); 00532 } 00533 00534 this->side_qoi(_femcontext, qoi_indices); 00535 } 00536 } 00537 00538 Parallel::sum(_femcontext.elem_qoi); 00539 00540 this->qoi = _femcontext.elem_qoi; 00541 00542 STOP_LOG("assemble_qoi()", "FEMSystem"); 00543 }
Runs a qoi derivative assembly loop over all elements, and if assemble_qoi_sides is true over all sides.
Users may have to override this function for quantities of interest that are not expressible as a sum of element qois.
Reimplemented from ExplicitSystem.
Definition at line 547 of file fem_system.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), System::add_adjoint_rhs(), DifferentiableSystem::assemble_qoi_sides, FEMSystem::build_context(), DifferentiableSystem::compute_internal_sides, DofMap::constrain_element_vector(), DiffContext::dof_indices, FEMContext::elem, DiffContext::elem_qoi_derivative, DifferentiableSystem::element_qoi_derivative(), System::get_adjoint_rhs(), System::get_dof_map(), System::get_mesh(), QoISet::has_index(), mesh, Elem::n_sides(), Elem::neighbor(), System::qoi, FEMContext::reinit(), FEMContext::side, FEMContext::side_fe, DifferentiableSystem::side_qoi_derivative(), and System::update().
00548 { 00549 START_LOG("assemble_qoi_derivative()", "FEMSystem"); 00550 00551 const MeshBase& mesh = this->get_mesh(); 00552 00553 this->update(); 00554 00555 AutoPtr<DiffContext> con = this->build_context(); 00556 FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con); 00557 00558 // The quantity of interest derivative assembly accumulates on 00559 // initially zero vectors 00560 for (unsigned int i=0; i != qoi.size(); ++i) 00561 if (qoi_indices.has_index(i)) 00562 this->add_adjoint_rhs(i).zero(); 00563 00564 // Loop over every active mesh element on this processor 00565 MeshBase::const_element_iterator el = 00566 mesh.active_local_elements_begin(); 00567 const MeshBase::const_element_iterator end_el = 00568 mesh.active_local_elements_end(); 00569 00570 for ( ; el != end_el; ++el) 00571 { 00572 _femcontext.reinit(*this, *el); 00573 00574 this->element_qoi_derivative(_femcontext, qoi_indices); 00575 00576 for (_femcontext.side = 0; 00577 _femcontext.side != _femcontext.elem->n_sides(); 00578 ++_femcontext.side) 00579 { 00580 // Don't compute on non-boundary sides unless requested 00581 if (!assemble_qoi_sides || 00582 (!compute_internal_sides && 00583 _femcontext.elem->neighbor(_femcontext.side) != NULL)) 00584 continue; 00585 00586 std::map<FEType, FEBase *>::iterator fe_end = 00587 _femcontext.side_fe.end(); 00588 for (std::map<FEType, FEBase *>::iterator i = 00589 _femcontext.side_fe.begin(); 00590 i != fe_end; ++i) 00591 { 00592 i->second->reinit(_femcontext.elem, _femcontext.side); 00593 } 00594 00595 this->side_qoi_derivative(_femcontext, qoi_indices); 00596 } 00597 00598 // We need some unmodified indices to use for constraining 00599 // multiple vector 00600 // FIXME - there should be a DofMap::constrain_element_vectors 00601 // to do this more efficiently 00602 std::vector<unsigned int> original_dofs = _femcontext.dof_indices; 00603 00604 for (unsigned int i=0; i != qoi.size(); ++i) 00605 if (qoi_indices.has_index(i)) 00606 { 00607 _femcontext.dof_indices = original_dofs; 00608 this->get_dof_map().constrain_element_vector 00609 (_femcontext.elem_qoi_derivative[i], _femcontext.dof_indices, false); 00610 00611 this->get_adjoint_rhs(i).add_vector 00612 (_femcontext.elem_qoi_derivative[i], _femcontext.dof_indices); 00613 } 00614 } 00615 00616 STOP_LOG("assemble_qoi_derivative()", "FEMSystem"); 00617 }
| void ImplicitSystem::assemble_residual_derivatives | ( | const ParameterVector & | parameters | ) | [virtual, inherited] |
Residual parameter derivative function.
Uses finite differences by default.
This will assemble the sensitivity rhs vectors to hold -(partial R / partial p_i), making them ready to solve the forward sensitivity equation.
Can be overloaded in derived classes.
Reimplemented from System.
Definition at line 622 of file implicit_system.C.
References System::add_sensitivity_rhs(), ImplicitSystem::assembly(), NumericVector< T >::close(), ExplicitSystem::rhs, and ParameterVector::size().
Referenced by ImplicitSystem::sensitivity_solve().
00623 { 00624 const unsigned int Np = parameters.size(); 00625 Real deltap = TOLERANCE; 00626 00627 for (unsigned int p=0; p != Np; ++p) 00628 { 00629 NumericVector<Number> &sensitivity_rhs = this->add_sensitivity_rhs(p); 00630 00631 // Approximate -(partial R / partial p) by 00632 // (R(p-dp) - R(p+dp)) / (2*dp) 00633 00634 Number old_parameter = *parameters[p]; 00635 *parameters[p] -= deltap; 00636 00637 this->assembly(true, false); 00638 this->rhs->close(); 00639 sensitivity_rhs = *this->rhs; 00640 00641 *parameters[p] = old_parameter + deltap; 00642 00643 this->assembly(true, false); 00644 this->rhs->close(); 00645 00646 sensitivity_rhs -= *this->rhs; 00647 sensitivity_rhs /= (2*deltap); 00648 sensitivity_rhs.close(); 00649 00650 *parameters[p] = old_parameter; 00651 } 00652 }
| void FEMSystem::assembly | ( | bool | get_residual, | |
| bool | get_jacobian | |||
| ) | [virtual, inherited] |
Prepares matrix or rhs for matrix assembly. Users may reimplement this to add pre- or post-assembly code before or after calling FEMSystem::assembly()
Implements DifferentiableSystem.
Definition at line 78 of file fem_system.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), DenseMatrix< T >::add(), FEMSystem::build_context(), DifferentiableSystem::compute_internal_sides, DofMap::constrain_element_matrix(), DofMap::constrain_element_matrix_and_vector(), DofMap::constrain_element_vector(), DiffContext::dof_indices, FEMContext::elem, DiffContext::elem_jacobian, DiffContext::elem_residual, FEMContext::elem_side_fe_reinit(), AutoPtr< Tp >::get(), System::get_dof_map(), System::get_mesh(), DofObject::id(), DenseMatrix< T >::l1_norm(), ImplicitSystem::matrix, std::max(), mesh, Elem::n_sides(), Elem::neighbor(), FEMSystem::numerical_elem_jacobian(), FEMSystem::numerical_side_jacobian(), DifferentiableSystem::print_element_jacobians, DifferentiableSystem::print_jacobian_norms, DifferentiableSystem::print_jacobians, DifferentiableSystem::print_residual_norms, DifferentiableSystem::print_residuals, DifferentiableSystem::print_solution_norms, DifferentiableSystem::print_solutions, FEMContext::reinit(), ExplicitSystem::rhs, FEMContext::side, System::solution, DenseMatrix< T >::swap(), DifferentiableSystem::time_solver, System::update(), and FEMSystem::verify_analytic_jacobians.
Referenced by continuation_solve(), and solve_tangent().
00079 { 00080 libmesh_assert(get_residual || get_jacobian); 00081 std::string log_name; 00082 if (get_residual && get_jacobian) 00083 log_name = "assembly()"; 00084 else if (get_residual) 00085 log_name = "assembly(get_residual)"; 00086 else 00087 log_name = "assembly(get_jacobian)"; 00088 00089 START_LOG(log_name, "FEMSystem"); 00090 00091 const MeshBase& mesh = this->get_mesh(); 00092 00093 // this->get_vector("_nonlinear_solution").localize 00094 // (*current_local_nonlinear_solution, 00095 // dof_map.get_send_list()); 00096 this->update(); 00097 00098 if (print_solution_norms) 00099 { 00100 // this->get_vector("_nonlinear_solution").close(); 00101 this->solution->close(); 00102 std::cout << "|U| = " 00103 // << this->get_vector("_nonlinear_solution").l1_norm() 00104 << this->solution->l1_norm() 00105 << std::endl; 00106 } 00107 if (print_solutions) 00108 { 00109 unsigned int old_precision = std::cout.precision(); 00110 std::cout.precision(16); 00111 // std::cout << "U = [" << this->get_vector("_nonlinear_solution") 00112 std::cout << "U = [" << *(this->solution) 00113 << "];" << std::endl; 00114 std::cout.precision(old_precision); 00115 } 00116 00117 // Is this definitely necessary? [RHS] 00118 if (get_jacobian) 00119 matrix->zero(); 00120 if (get_residual) 00121 rhs->zero(); 00122 00123 // Stupid C++ lets you set *Real* verify_analytic_jacobians = true! 00124 if (verify_analytic_jacobians > 0.5) 00125 { 00126 std::cerr << "WARNING! verify_analytic_jacobians was set " 00127 << "to absurdly large value of " 00128 << verify_analytic_jacobians << std::endl; 00129 std::cerr << "Resetting to 1e-6!" << std::endl; 00130 verify_analytic_jacobians = 1e-6; 00131 } 00132 00133 // In time-dependent problems, the nonlinear function we're trying 00134 // to solve at each timestep may depend on the particular solver 00135 // we're using 00136 libmesh_assert (time_solver.get() != NULL); 00137 00138 AutoPtr<DiffContext> con = this->build_context(); 00139 FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con); 00140 00141 // Build the residual and jacobian contributions on every active 00142 // mesh element on this processor 00143 MeshBase::const_element_iterator el = 00144 mesh.active_local_elements_begin(); 00145 const MeshBase::const_element_iterator end_el = 00146 mesh.active_local_elements_end(); 00147 00148 for ( ; el != end_el; ++el) 00149 { 00150 _femcontext.reinit(*this, *el); 00151 00152 bool jacobian_computed = 00153 time_solver->element_residual(get_jacobian, _femcontext); 00154 00155 // Compute a numeric jacobian if we have to 00156 if (get_jacobian && !jacobian_computed) 00157 { 00158 // Make sure we didn't compute a jacobian and lie about it 00159 libmesh_assert(_femcontext.elem_jacobian.l1_norm() == 0.0); 00160 // Logging of numerical jacobians is done separately 00161 this->numerical_elem_jacobian(_femcontext); 00162 } 00163 00164 // Compute a numeric jacobian if we're asked to verify the 00165 // analytic jacobian we got 00166 if (get_jacobian && jacobian_computed && 00167 verify_analytic_jacobians != 0.0) 00168 { 00169 DenseMatrix<Number> analytic_jacobian(_femcontext.elem_jacobian); 00170 00171 _femcontext.elem_jacobian.zero(); 00172 // Logging of numerical jacobians is done separately 00173 this->numerical_elem_jacobian(_femcontext); 00174 00175 Real analytic_norm = analytic_jacobian.l1_norm(); 00176 Real numerical_norm = _femcontext.elem_jacobian.l1_norm(); 00177 00178 // If we can continue, we'll probably prefer the analytic jacobian 00179 analytic_jacobian.swap(_femcontext.elem_jacobian); 00180 00181 // The matrix "analytic_jacobian" will now hold the error matrix 00182 analytic_jacobian.add(-1.0, _femcontext.elem_jacobian); 00183 Real error_norm = analytic_jacobian.l1_norm(); 00184 00185 Real relative_error = error_norm / 00186 std::max(analytic_norm, numerical_norm); 00187 00188 if (relative_error > verify_analytic_jacobians) 00189 { 00190 std::cerr << "Relative error " << relative_error 00191 << " detected in analytic jacobian on element " 00192 << _femcontext.elem->id() << '!' << std::endl; 00193 00194 unsigned int old_precision = std::cout.precision(); 00195 std::cout.precision(16); 00196 std::cout << "J_analytic " << _femcontext.elem->id() << " = " 00197 << _femcontext.elem_jacobian << std::endl; 00198 analytic_jacobian.add(1.0, _femcontext.elem_jacobian); 00199 std::cout << "J_numeric " << _femcontext.elem->id() << " = " 00200 << analytic_jacobian << std::endl; 00201 00202 std::cout.precision(old_precision); 00203 00204 libmesh_error(); 00205 } 00206 } 00207 00208 for (_femcontext.side = 0; 00209 _femcontext.side != _femcontext.elem->n_sides(); 00210 ++_femcontext.side) 00211 { 00212 // Don't compute on non-boundary sides unless requested 00213 if (!compute_internal_sides && 00214 _femcontext.elem->neighbor(_femcontext.side) != NULL) 00215 continue; 00216 00217 // Any mesh movement has already been done (and restored, 00218 // if the TimeSolver isn't broken), but 00219 // reinitializing the side FE objects is still necessary 00220 _femcontext.elem_side_fe_reinit(); 00221 00222 DenseMatrix<Number> old_jacobian; 00223 // If we're in DEBUG mode, we should always verify that the 00224 // user's side_residual function doesn't alter our existing 00225 // jacobian and then lie about it 00226 #ifndef DEBUG 00227 // Even if we're not in DEBUG mode, when we're verifying 00228 // analytic jacobians we'll want to verify each side's 00229 // jacobian contribution separately 00230 if (verify_analytic_jacobians != 0.0 && get_jacobian) 00231 #endif // ifndef DEBUG 00232 { 00233 old_jacobian = _femcontext.elem_jacobian; 00234 _femcontext.elem_jacobian.zero(); 00235 } 00236 jacobian_computed = 00237 time_solver->side_residual(get_jacobian, _femcontext); 00238 00239 // Compute a numeric jacobian if we have to 00240 if (get_jacobian && !jacobian_computed) 00241 { 00242 // In DEBUG mode, we've already set elem_jacobian == 0, 00243 // so we can make sure side_residual didn't compute a 00244 // jacobian and lie about it 00245 #ifdef DEBUG 00246 libmesh_assert(_femcontext.elem_jacobian.l1_norm() == 0.0); 00247 #endif 00248 // Logging of numerical jacobians is done separately 00249 this->numerical_side_jacobian(_femcontext); 00250 00251 // If we're in DEBUG mode or if 00252 // verify_analytic_jacobians is on, we've moved 00253 // elem_jacobian's accumulated values into old_jacobian. 00254 // Now let's add them back. 00255 #ifndef DEBUG 00256 if (verify_analytic_jacobians != 0.0) 00257 #endif // ifndef DEBUG 00258 _femcontext.elem_jacobian += old_jacobian; 00259 } 00260 00261 // Compute a numeric jacobian if we're asked to verify the 00262 // analytic jacobian we got 00263 if (get_jacobian && jacobian_computed && 00264 verify_analytic_jacobians != 0.0) 00265 { 00266 DenseMatrix<Number> analytic_jacobian(_femcontext.elem_jacobian); 00267 00268 _femcontext.elem_jacobian.zero(); 00269 // Logging of numerical jacobians is done separately 00270 this->numerical_side_jacobian(_femcontext); 00271 00272 Real analytic_norm = analytic_jacobian.l1_norm(); 00273 Real numerical_norm = _femcontext.elem_jacobian.l1_norm(); 00274 00275 // If we can continue, we'll probably prefer the analytic jacobian 00276 analytic_jacobian.swap(_femcontext.elem_jacobian); 00277 00278 // The matrix "analytic_jacobian" will now hold the error matrix 00279 analytic_jacobian.add(-1.0, _femcontext.elem_jacobian); 00280 Real error_norm = analytic_jacobian.l1_norm(); 00281 00282 Real relative_error = error_norm / 00283 std::max(analytic_norm, numerical_norm); 00284 00285 if (relative_error > verify_analytic_jacobians) 00286 { 00287 std::cerr << "Relative error " << relative_error 00288 << " detected in analytic jacobian on element " 00289 << _femcontext.elem->id() 00290 << ", side " 00291 << _femcontext.side << '!' << std::endl; 00292 00293 unsigned int old_precision = std::cout.precision(); 00294 std::cout.precision(16); 00295 std::cout << "J_analytic " << _femcontext.elem->id() << " = " 00296 << _femcontext.elem_jacobian << std::endl; 00297 analytic_jacobian.add(1.0, _femcontext.elem_jacobian); 00298 std::cout << "J_numeric " << _femcontext.elem->id() << " = " 00299 << analytic_jacobian << std::endl; 00300 std::cout.precision(old_precision); 00301 00302 libmesh_error(); 00303 } 00304 // Once we've verified a side, we'll want to add back the 00305 // rest of the accumulated jacobian 00306 _femcontext.elem_jacobian += old_jacobian; 00307 } 00308 // In DEBUG mode, we've set elem_jacobian == 0, and we 00309 // may still need to add the old jacobian back 00310 #ifdef DEBUG 00311 if (get_jacobian && jacobian_computed && 00312 verify_analytic_jacobians == 0.0) 00313 { 00314 _femcontext.elem_jacobian += old_jacobian; 00315 } 00316 #endif // ifdef DEBUG 00317 } 00318 00319 #ifdef LIBMESH_ENABLE_AMR 00320 // We turn off the asymmetric constraint application; 00321 // enforce_constraints_exactly() should be called in the solver 00322 if (get_residual && get_jacobian) 00323 this->get_dof_map().constrain_element_matrix_and_vector 00324 (_femcontext.elem_jacobian, _femcontext.elem_residual, 00325 _femcontext.dof_indices, false); 00326 else if (get_residual) 00327 this->get_dof_map().constrain_element_vector 00328 (_femcontext.elem_residual, _femcontext.dof_indices, false); 00329 else if (get_jacobian) 00330 this->get_dof_map().constrain_element_matrix 00331 (_femcontext.elem_jacobian, _femcontext.dof_indices, false); 00332 #endif // #ifdef LIBMESH_ENABLE_AMR 00333 00334 if (get_jacobian && print_element_jacobians) 00335 { 00336 unsigned int old_precision = std::cout.precision(); 00337 std::cout.precision(16); 00338 std::cout << "J_elem " << _femcontext.elem->id() << " = " 00339 << _femcontext.elem_jacobian << std::endl; 00340 std::cout.precision(old_precision); 00341 } 00342 00343 if (get_jacobian) 00344 this->matrix->add_matrix (_femcontext.elem_jacobian, 00345 _femcontext.dof_indices); 00346 if (get_residual) 00347 this->rhs->add_vector (_femcontext.elem_residual, 00348 _femcontext.dof_indices); 00349 } 00350 00351 00352 if (get_residual && print_residual_norms) 00353 { 00354 this->rhs->close(); 00355 std::cout << "|F| = " << this->rhs->l1_norm() << std::endl; 00356 } 00357 if (get_residual && print_residuals) 00358 { 00359 this->rhs->close(); 00360 unsigned int old_precision = std::cout.precision(); 00361 std::cout.precision(16); 00362 std::cout << "F = [" << *(this->rhs) << "];" << std::endl; 00363 std::cout.precision(old_precision); 00364 } 00365 if (get_jacobian && print_jacobian_norms) 00366 { 00367 this->matrix->close(); 00368 std::cout << "|J| = " << this->matrix->l1_norm() << std::endl; 00369 } 00370 if (get_jacobian && print_jacobians) 00371 { 00372 this->matrix->close(); 00373 unsigned int old_precision = std::cout.precision(); 00374 std::cout.precision(16); 00375 std::cout << "J = [" << *(this->matrix) << "];" << std::endl; 00376 std::cout.precision(old_precision); 00377 } 00378 STOP_LOG(log_name, "FEMSystem"); 00379 }
| void System::attach_assemble_function | ( | void | fptrEquationSystems &es,const std::string &name | ) | [inherited] |
Register a user function to use in assembling the system matrix and RHS.
Definition at line 1316 of file system.C.
References System::_assemble_system.
01318 { 01319 libmesh_assert (fptr != NULL); 01320 01321 _assemble_system = fptr; 01322 }
| void System::attach_constraint_function | ( | void | fptrEquationSystems &es,const std::string &name | ) | [inherited] |
Register a user function for imposing constraints.
Definition at line 1326 of file system.C.
References System::_constrain_system.
01328 { 01329 libmesh_assert (fptr != NULL); 01330 01331 _constrain_system = fptr; 01332 }
| void System::attach_init_function | ( | void | fptrEquationSystems &es,const std::string &name | ) | [inherited] |
Register a user function to use in initializing the system.
Definition at line 1306 of file system.C.
References System::_init_system.
01308 { 01309 libmesh_assert (fptr != NULL); 01310 01311 _init_system = fptr; 01312 }
| void System::attach_QOI_derivative | ( | void | fptrEquationSystems &es, const std::string &name, const QoISet &qoi_indices | ) | [inherited] |
Register a user function for evaluating derivatives of a quantity of interest with respect to test functions, whose values should be placed in System::rhs
| void System::attach_QOI_function | ( | void | fptrEquationSystems &es, const std::string &name, const QoISet &qoi_indices | ) | [inherited] |
Register a user function for evaluating the quantities of interest, whose values should be placed in System::qoi
| AutoPtr< DiffContext > FEMSystem::build_context | ( | ) | [virtual, inherited] |
Builds a FEMContext object with enough information to do evaluations on each element.
For most problems, the default FEMSystem implementation is correct; users who subclass FEMContext will need to also reimplement this method to build it.
Reimplemented from DifferentiableSystem.
Definition at line 742 of file fem_system.C.
Referenced by FEMSystem::assemble_qoi(), FEMSystem::assemble_qoi_derivative(), FEMSystem::assembly(), FEMSystem::mesh_position_get(), FEMSystem::mesh_position_set(), and FEMSystem::postprocess().
00743 { 00744 return AutoPtr<DiffContext>(new FEMContext(*this)); 00745 }
| Real System::calculate_norm | ( | NumericVector< Number > & | v, | |
| const SystemNorm & | norm | |||
| ) | const [inherited] |
- Returns:
- a norm of the vector
v, usingcomponent_normandcomponent_scaleto choose and weight the norms of each variable.
Definition at line 1077 of file system.C.
References System::_dof_map, MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), TypeTensor< T >::add_scaled(), TypeVector< T >::add_scaled(), FEBase::build(), FEType::default_quadrature_rule(), dim, libMeshEnums::DISCRETE_L1, libMeshEnums::DISCRETE_L2, libMeshEnums::DISCRETE_L_INF, System::discrete_var_norm(), DofMap::dof_indices(), AutoPtr< Tp >::get(), System::get_dof_map(), System::get_mesh(), libMeshEnums::H1, libMeshEnums::H1_SEMINORM, libMeshEnums::H2, libMeshEnums::H2_SEMINORM, SystemNorm::is_discrete(), NumericVector< T >::l1_norm(), libMeshEnums::L2, NumericVector< T >::l2_norm(), libmesh_norm(), NumericVector< T >::linfty_norm(), NumericVector< T >::localize(), MeshBase::mesh_dimension(), System::n_vars(), libMeshEnums::SERIAL, NumericVector< T >::size(), TypeTensor< T >::size_sq(), TypeVector< T >::size_sq(), SystemNorm::type(), DofMap::variable_type(), SystemNorm::weight(), and SystemNorm::weight_sq().
01079 { 01080 // This function must be run on all processors at once 01081 parallel_only(); 01082 01083 START_LOG ("calculate_norm()", "System"); 01084 01085 // Zero the norm before summation 01086 Real v_norm = 0.; 01087 01088 if (norm.is_discrete()) 01089 { 01090 STOP_LOG ("calculate_norm()", "System"); 01091 //Check to see if all weights are 1.0 01092 unsigned int check_var = 0; 01093 for (; check_var != this->n_vars(); ++check_var) 01094 if(norm.weight(check_var) != 1.0) 01095 break; 01096 01097 //All weights were 1.0 so just do the full vector discrete norm 01098 if(check_var == this->n_vars()) 01099 { 01100 FEMNormType norm_type = norm.type(0); 01101 01102 if(norm_type == DISCRETE_L1) 01103 return v.l1_norm(); 01104 if(norm_type == DISCRETE_L2) 01105 return v.l2_norm(); 01106 if(norm_type == DISCRETE_L_INF) 01107 return v.linfty_norm(); 01108 else 01109 libmesh_error(); 01110 } 01111 01112 for (unsigned int var=0; var != this->n_vars(); ++var) 01113 { 01114 // Skip any variables we don't need to integrate 01115 if (norm.weight(var) == 0.0) 01116 continue; 01117 01118 v_norm += norm.weight(var) * discrete_var_norm(v, var, norm.type(var)); 01119 } 01120 01121 return v_norm; 01122 } 01123 01124 // Localize the potentially parallel vector 01125 AutoPtr<NumericVector<Number> > local_v = NumericVector<Number>::build(); 01126 local_v->init(v.size(), true, SERIAL); 01127 v.localize (*local_v, _dof_map->get_send_list()); 01128 01129 unsigned int dim = this->get_mesh().mesh_dimension(); 01130 01131 // Loop over all variables 01132 for (unsigned int var=0; var != this->n_vars(); ++var) 01133 { 01134 // Skip any variables we don't need to integrate 01135 if (norm.weight(var) == 0.0) 01136 continue; 01137 01138 const FEType& fe_type = this->get_dof_map().variable_type(var); 01139 AutoPtr<QBase> qrule = 01140 fe_type.default_quadrature_rule (dim); 01141 AutoPtr<FEBase> fe 01142 (FEBase::build(dim, fe_type)); 01143 fe->attach_quadrature_rule (qrule.get()); 01144 01145 const std::vector<Real>& JxW = fe->get_JxW(); 01146 const std::vector<std::vector<Real> >* phi = NULL; 01147 if (norm.type(var) == H1 || 01148 norm.type(var) == H2 || 01149 norm.type(var) == L2) 01150 phi = &(fe->get_phi()); 01151 01152 const std::vector<std::vector<RealGradient> >* dphi = NULL; 01153 if (norm.type(var) == H1 || 01154 norm.type(var) == H2 || 01155 norm.type(var) == H1_SEMINORM) 01156 dphi = &(fe->get_dphi()); 01157 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01158 const std::vector<std::vector<RealTensor> >* d2phi = NULL; 01159 if (norm.type(var) == H2 || 01160 norm.type(var) == H2_SEMINORM) 01161 d2phi = &(fe->get_d2phi()); 01162 #endif 01163 01164 std::vector<unsigned int> dof_indices; 01165 01166 // Begin the loop over the elements 01167 MeshBase::const_element_iterator el = 01168 this->get_mesh().active_local_elements_begin(); 01169 const MeshBase::const_element_iterator end_el = 01170 this->get_mesh().active_local_elements_end(); 01171 01172 for ( ; el != end_el; ++el) 01173 { 01174 const Elem* elem = *el; 01175 01176 fe->reinit (elem); 01177 01178 this->get_dof_map().dof_indices (elem, dof_indices, var); 01179 01180 const unsigned int n_qp = qrule->n_points(); 01181 01182 const unsigned int n_sf = dof_indices.size(); 01183 01184 // Begin the loop over the Quadrature points. 01185 for (unsigned int qp=0; qp<n_qp; qp++) 01186 { 01187 if (norm.type(var) == H1 || 01188 norm.type(var) == H2 || 01189 norm.type(var) == L2) 01190 { 01191 Number u_h = 0.; 01192 for (unsigned int i=0; i != n_sf; ++i) 01193 u_h += (*phi)[i][qp] * (*local_v)(dof_indices[i]); 01194 v_norm += norm.weight_sq(var) * 01195 JxW[qp] * libmesh_norm(u_h); 01196 } 01197 01198 if (norm.type(var) == H1 || 01199 norm.type(var) == H2 || 01200 norm.type(var) == H1_SEMINORM) 01201 { 01202 Gradient grad_u_h; 01203 for (unsigned int i=0; i != n_sf; ++i) 01204 grad_u_h.add_scaled((*dphi)[i][qp], (*local_v)(dof_indices[i])); 01205 v_norm += norm.weight_sq(var) * 01206 JxW[qp] * grad_u_h.size_sq(); 01207 } 01208 01209 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01210 if (norm.type(var) == H2 || 01211 norm.type(var) == H2_SEMINORM) 01212 { 01213 Tensor hess_u_h; 01214 for (unsigned int i=0; i != n_sf; ++i) 01215 hess_u_h.add_scaled((*d2phi)[i][qp], (*local_v)(dof_indices[i])); 01216 v_norm += norm.weight_sq(var) * 01217 JxW[qp] * hess_u_h.size_sq(); 01218 } 01219 #endif 01220 } 01221 } 01222 } 01223 01224 Parallel::sum(v_norm); 01225 01226 STOP_LOG ("calculate_norm()", "System"); 01227 01228 return std::sqrt(v_norm); 01229 }
| Real System::calculate_norm | ( | NumericVector< Number > & | v, | |
| unsigned int | var = 0, |
|||
| FEMNormType | norm_type = L2 | |||
| ) | const [inherited] |
- Returns:
- a norm of variable
varin the vectorv, in the specified norm (e.g. L2, H0, H1)
Definition at line 1056 of file system.C.
References libMeshEnums::DISCRETE_L1, libMeshEnums::DISCRETE_L2, libMeshEnums::DISCRETE_L_INF, System::discrete_var_norm(), libMeshEnums::L2, and System::n_vars().
Referenced by AdaptiveTimeSolver::calculate_norm(), and UnsteadySolver::du().
01059 { 01060 //short circuit to save time 01061 if(norm_type == DISCRETE_L1 || 01062 norm_type == DISCRETE_L2 || 01063 norm_type == DISCRETE_L_INF) 01064 return discrete_var_norm(v,var,norm_type); 01065 01066 // Not a discrete norm 01067 std::vector<FEMNormType> norms(this->n_vars(), L2); 01068 std::vector<Real> weights(this->n_vars(), 0.0); 01069 norms[var] = norm_type; 01070 weights[var] = 1.0; 01071 Real val = this->calculate_norm(v, SystemNorm(norms, weights)); 01072 return val; 01073 }
| void ContinuationSystem::clear | ( | ) | [virtual] |
Clear all the data structures associated with the system.
Reimplemented from FEMSystem.
Definition at line 74 of file continuation_system.C.
References FEMSystem::clear().
Referenced by ~ContinuationSystem().
00075 { 00076 // FIXME: Do anything here, e.g. zero vectors, etc? 00077 00078 // Call the Parent's clear function 00079 Parent::clear(); 00080 }
| bool System::compare | ( | const System & | other_system, | |
| const Real | threshold, | |||
| const bool | verbose | |||
| ) | const [virtual, inherited] |
- Returns:
truewhen the other system contains identical data, up to the given threshold. Outputs some diagnostic info whenverboseis set.
Definition at line 399 of file system.C.
References System::_can_add_vectors, System::_sys_name, System::_vectors, System::get_vector(), System::n_vectors(), System::name(), and System::solution.
Referenced by EquationSystems::compare().
00402 { 00403 // we do not care for matrices, but for vectors 00404 libmesh_assert (!_can_add_vectors); 00405 libmesh_assert (!other_system._can_add_vectors); 00406 00407 if (verbose) 00408 { 00409 std::cout << " Systems \"" << _sys_name << "\"" << std::endl; 00410 std::cout << " comparing matrices not supported." << std::endl; 00411 std::cout << " comparing names..."; 00412 } 00413 00414 // compare the name: 0 means identical 00415 const int name_result = _sys_name.compare(other_system.name()); 00416 if (verbose) 00417 { 00418 if (name_result == 0) 00419 std::cout << " identical." << std::endl; 00420 else 00421 std::cout << " names not identical." << std::endl; 00422 std::cout << " comparing solution vector..."; 00423 } 00424 00425 00426 // compare the solution: -1 means identical 00427 const int solu_result = solution->compare (*other_system.solution.get(), 00428 threshold); 00429 00430 if (verbose) 00431 { 00432 if (solu_result == -1) 00433 std::cout << " identical up to threshold." << std::endl; 00434 else 00435 std::cout << " first difference occured at index = " 00436 << solu_result << "." << std::endl; 00437 } 00438 00439 00440 // safety check, whether we handle at least the same number 00441 // of vectors 00442 std::vector<int> ov_result; 00443 00444 if (this->n_vectors() != other_system.n_vectors()) 00445 { 00446 if (verbose) 00447 { 00448 std::cout << " Fatal difference. This system handles " 00449 << this->n_vectors() << " add'l vectors," << std::endl 00450 << " while the other system handles " 00451 << other_system.n_vectors() 00452 << " add'l vectors." << std::endl 00453 << " Aborting comparison." << std::endl; 00454 } 00455 return false; 00456 } 00457 else if (this->n_vectors() == 0) 00458 { 00459 // there are no additional vectors... 00460 ov_result.clear (); 00461 } 00462 else 00463 { 00464 // compare other vectors 00465 for (const_vectors_iterator pos = _vectors.begin(); 00466 pos != _vectors.end(); ++pos) 00467 { 00468 if (verbose) 00469 std::cout << " comparing vector \"" 00470 << pos->first << "\" ..."; 00471 00472 // assume they have the same name 00473 const NumericVector<Number>& other_system_vector = 00474 other_system.get_vector(pos->first); 00475 00476 ov_result.push_back(pos->second->compare (other_system_vector, 00477 threshold)); 00478 00479 if (verbose) 00480 { 00481 if (ov_result[ov_result.size()-1] == -1) 00482 std::cout << " identical up to threshold." << std::endl; 00483 else 00484 std::cout << " first difference occured at" << std::endl 00485 << " index = " << ov_result[ov_result.size()-1] << "." << std::endl; 00486 } 00487 00488 } 00489 00490 } // finished comparing additional vectors 00491 00492 00493 bool overall_result; 00494 00495 // sum up the results 00496 if ((name_result==0) && (solu_result==-1)) 00497 { 00498 if (ov_result.size()==0) 00499 overall_result = true; 00500 else 00501 { 00502 bool ov_identical; 00503 unsigned int n = 0; 00504 do 00505 { 00506 ov_identical = (ov_result[n]==-1); 00507 n++; 00508 } 00509 while (ov_identical && n<ov_result.size()); 00510 overall_result = ov_identical; 00511 } 00512 } 00513 else 00514 overall_result = false; 00515 00516 if (verbose) 00517 { 00518 std::cout << " finished comparisons, "; 00519 if (overall_result) 00520 std::cout << "found no differences." << std::endl << std::endl; 00521 else 00522 std::cout << "found differences." << std::endl << std::endl; 00523 } 00524 00525 return overall_result; 00526 }
| void ContinuationSystem::continuation_solve | ( | ) |
Perform a continuation solve of the system. In general, you can only begin the continuation solves after either reading in or solving for two previous values of the control parameter. The prior two solutions are required for starting up the continuation method.
Definition at line 352 of file continuation_system.C.
References apply_predictor(), FEMSystem::assembly(), continuation_parameter, continuation_parameter_tolerance, delta_u, dlambda_ds, ds_current, du_ds, G_Lambda, AutoPtr< Tp >::get(), initial_newton_tolerance, initialize_tangent(), libmesh_real(), linear_solver, ImplicitSystem::matrix, max_continuation_parameter, DiffSolver::max_linear_iterations, DiffSolver::max_nonlinear_iterations, std::min(), min_continuation_parameter, n_arclength_reductions, n_backtrack_steps, newton_progress_check, newton_solver, newton_step, old_continuation_parameter, Utility::pow(), previous_u, quiet, Residual, ExplicitSystem::rhs, rhs_mode, System::solution, solution_tolerance, tangent_initialized, Theta, Theta_LOCA, DifferentiableSystem::time_solver, y, y_old, and z.
00353 { 00354 // Be sure the user has set the continuation parameter pointer 00355 if (!continuation_parameter) 00356 { 00357 std::cerr << "You must set the continuation_parameter pointer " 00358 << "to a member variable of the derived class, preferably in the " 00359 << "Derived class's init_data function. This is how the ContinuationSystem " 00360 << "updates the continuation parameter." 00361 << std::endl; 00362 00363 libmesh_error(); 00364 } 00365 00366 // Use extra precision for all the numbers printed in this function. 00367 unsigned int old_precision = std::cout.precision(); 00368 std::cout.precision(16); 00369 std::cout.setf(std::ios_base::scientific); 00370 00371 // We can't start solving the augmented PDE system unless the tangent 00372 // vectors have been initialized. This only needs to occur once. 00373 if (!tangent_initialized) 00374 initialize_tangent(); 00375 00376 // Save the old value of -du/dlambda. This will be used after the Newton iterations 00377 // to compute the angle between previous tangent vectors. This cosine of this angle is 00378 // 00379 // tau := abs( (du/d(lambda)_i , du/d(lambda)_{i-1}) / (||du/d(lambda)_i|| * ||du/d(lambda)_{i-1}||) ) 00380 // 00381 // The scaling factor tau (which should vary between 0 and 1) is used to shrink the step-size ds 00382 // when we are approaching a turning point. Note that it can only shrink the step size. 00383 *y_old = *y; 00384 00385 // Set pointer to underlying Newton solver 00386 if (!newton_solver) 00387 newton_solver = libmesh_cast_ptr<NewtonSolver*> (this->time_solver->diff_solver().get()); 00388 00389 // A pair for catching return values from linear system solves. 00390 std::pair<unsigned int, Real> rval; 00391 00392 // Convergence flag for the entire arcstep 00393 bool arcstep_converged = false; 00394 00395 // Begin loop over arcstep reductions. 00396 for (unsigned int ns=0; ns<n_arclength_reductions; ++ns) 00397 { 00398 if (!quiet) 00399 { 00400 std::cout << "Current arclength stepsize, ds_current=" << ds_current << std::endl; 00401 std::cout << "Current parameter value, lambda=" << *continuation_parameter << std::endl; 00402 } 00403 00404 // Upon exit from the nonlinear loop, the newton_converged flag 00405 // will tell us the convergence status of Newton's method. 00406 bool newton_converged = false; 00407 00408 // The nonlinear residual before *any* nonlinear steps have been taken. 00409 Real nonlinear_residual_firststep = 0.; 00410 00411 // The nonlinear residual from the current "k" Newton step, before the Newton step 00412 Real nonlinear_residual_beforestep = 0.; 00413 00414 // The nonlinear residual from the current "k" Newton step, after the Newton step 00415 Real nonlinear_residual_afterstep = 0.; 00416 00417 // The linear solver tolerance, can be updated dynamically at each Newton step. 00418 Real current_linear_tolerance = 0.; 00419 00420 // The nonlinear loop 00421 for (newton_step=0; newton_step<newton_solver->max_nonlinear_iterations; ++newton_step) 00422 { 00423 std::cout << "\n === Starting Newton step " << newton_step << " ===" << std::endl; 00424 00425 // Set the linear system solver tolerance 00426 // // 1.) Set the current linear tolerance based as a multiple of the current residual of the system. 00427 // const Real residual_multiple = 1.e-4; 00428 // Real current_linear_tolerance = residual_multiple*nonlinear_residual_beforestep; 00429 00430 // // But if the current residual isn't small, don't let the solver exit with zero iterations! 00431 // if (current_linear_tolerance > 1.) 00432 // current_linear_tolerance = residual_multiple; 00433 00434 // 2.) Set the current linear tolerance based on the method based on technique of Eisenstat & Walker. 00435 if (newton_step==0) 00436 { 00437 // At first step, only try reducing the residual by a small amount 00438 current_linear_tolerance = initial_newton_tolerance;//0.01; 00439 } 00440 00441 else 00442 { 00443 // The new tolerance is based on the ratio of the most recent tolerances 00444 const Real alp=0.5*(1.+std::sqrt(5.)); 00445 const Real gam=0.9; 00446 00447 libmesh_assert (nonlinear_residual_beforestep != 0.0); 00448 libmesh_assert (nonlinear_residual_afterstep != 0.0); 00449 00450 current_linear_tolerance = std::min(gam*std::pow(nonlinear_residual_afterstep/nonlinear_residual_beforestep, alp), 00451 current_linear_tolerance*current_linear_tolerance 00452 ); 00453 00454 // Don't let it get ridiculously small!! 00455 if (current_linear_tolerance < 1.e-12) 00456 current_linear_tolerance = 1.e-12; 00457 } 00458 00459 if (!quiet) 00460 std::cout << "Using current_linear_tolerance=" << current_linear_tolerance << std::endl; 00461 00462 00463 // Assemble the residual (and Jacobian). 00464 rhs_mode = Residual; 00465 assembly(true, // Residual 00466 true); // Jacobian 00467 rhs->close(); 00468 00469 // Save the current nonlinear residual. We don't need to recompute the residual unless 00470 // this is the first step, since it was already computed as part of the convergence check 00471 // at the end of the last loop iteration. 00472 if (newton_step==0) 00473 { 00474 nonlinear_residual_beforestep = rhs->l2_norm(); 00475 00476 // Store the residual before any steps have been taken. This will *not* 00477 // be updated at each step, and can be used to see if any progress has 00478 // been made from the initial residual at later steps. 00479 nonlinear_residual_firststep = nonlinear_residual_beforestep; 00480 00481 const Real old_norm_u = solution->l2_norm(); 00482 std::cout << " (before step) ||R||_{L2} = " << nonlinear_residual_beforestep << std::endl; 00483 std::cout << " (before step) ||R||_{L2}/||u|| = " << nonlinear_residual_beforestep / old_norm_u << std::endl; 00484 00485 // In rare cases (very small arcsteps), it's possible that the residual is 00486 // already below our absolute linear tolerance. 00487 if (nonlinear_residual_beforestep < solution_tolerance) 00488 { 00489 if (!quiet) 00490 std::cout << "Initial guess satisfied linear tolerance, exiting with zero Newton iterations!" << std::endl; 00491 00492 // Since we go straight from here to the solve of the next tangent, we 00493 // have to close the matrix before it can be assembled again. 00494 matrix->close(); 00495 newton_converged=true; 00496 break; // out of Newton iterations, with newton_converged=true 00497 } 00498 } 00499 00500 else 00501 { 00502 nonlinear_residual_beforestep = nonlinear_residual_afterstep; 00503 } 00504 00505 00506 // Solve the linear system G_u*z = G 00507 // Initial guess? 00508 z->zero(); // It seems to be extremely important to zero z here, otherwise the solver quits early. 00509 z->close(); 00510 00511 // It's possible that we have selected the current_linear_tolerance so large that 00512 // a guess of z=zero yields a linear system residual |Az + R| small enough that the 00513 // linear solver exits in zero iterations. If this happens, we will reduce the 00514 // current_linear_tolerance until the linear solver does at least 1 iteration. 00515 do 00516 { 00517 rval = 00518 linear_solver->solve(*matrix, 00519 *z, 00520 *rhs, 00521 //1.e-12, 00522 current_linear_tolerance, 00523 newton_solver->max_linear_iterations); // max linear iterations 00524 00525 if (rval.first==0) 00526 { 00527 if (newton_step==0) 00528 { 00529 std::cout << "Repeating initial solve with smaller linear tolerance!" << std::endl; 00530 current_linear_tolerance *= initial_newton_tolerance; // reduce the linear tolerance to force the solver to do some work 00531 } 00532 else 00533 { 00534 // We shouldn't get here ... it means the linear solver did no work on a Newton 00535 // step other than the first one. If this happens, we need to think more about our 00536 // tolerance selection. 00537 libmesh_error(); 00538 } 00539 } 00540 00541 } while (rval.first==0); 00542 00543 00544 if (!quiet) 00545 std::cout << " G_u*z = G solver converged at step " 00546 << rval.first 00547 << " linear tolerance = " 00548 << rval.second 00549 << "." 00550 << std::endl; 00551 00552 // Sometimes (I am not sure why) the linear solver exits after zero iterations. 00553 // Perhaps it is hitting PETSc's divergence tolerance dtol??? If this occurs, 00554 // we should break out of the Newton iteration loop because nothing further is 00555 // going to happen... Of course if the tolerance is already small enough after 00556 // zero iterations (how can this happen?!) we should not quit. 00557 if ((rval.first == 0) && (rval.second > current_linear_tolerance*nonlinear_residual_beforestep)) 00558 { 00559 if (!quiet) 00560 std::cout << "Linear solver exited in zero iterations!" << std::endl; 00561 00562 // Try to find out the reason for convergence/divergence 00563 linear_solver->print_converged_reason(); 00564 00565 break; // out of Newton iterations 00566 } 00567 00568 // Note: need to scale z by -1 since our code always solves Jx=R 00569 // instead of Jx=-R. 00570 z->scale(-1.); 00571 z->close(); 00572 00573 00574 00575 00576 00577 00578 // Assemble the G_Lambda vector, skip residual. 00579 rhs_mode = G_Lambda; 00580 00581 // Assemble both rhs and Jacobian 00582 assembly(true, // Residual 00583 false); // Jacobian 00584 00585 // Not sure if this is really necessary 00586 rhs->close(); 00587 const Real yrhsnorm=rhs->l2_norm(); 00588 if (yrhsnorm == 0.0) 00589 { 00590 std::cout << "||G_Lambda|| = 0" << std::endl; 00591 libmesh_error(); 00592 } 00593 00594 // We select a tolerance for the y-system which is based on the inexact Newton 00595 // tolerance but scaled by an extra term proportional to the RHS (which is not -> 0 in this case) 00596 const Real ysystemtol=current_linear_tolerance*(nonlinear_residual_beforestep/yrhsnorm); 00597 if (!quiet) 00598 std::cout << "ysystemtol=" << ysystemtol << std::endl; 00599 00600 // Solve G_u*y = G_{\lambda} 00601 // FIXME: Initial guess? This is really a solve for -du/dlambda so we could try 00602 // initializing it with the latest approximation to that... du/dlambda ~ du/ds * ds/dlambda 00603 //*y = *solution; 00604 //y->add(-1., *previous_u); 00605 //y->scale(-1. / (*continuation_parameter - old_continuation_parameter)); // Be careful of divide by zero... 00606 //y->close(); 00607 00608 // const unsigned int max_attempts=1; 00609 // unsigned int attempt=0; 00610 // do 00611 // { 00612 // if (!quiet) 00613 // std::cout << "Trying to solve tangent system, attempt " << attempt << std::endl; 00614 00615 rval = 00616 linear_solver->solve(*matrix, 00617 *y, 00618 *rhs, 00619 //1.e-12, 00620 ysystemtol, 00621 newton_solver->max_linear_iterations); // max linear iterations 00622 00623 if (!quiet) 00624 std::cout << " G_u*y = G_{lambda} solver converged at step " 00625 << rval.first 00626 << ", linear tolerance = " 00627 << rval.second 00628 << "." 00629 << std::endl; 00630 00631 // Sometimes (I am not sure why) the linear solver exits after zero iterations. 00632 // Perhaps it is hitting PETSc's divergence tolerance dtol??? If this occurs, 00633 // we should break out of the Newton iteration loop because nothing further is 00634 // going to happen... 00635 if ((rval.first == 0) && (rval.second > ysystemtol)) 00636 { 00637 if (!quiet) 00638 std::cout << "Linear solver exited in zero iterations!" << std::endl; 00639 00640 break; // out of Newton iterations 00641 } 00642 00643 // ++attempt; 00644 // } while ((attempt<max_attempts) && (rval.first==newton_solver->max_linear_iterations)); 00645 00646 00647 00648 00649 00650 // Compute N, the residual of the arclength constraint eqn. 00651 // Note 1: N(u,lambda,s) := (u-u_{old}, du_ds) + (lambda-lambda_{old}, dlambda_ds) - _ds 00652 // We temporarily use the delta_u vector as a temporary vector for this calculation. 00653 *delta_u = *solution; 00654 delta_u->add(-1., *previous_u); 00655 00656 // First part of the arclength constraint 00657 const Number N1 = Theta_LOCA*Theta_LOCA*Theta*delta_u->dot(*du_ds); 00658 const Number N2 = ((*continuation_parameter) - old_continuation_parameter)*dlambda_ds; 00659 const Number N3 = ds_current; 00660 00661 if (!quiet) 00662 { 00663 std::cout << " N1=" << N1 << std::endl; 00664 std::cout << " N2=" << N2 << std::endl; 00665 std::cout << " N3=" << N3 << std::endl; 00666 } 00667 00668 // The arclength constraint value 00669 const Number N = N1+N2-N3; 00670 00671 if (!quiet) 00672 std::cout << " N=" << N << std::endl; 00673 00674 const Number duds_dot_z = du_ds->dot(*z); 00675 const Number duds_dot_y = du_ds->dot(*y); 00676 00677 //std::cout << "duds_dot_z=" << duds_dot_z << std::endl; 00678 //std::cout << "duds_dot_y=" << duds_dot_y << std::endl; 00679 //std::cout << "dlambda_ds=" << dlambda_ds << std::endl; 00680 00681 const Number delta_lambda_numerator = -(N + Theta_LOCA*Theta_LOCA*Theta*duds_dot_z); 00682 const Number delta_lambda_denominator = (dlambda_ds - Theta_LOCA*Theta_LOCA*Theta*duds_dot_y); 00683 00684 libmesh_assert (delta_lambda_denominator != 0.0); 00685 00686 // Now, we are ready to compute the step delta_lambda 00687 const Number delta_lambda_comp = delta_lambda_numerator / 00688 delta_lambda_denominator; 00689 // Lambda is real-valued 00690 const Real delta_lambda = libmesh_real(delta_lambda_comp); 00691 00692 // Knowing delta_lambda, we are ready to update delta_u 00693 // delta_u = z - delta_lambda*y 00694 delta_u->zero(); 00695 delta_u->add(1., *z); 00696 delta_u->add(-delta_lambda, *y); 00697 delta_u->close(); 00698 00699 // Update the system solution and the continuation parameter. 00700 solution->add(1., *delta_u); 00701 solution->close(); 00702 *continuation_parameter += delta_lambda; 00703 00704 // Did the Newton step actually reduce the residual? 00705 rhs_mode = Residual; 00706 assembly(true, // Residual 00707 false); // Jacobian 00708 rhs->close(); 00709 nonlinear_residual_afterstep = rhs->l2_norm(); 00710 00711 00712 // In a "normal" Newton step, ||du||/||R|| > 1 since the most recent 00713 // step is where you "just were" and the current residual is where 00714 // you are now. It can occur that ||du||/||R|| < 1, but these are 00715 // likely not good cases to attempt backtracking (?). 00716 const Real norm_du_norm_R = delta_u->l2_norm() / nonlinear_residual_afterstep; 00717 if (!quiet) 00718 std::cout << " norm_du_norm_R=" << norm_du_norm_R << std::endl; 00719 00720 00721 // Factor to decrease the stepsize by for backtracking 00722 Real newton_stepfactor = 1.; 00723 00724 const bool attempt_backtracking = 00725 (nonlinear_residual_afterstep > solution_tolerance) 00726 && (nonlinear_residual_afterstep > nonlinear_residual_beforestep) 00727 && (n_backtrack_steps>0) 00728 && (norm_du_norm_R > 1.) 00729 ; 00730 00731 // If residual is not reduced, do Newton back tracking. 00732 if (attempt_backtracking) 00733 { 00734 if (!quiet) 00735 std::cout << "Newton step did not reduce residual." << std::endl; 00736 00737 // back off the previous step. 00738 solution->add(-1., *delta_u); 00739 solution->close(); 00740 *continuation_parameter -= delta_lambda; 00741 00742 // Backtracking: start cutting the Newton stepsize by halves until 00743 // the new residual is actually smaller... 00744 for (unsigned int backtrack_step=0; backtrack_step<n_backtrack_steps; ++backtrack_step) 00745 { 00746 newton_stepfactor *= 0.5; 00747 00748 if (!quiet) 00749 std::cout << "Shrinking step size by " << newton_stepfactor << std::endl; 00750 00751 // Take fractional step 00752 solution->add(newton_stepfactor, *delta_u); 00753 solution->close(); 00754 *continuation_parameter += newton_stepfactor*delta_lambda; 00755 00756 rhs_mode = Residual; 00757 assembly(true, // Residual 00758 false); // Jacobian 00759 rhs->close(); 00760 nonlinear_residual_afterstep = rhs->l2_norm(); 00761 00762 if (!quiet) 00763 std::cout << "At shrink step " 00764 << backtrack_step 00765 << ", nonlinear_residual_afterstep=" 00766 << nonlinear_residual_afterstep 00767 << std::endl; 00768 00769 if (nonlinear_residual_afterstep < nonlinear_residual_beforestep) 00770 { 00771 if (!quiet) 00772 std::cout << "Backtracking succeeded!" << std::endl; 00773 00774 break; // out of backtracking loop 00775 } 00776 00777 else 00778 { 00779 // Back off that step 00780 solution->add(-newton_stepfactor, *delta_u); 00781 solution->close(); 00782 *continuation_parameter -= newton_stepfactor*delta_lambda; 00783 } 00784 00785 // Save a copy of the solution from before the Newton step. 00786 //AutoPtr<NumericVector<Number> > prior_iterate = solution->clone(); 00787 } 00788 } // end if (attempte_backtracking) 00789 00790 00791 // If we tried backtracking but the residual is still not reduced, print message. 00792 if ((attempt_backtracking) && (nonlinear_residual_afterstep > nonlinear_residual_beforestep)) 00793 { 00794 //std::cerr << "Backtracking failed." << std::endl; 00795 std::cout << "Backtracking failed." << std::endl; 00796 00797 // 1.) Quit, exit program. 00798 //libmesh_error(); 00799 00800 // 2.) Continue with last newton_stepfactor 00801 if (newton_step<3) 00802 { 00803 solution->add(newton_stepfactor, *delta_u); 00804 solution->close(); 00805 *continuation_parameter += newton_stepfactor*delta_lambda; 00806 if (!quiet) 00807 std::cout << "Backtracking could not reduce residual ... continuing anyway!" << std::endl; 00808 } 00809 00810 // 3.) Break out of Newton iteration loop with newton_converged = false, 00811 // reduce the arclength stepsize, and try again. 00812 else 00813 { 00814 break; // out of Newton iteration loop, with newton_converged=false 00815 } 00816 } 00817 00818 // Another type of convergence check: suppose the residual has not been reduced 00819 // from its initial value after half of the allowed Newton steps have occurred. 00820 // In our experience, this typically means that it isn't going to converge and 00821 // we could probably save time by dropping out of the Newton iteration loop and 00822 // trying a smaller arcstep. 00823 if (this->newton_progress_check) 00824 { 00825 if ((nonlinear_residual_afterstep > nonlinear_residual_firststep) && 00826 (newton_step+1 > static_cast<unsigned int>(0.5*newton_solver->max_nonlinear_iterations))) 00827 { 00828 std::cout << "Progress check failed: the current residual: " 00829 << nonlinear_residual_afterstep 00830 << ", is\n" 00831 << "larger than the initial residual, and half of the allowed\n" 00832 << "number of Newton iterations have elapsed.\n" 00833 << "Exiting Newton iterations with converged==false." << std::endl; 00834 00835 break; // out of Newton iteration loop, newton_converged = false 00836 } 00837 } 00838 00839 // Safety check: Check the current continuation parameter against user-provided min-allowable parameter value 00840 if (*continuation_parameter < min_continuation_parameter) 00841 { 00842 std::cout << "Continuation parameter fell below min-allowable value." << std::endl; 00843 // libmesh_error(); 00844 break; // out of Newton iteration loop, newton_converged = false 00845 } 00846 00847 // Safety check: Check the current continuation parameter against user-provided max-allowable parameter value 00848 if ( (max_continuation_parameter != 0.0) && 00849 (*continuation_parameter > max_continuation_parameter) ) 00850 { 00851 std::cout << "Current continuation parameter value: " 00852 << *continuation_parameter 00853 << " exceeded max-allowable value." 00854 << std::endl; 00855 // libmesh_error(); 00856 break; // out of Newton iteration loop, newton_converged = false 00857 } 00858 00859 00860 // Check the convergence of the parameter and the solution. If they are small 00861 // enough, we can break out of the Newton iteration loop. 00862 const Real norm_delta_u = delta_u->l2_norm(); 00863 const Real norm_u = solution->l2_norm(); 00864 std::cout << " delta_lambda = " << delta_lambda << std::endl; 00865 std::cout << " newton_stepfactor*delta_lambda = " << newton_stepfactor*delta_lambda << std::endl; 00866 std::cout << " lambda_current = " << *continuation_parameter << std::endl; 00867 std::cout << " ||delta_u|| = " << norm_delta_u << std::endl; 00868 std::cout << " ||delta_u||/||u|| = " << norm_delta_u / norm_u << std::endl; 00869 00870 00871 // Evaluate the residual at the current Newton iterate. We don't want to detect 00872 // convergence due to a small Newton step when the residual is still not small. 00873 rhs_mode = Residual; 00874 assembly(true, // Residual 00875 false); // Jacobian 00876 rhs->close(); 00877 const Real norm_residual = rhs->l2_norm(); 00878 std::cout << " ||R||_{L2} = " << norm_residual << std::endl; 00879 std::cout << " ||R||_{L2}/||u|| = " << norm_residual / norm_u << std::endl; 00880 00881 00882 // FIXME: The norm_delta_u tolerance (at least) should be relative. 00883 // It doesn't make sense to converge a solution whose size is ~ 10^5 to 00884 // a tolerance of 1.e-6. Oh, and we should also probably check the 00885 // (relative) size of the residual as well, instead of just the step. 00886 if ((std::abs(delta_lambda) < continuation_parameter_tolerance) && 00887 //(norm_delta_u < solution_tolerance) && // This is a *very* strict criterion we can probably skip 00888 (norm_residual < solution_tolerance)) 00889 { 00890 if (!quiet) 00891 std::cout << "Newton iterations converged!" << std::endl; 00892 00893 newton_converged = true; 00894 break; // out of Newton iterations 00895 } 00896 } // end nonlinear loop 00897 00898 if (!newton_converged) 00899 { 00900 std::cout << "Newton iterations of augmented system did not converge!" << std::endl; 00901 00902 // Reduce ds_current, recompute the solution and parameter, and continue to next 00903 // arcstep, if there is one. 00904 ds_current *= 0.5; 00905 00906 // Go back to previous solution and parameter value. 00907 *solution = *previous_u; 00908 *continuation_parameter = old_continuation_parameter; 00909 00910 // Compute new predictor with smaller ds 00911 apply_predictor(); 00912 } 00913 else 00914 { 00915 // Set step convergence and break out 00916 arcstep_converged=true; 00917 break; // out of arclength reduction loop 00918 } 00919 00920 } // end loop over arclength reductions 00921 00922 // Check for convergence of the whole arcstep. If not converged at this 00923 // point, we have no choice but to quit. 00924 if (!arcstep_converged) 00925 { 00926 std::cout << "Arcstep failed to converge after max number of reductions! Exiting..." << std::endl; 00927 libmesh_error(); 00928 } 00929 00930 // Print converged solution control parameter and max value. 00931 std::cout << "lambda_current=" << *continuation_parameter << std::endl; 00932 //std::cout << "u_max=" << solution->max() << std::endl; 00933 00934 // Reset old stream precision and flags. 00935 std::cout.precision(old_precision); 00936 std::cout.unsetf(std::ios_base::scientific); 00937 00938 // Note: we don't want to go on to the next guess yet, since the user may 00939 // want to post-process this data. It's up to the user to call advance_arcstep() 00940 // when they are ready to go on. 00941 }
| Number System::current_solution | ( | const unsigned int | global_dof_number | ) | const [inherited] |
- Returns:
- the current solution for the specified global DOF.
Definition at line 117 of file system.C.
References System::current_local_solution, and System::n_dofs().
Referenced by ExactSolution::_compute_error(), HPCoarsenTest::add_projection(), JumpErrorEstimator::estimate_error(), ExactErrorEstimator::estimate_error(), FEMSystem::eulerian_residual(), PatchRecoveryErrorEstimator::EstimateError::operator()(), FEMContext::reinit(), HPCoarsenTest::select_refinement(), VTKIO::solution_to_vtk(), EnsightIO::write_scalar_ascii(), and EnsightIO::write_vector_ascii().
00118 { 00119 // Check the sizes 00120 libmesh_assert (global_dof_number < _dof_map->n_dofs()); 00121 libmesh_assert (global_dof_number < current_local_solution->size()); 00122 00123 return (*current_local_solution)(global_dof_number); 00124 }
| void System::deactivate | ( | ) | [inline, inherited] |
Deactivates the system. Only active systems are solved.
Definition at line 1388 of file system.h.
References System::_active.
01389 { 01390 _active = false; 01391 }
| virtual bool DifferentiableSystem::element_constraint | ( | bool | request_jacobian, | |
| DiffContext & | ||||
| ) | [inline, virtual, inherited] |
Adds the constraint contribution on elem to elem_residual. If this method receives request_jacobian = true, then it should compute elem_jacobian and return true if possible. If elem_jacobian has not been computed then the method should return false.
Users may need to reimplement this for their particular PDE. To implement the constraint 0 = G(u), the user should examine u = elem_solution and add (G(u), phi_i) to elem_residual.
Definition at line 157 of file diff_system.h.
Referenced by SteadySolver::element_residual(), EulerSolver::element_residual(), Euler2Solver::element_residual(), and EigenTimeSolver::element_residual().
| virtual void DifferentiableSystem::element_postprocess | ( | DiffContext & | ) | [inline, virtual, inherited] |
Does any work that needs to be done on elem in a postprocessing loop.
Definition at line 225 of file diff_system.h.
Referenced by FEMSystem::postprocess().
| virtual void DifferentiableSystem::element_qoi | ( | DiffContext & | , | |
| const QoISet & | ||||
| ) | [inline, virtual, inherited] |
Does any work that needs to be done on elem in a quantity of interest assembly loop, outputting to elem_qoi.
Only qois included in the supplied QoISet need to be assembled.
Definition at line 240 of file diff_system.h.
Referenced by FEMSystem::assemble_qoi().
| virtual void DifferentiableSystem::element_qoi_derivative | ( | DiffContext & | , | |
| const QoISet & | ||||
| ) | [inline, virtual, inherited] |
Does any work that needs to be done on elem in a quantity of interest derivative assembly loop, outputting to elem_qoi_derivative
Only qois included in the supplied QoISet need their derivatives assembled.
Definition at line 252 of file diff_system.h.
Referenced by FEMSystem::assemble_qoi_derivative().
| virtual bool DifferentiableSystem::element_time_derivative | ( | bool | request_jacobian, | |
| DiffContext & | ||||
| ) | [inline, virtual, inherited] |
Adds the time derivative contribution on elem to elem_residual. If this method receives request_jacobian = true, then it should compute elem_jacobian and return true if possible. If elem_jacobian has not been computed then the method should return false.
Users need to reimplement this for their particular PDE. To implement the physics model du/dt = F(u), the user should examine u = elem_solution and add (F(u), phi_i) to elem_residual.
Definition at line 140 of file diff_system.h.
Referenced by SteadySolver::element_residual(), EulerSolver::element_residual(), Euler2Solver::element_residual(), and EigenTimeSolver::element_residual().
| bool FEMSystem::eulerian_residual | ( | bool | request_jacobian, | |
| DiffContext & | context | |||
| ) | [virtual, inherited] |
Adds a pseudo-convection contribution on elem to elem_residual, if the nodes of elem are being translated by a moving mesh.
This function assumes that the user's time derivative equations (except for any equations involving unknown mesh xyz coordinates themselves) are expressed in an Eulerian frame of reference, and that the user is satisfied with an unstabilized convection term. Lagrangian equations will probably require overriding eulerian_residual() with a blank function; ALE or stabilized formulations will require reimplementing eulerian_residual() entirely.
Reimplemented from DifferentiableSystem.
Definition at line 864 of file fem_system.C.
References FEMSystem::_mesh_sys, FEMSystem::_mesh_x_var, FEMSystem::_mesh_y_var, FEMSystem::_mesh_z_var, DifferentiableSystem::_time_evolving, System::current_solution(), DifferentiableSystem::deltat, DiffContext::dof_indices_var, DiffContext::elem_subjacobians, DiffContext::elem_subresiduals, FEMContext::element_fe_var, FEMContext::element_qrule, AutoPtr< Tp >::get(), FEMContext::interior_gradient(), libMesh::invalid_uint, libmesh_real(), QBase::n_points(), System::n_vars(), System::number(), UnsteadySolver::old_nonlinear_solution(), and DifferentiableSystem::time_solver.
00866 { 00867 // Only calculate a mesh movement residual if it's necessary 00868 if (_mesh_sys == libMesh::invalid_uint) 00869 return request_jacobian; 00870 00871 FEMContext &context = libmesh_cast_ref<FEMContext&>(c); 00872 00873 // This function only supports fully coupled mesh motion for now 00874 libmesh_assert(_mesh_sys == this->number()); 00875 00876 unsigned int n_qpoints = context.element_qrule->n_points(); 00877 00878 const unsigned int n_x_dofs = (_mesh_x_var == libMesh::invalid_uint) ? 00879 0 : context.dof_indices_var[_mesh_x_var].size(); 00880 const unsigned int n_y_dofs = (_mesh_y_var == libMesh::invalid_uint) ? 00881 0 : context.dof_indices_var[_mesh_y_var].size(); 00882 const unsigned int n_z_dofs = (_mesh_z_var == libMesh::invalid_uint) ? 00883 0 : context.dof_indices_var[_mesh_z_var].size(); 00884 00885 const unsigned int mesh_xyz_var = n_x_dofs ? _mesh_x_var : 00886 (n_y_dofs ? _mesh_y_var : 00887 (n_z_dofs ? _mesh_z_var : 00888 libMesh::invalid_uint)); 00889 00890 // If we're our own _mesh_sys, we'd better be in charge of 00891 // at least one coordinate, and we'd better have the same 00892 // FE type for all coordinates we are in charge of 00893 libmesh_assert(mesh_xyz_var != libMesh::invalid_uint); 00894 libmesh_assert(!n_x_dofs || context.element_fe_var[_mesh_x_var] == 00895 context.element_fe_var[mesh_xyz_var]); 00896 libmesh_assert(!n_y_dofs || context.element_fe_var[_mesh_y_var] == 00897 context.element_fe_var[mesh_xyz_var]); 00898 libmesh_assert(!n_z_dofs || context.element_fe_var[_mesh_z_var] == 00899 context.element_fe_var[mesh_xyz_var]); 00900 00901 const std::vector<std::vector<Real> > &psi = 00902 context.element_fe_var[mesh_xyz_var]->get_phi(); 00903 00904 for (unsigned int var = 0; var != this->n_vars(); ++var) 00905 { 00906 // Mesh motion only affects time-evolving variables 00907 if (!_time_evolving[var]) 00908 continue; 00909 00910 // The mesh coordinate variables themselves are Lagrangian, 00911 // not Eulerian, and no convective term is desired. 00912 if (_mesh_sys == this->number() && 00913 (var == _mesh_x_var || 00914 var == _mesh_y_var || 00915 var == _mesh_z_var)) 00916 continue; 00917 00918 // Some of this code currently relies on the assumption that 00919 // we can pull mesh coordinate data from our own system 00920 if (_mesh_sys != this->number()) 00921 libmesh_not_implemented(); 00922 00923 // This residual should only be called by unsteady solvers: 00924 // if the mesh is steady, there's no mesh convection term! 00925 UnsteadySolver *unsteady = 00926 dynamic_cast<UnsteadySolver *>(this->time_solver.get()); 00927 if (!unsteady) 00928 return request_jacobian; 00929 00930 const std::vector<Real> &JxW = 00931 context.element_fe_var[var]->get_JxW(); 00932 00933 const std::vector<std::vector<Real> > &phi = 00934 context.element_fe_var[var]->get_phi(); 00935 00936 const std::vector<std::vector<RealGradient> > &dphi = 00937 context.element_fe_var[var]->get_dphi(); 00938 00939 const unsigned int n_u_dofs = context.dof_indices_var[var].size(); 00940 00941 DenseSubVector<Number> &Fu = *context.elem_subresiduals[var]; 00942 DenseSubMatrix<Number> &Kuu = *context.elem_subjacobians[var][var]; 00943 00944 DenseSubMatrix<Number> *Kux = n_x_dofs ? 00945 context.elem_subjacobians[var][_mesh_x_var] : NULL; 00946 DenseSubMatrix<Number> *Kuy = n_y_dofs ? 00947 context.elem_subjacobians[var][_mesh_y_var] : NULL; 00948 DenseSubMatrix<Number> *Kuz = n_z_dofs ? 00949 context.elem_subjacobians[var][_mesh_z_var] : NULL; 00950 00951 std::vector<Real> delta_x(n_x_dofs, 0.); 00952 std::vector<Real> delta_y(n_y_dofs, 0.); 00953 std::vector<Real> delta_z(n_z_dofs, 0.); 00954 00955 for (unsigned int i = 0; i != n_x_dofs; ++i) 00956 { 00957 unsigned int j = context.dof_indices_var[_mesh_x_var][i]; 00958 delta_x[i] = libmesh_real(this->current_solution(j)) - 00959 libmesh_real(unsteady->old_nonlinear_solution(j)); 00960 } 00961 00962 for (unsigned int i = 0; i != n_y_dofs; ++i) 00963 { 00964 unsigned int j = context.dof_indices_var[_mesh_y_var][i]; 00965 delta_y[i] = libmesh_real(this->current_solution(j)) - 00966 libmesh_real(unsteady->old_nonlinear_solution(j)); 00967 } 00968 00969 for (unsigned int i = 0; i != n_z_dofs; ++i) 00970 { 00971 unsigned int j = context.dof_indices_var[_mesh_z_var][i]; 00972 delta_z[i] = libmesh_real(this->current_solution(j)) - 00973 libmesh_real(unsteady->old_nonlinear_solution(j)); 00974 } 00975 00976 for (unsigned int qp = 0; qp != n_qpoints; ++qp) 00977 { 00978 Gradient grad_u = context.interior_gradient(var, qp); 00979 RealGradient convection(0.); 00980 00981 for (unsigned int i = 0; i != n_x_dofs; ++i) 00982 convection(0) += delta_x[i] * psi[i][qp]; 00983 for (unsigned int i = 0; i != n_y_dofs; ++i) 00984 convection(1) += delta_y[i] * psi[i][qp]; 00985 for (unsigned int i = 0; i != n_z_dofs; ++i) 00986 convection(2) += delta_z[i] * psi[i][qp]; 00987 00988 for (unsigned int i = 0; i != n_u_dofs; ++i) 00989 { 00990 Number JxWxPhiI = JxW[qp] * phi[i][qp]; 00991 Fu(i) += (convection * grad_u) * JxWxPhiI; 00992 if (request_jacobian) 00993 { 00994 Number JxWxPhiI = JxW[qp] * phi[i][qp]; 00995 for (unsigned int j = 0; j != n_u_dofs; ++j) 00996 Kuu(i,j) += JxWxPhiI * (convection * dphi[j][qp]); 00997 00998 Number JxWxPhiIoverDT = JxWxPhiI/this->deltat; 00999 01000 Number JxWxPhiIxDUDXoverDT = JxWxPhiIoverDT * grad_u(0); 01001 for (unsigned int j = 0; j != n_x_dofs; ++j) 01002 (*Kux)(i,j) += JxWxPhiIxDUDXoverDT * psi[j][qp]; 01003 01004 Number JxWxPhiIxDUDYoverDT = JxWxPhiIoverDT * grad_u(1); 01005 for (unsigned int j = 0; j != n_y_dofs; ++j) 01006 (*Kuy)(i,j) += JxWxPhiIxDUDYoverDT * psi[j][qp]; 01007 01008 Number JxWxPhiIxDUDZoverDT = JxWxPhiIoverDT * grad_u(2); 01009 for (unsigned int j = 0; j != n_z_dofs; ++j) 01010 (*Kuz)(i,j) += JxWxPhiIxDUDZoverDT * psi[j][qp]; 01011 } 01012 } 01013 } 01014 } 01015 01016 return request_jacobian; 01017 }
| void ImplicitSystem::forward_qoi_parameter_sensitivity | ( | const QoISet & | qoi_indices, | |
| const ParameterVector & | parameters, | |||
| SensitivityData & | sensitivities | |||
| ) | [virtual, inherited] |
Solves for the derivative of each of the system's quantities of interest q in qoi[qoi_indices] with respect to each parameter in parameters, placing the result for qoi i and parameter j into sensitivities[i][j].
Uses the forward sensitivity method.
Currently uses finite differenced derivatives (partial q / partial p) and (partial R / partial p).
Reimplemented from System.
Definition at line 749 of file implicit_system.C.
References SensitivityData::allocate_data(), QoISet::has_index(), and ParameterVector::size().
00752 { 00753 const unsigned int Np = parameters.size(); 00754 const unsigned int Nq = qoi.size(); 00755 00756 // We currently get partial derivatives via central differencing 00757 const Real delta_p = TOLERANCE; 00758 00759 // An introduction to the problem: 00760 // 00761 // Residual R(u(p),p) = 0 00762 // partial R / partial u = J = system matrix 00763 // 00764 // This implies that: 00765 // d/dp(R) = 0 00766 // (partial R / partial p) + 00767 // (partial R / partial u) * (partial u / partial p) = 0 00768 00769 // We first solve for (partial u / partial p) for each parameter: 00770 // J * (partial u / partial p) = - (partial R / partial p) 00771 00772 this->sensitivity_solve(parameters); 00773 00774 // Get ready to fill in senstivities: 00775 sensitivities.allocate_data(qoi_indices, *this, parameters); 00776 00777 // We use the identity: 00778 // dq/dp = (partial q / partial p) + (partial q / partial u) * 00779 // (partial u / partial p) 00780 00781 // We get (partial q / partial u) from the user 00782 this->assemble_qoi_derivative(qoi_indices); 00783 00784 for (unsigned int j=0; j != Np; ++j) 00785 { 00786 // (partial q / partial p) ~= (q(p+dp)-q(p-dp))/(2*dp) 00787 00788 Number old_parameter = *parameters[j]; 00789 00790 *parameters[j] = old_parameter - delta_p; 00791 this->assemble_qoi(); 00792 std::vector<Number> qoi_minus = this->qoi; 00793 00794 *parameters[j] = old_parameter + delta_p; 00795 this->assemble_qoi(); 00796 std::vector<Number>& qoi_plus = this->qoi; 00797 00798 std::vector<Number> partialq_partialp(Nq, 0); 00799 for (unsigned int i=0; i != Nq; ++i) 00800 if (qoi_indices.has_index(i)) 00801 partialq_partialp[i] = (qoi_plus[i] - qoi_minus[i]) / (2.*delta_p); 00802 00803 // Don't leave the parameter changed 00804 *parameters[j] = old_parameter; 00805 00806 for (unsigned int i=0; i != Nq; ++i) 00807 if (qoi_indices.has_index(i)) 00808 sensitivities[i][j] = partialq_partialp[i] + 00809 this->get_adjoint_rhs(i).dot(this->get_sensitivity_solution(i)); 00810 } 00811 00812 // All parameters have been reset. 00813 // We didn't cache the original rhs or matrix for memory reasons, 00814 // but we can restore them to a state consistent solution - 00815 // principle of least surprise. 00816 this->assembly(true, true); 00817 this->rhs->close(); 00818 this->matrix->close(); 00819 this->assemble_qoi(qoi_indices); 00820 }
| const NumericVector< Number > & System::get_adjoint_rhs | ( | unsigned int | i = 0 |
) | const [inherited] |
- Returns:
- a reference to one of the system's adjoint rhs vectors, by default the one corresponding to the first qoi.
Definition at line 844 of file system.C.
References System::get_vector().
00845 { 00846 OStringStream adjoint_rhs_name; 00847 adjoint_rhs_name << "adjoint_rhs" << i; 00848 00849 return this->get_vector(adjoint_rhs_name.str()); 00850 }
| NumericVector< Number > & System::get_adjoint_rhs | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's adjoint rhs vectors, by default the one corresponding to the first qoi. This what the user's QoI derivative code should assemble when setting up an adjoint problem
Definition at line 834 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::adjoint_solve(), FEMSystem::assemble_qoi_derivative(), and ImplicitSystem::weighted_sensitivity_adjoint_solve().
00835 { 00836 OStringStream adjoint_rhs_name; 00837 adjoint_rhs_name << "adjoint_rhs" << i; 00838 00839 return this->get_vector(adjoint_rhs_name.str()); 00840 }
| const NumericVector< Number > & System::get_adjoint_solution | ( | unsigned int | i = 0 |
) | const [inherited] |
- Returns:
- a reference to one of the system's adjoint solution vectors, by default the one corresponding to the first qoi.
Definition at line 784 of file system.C.
References System::get_vector().
00785 { 00786 OStringStream adjoint_name; 00787 adjoint_name << "adjoint_solution" << i; 00788 00789 return this->get_vector(adjoint_name.str()); 00790 }
| NumericVector< Number > & System::get_adjoint_solution | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's adjoint solution vectors, by default the one corresponding to the first qoi.
Definition at line 774 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::adjoint_solve(), AdjointResidualErrorEstimator::estimate_error(), and ImplicitSystem::weighted_sensitivity_adjoint_solve().
00775 { 00776 OStringStream adjoint_name; 00777 adjoint_name << "adjoint_solution" << i; 00778 00779 return this->get_vector(adjoint_name.str()); 00780 }
| DofMap & System::get_dof_map | ( | ) | [inline, inherited] |
- Returns:
- a writeable reference to this system's
_dof_map.
Definition at line 1364 of file system.h.
References System::_dof_map.
01365 { 01366 return *_dof_map; 01367 }
| const DofMap & System::get_dof_map | ( | ) | const [inline, inherited] |
- Returns:
- a constant reference to this system's
_dof_map.
Definition at line 1356 of file system.h.
References System::_dof_map.
Referenced by __libmesh_petsc_diff_solver_jacobian(), __libmesh_petsc_diff_solver_residual(), ExactSolution::_compute_error(), HPCoarsenTest::add_projection(), ImplicitSystem::adjoint_solve(), FEMSystem::assemble_qoi_derivative(), FEMSystem::assembly(), EquationSystems::build_discontinuous_solution_vector(), EquationSystems::build_solution_vector(), System::calculate_norm(), DofMap::enforce_constraints_exactly(), JumpErrorEstimator::estimate_error(), ExactErrorEstimator::estimate_error(), System::get_info(), EigenSystem::init_data(), ImplicitSystem::init_matrices(), System::local_dof_indices(), DofMap::max_constraint_error(), FEMSystem::mesh_position_get(), UnsteadySolver::old_nonlinear_solution(), System::ProjectVector::operator()(), PatchRecoveryErrorEstimator::EstimateError::operator()(), ErrorVector::plot_error(), System::project_vector(), FEMContext::reinit(), EquationSystems::reinit(), HPCoarsenTest::select_refinement(), ImplicitSystem::sensitivity_solve(), UnsteadySolver::solve(), PetscDiffSolver::solve(), NewtonSolver::solve(), ImplicitSystem::weighted_sensitivity_adjoint_solve(), ImplicitSystem::weighted_sensitivity_solve(), EnsightIO::write_scalar_ascii(), and EnsightIO::write_vector_ascii().
01357 { 01358 return *_dof_map; 01359 }
| EquationSystems& System::get_equation_systems | ( | ) | [inline, inherited] |
- Returns:
- a reference to this system's parent EquationSystems object.
Definition at line 389 of file system.h.
References System::_equation_systems.
00389 { return _equation_systems; }
| const EquationSystems& System::get_equation_systems | ( | ) | const [inline, inherited] |
- Returns:
- a constant reference to this system's parent EquationSystems object.
Definition at line 384 of file system.h.
References System::_equation_systems.
Referenced by NewmarkSystem::clear(), FrequencySystem::clear_all(), ExactErrorEstimator::find_squared_element_error(), ImplicitSystem::get_linear_solve_parameters(), FrequencySystem::init_data(), FrequencySystem::n_frequencies(), FrequencySystem::set_current_frequency(), FrequencySystem::set_frequencies(), FrequencySystem::set_frequencies_by_range(), FrequencySystem::set_frequencies_by_steps(), NewmarkSystem::set_newmark_parameters(), NonlinearImplicitSystem::set_solver_parameters(), LinearImplicitSystem::solve(), FrequencySystem::solve(), and EigenSystem::solve().
00384 { return _equation_systems; }
| std::string ReferenceCounter::get_info | ( | ) | [static, inherited] |
Gets a string containing the reference information.
Definition at line 45 of file reference_counter.C.
References ReferenceCounter::_counts, and QuadratureRules::name().
Referenced by ReferenceCounter::print_info().
00046 { 00047 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG) 00048 00049 std::ostringstream out; 00050 00051 out << '\n' 00052 << " ---------------------------------------------------------------------------- \n" 00053 << "| Reference count information |\n" 00054 << " ---------------------------------------------------------------------------- \n"; 00055 00056 for (Counts::iterator it = _counts.begin(); 00057 it != _counts.end(); ++it) 00058 { 00059 const std::string name(it->first); 00060 const unsigned int creations = it->second.first; 00061 const unsigned int destructions = it->second.second; 00062 00063 out << "| " << name << " reference count information:\n" 00064 << "| Creations: " << creations << '\n' 00065 << "| Destructions: " << destructions << '\n'; 00066 } 00067 00068 out << " ---------------------------------------------------------------------------- \n"; 00069 00070 return out.str(); 00071 00072 #else 00073 00074 return ""; 00075 00076 #endif 00077 }
| std::string System::get_info | ( | ) | const [inherited] |
- Returns:
- a string containing information about the system.
Definition at line 1233 of file system.C.
References Utility::enum_to_string< FEFamily >(), Utility::enum_to_string< InfMapType >(), Utility::enum_to_string< Order >(), FEType::family, System::get_dof_map(), FEType::inf_map, System::n_constrained_dofs(), System::n_dofs(), System::n_local_dofs(), System::n_vars(), System::n_vectors(), System::name(), FEType::order, FEType::radial_family, FEType::radial_order, System::system_type(), System::variable_name(), and DofMap::variable_type().
01234 { 01235 std::ostringstream out; 01236 01237 01238 const std::string& sys_name = this->name(); 01239 01240 out << " System \"" << sys_name << "\"\n" 01241 << " Type \"" << this->system_type() << "\"\n" 01242 << " Variables="; 01243 01244 for (unsigned int vn=0; vn<this->n_vars(); vn++) 01245 out << "\"" << this->variable_name(vn) << "\" "; 01246 01247 out << '\n'; 01248 01249 out << " Finite Element Types="; 01250 #ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS 01251 for (unsigned int vn=0; vn<this->n_vars(); vn++) 01252 out << "\"" 01253 << Utility::enum_to_string<FEFamily>(this->get_dof_map().variable_type(vn).family) 01254 << "\" "; 01255 #else 01256 for (unsigned int vn=0; vn<this->n_vars(); vn++) 01257 { 01258 out << "\"" 01259 << Utility::enum_to_string<FEFamily>(this->get_dof_map().variable_type(vn).family) 01260 << "\", \"" 01261 << Utility::enum_to_string<FEFamily>(this->get_dof_map().variable_type(vn).radial_family) 01262 << "\" "; 01263 } 01264 01265 out << '\n' << " Infinite Element Mapping="; 01266 for (unsigned int vn=0; vn<this->n_vars(); vn++) 01267 out << "\"" 01268 << Utility::enum_to_string<InfMapType>(this->get_dof_map().variable_type(vn).inf_map) 01269 << "\" "; 01270 #endif 01271 01272 out << '\n'; 01273 01274 out << " Approximation Orders="; 01275 for (unsigned int vn=0; vn<this->n_vars(); vn++) 01276 { 01277 #ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS 01278 out << "\"" 01279 << Utility::enum_to_string<Order>(this->get_dof_map().variable_type(vn).order) 01280 << "\" "; 01281 #else 01282 out << "\"" 01283 << Utility::enum_to_string<Order>(this->get_dof_map().variable_type(vn).order) 01284 << "\", \"" 01285 << Utility::enum_to_string<Order>(this->get_dof_map().variable_type(vn).radial_order) 01286 << "\" "; 01287 #endif 01288 } 01289 01290 out << '\n'; 01291 01292 out << " n_dofs()=" << this->n_dofs() << '\n'; 01293 out << " n_local_dofs()=" << this->n_local_dofs() << '\n'; 01294 #ifdef LIBMESH_ENABLE_AMR 01295 out << " n_constrained_dofs()=" << this->n_constrained_dofs() << '\n'; 01296 #endif 01297 01298 out << " " << "n_vectors()=" << this->n_vectors() << '\n'; 01299 // out << " " << "n_additional_matrices()=" << this->n_additional_matrices() << '\n'; 01300 01301 return out.str(); 01302 }
| std::pair< unsigned int, Real > DifferentiableSystem::get_linear_solve_parameters | ( | ) | const [virtual, inherited] |
Returns an integer corresponding to the upper iteration count limit and a Real corresponding to the convergence tolerance to be used in linear adjoint and/or sensitivity solves
Reimplemented from ImplicitSystem.
Definition at line 123 of file diff_system.C.
References DifferentiableSystem::time_solver.
00124 { 00125 return std::make_pair(this->time_solver->diff_solver()->max_linear_iterations, 00126 this->time_solver->diff_solver()->relative_residual_tolerance); 00127 }
| LinearSolver< Number > * DifferentiableSystem::get_linear_solver | ( | ) | const [virtual, inherited] |
Returns a pointer to a linear solver appropriate for use in adjoint and/or sensitivity solves
Reimplemented from ImplicitSystem.
Definition at line 116 of file diff_system.C.
References AutoPtr< Tp >::get(), and DifferentiableSystem::time_solver.
00117 { 00118 return this->time_solver->linear_solver().get(); 00119 }
| SparseMatrix< Number > & ImplicitSystem::get_matrix | ( | const std::string & | mat_name | ) | [inherited] |
- Returns:
- a writeable reference to this system's additional matrix named
mat_name. None of these matrices is involved in the solution process. Access is only granted when the matrix is already properly initialized.
Definition at line 245 of file implicit_system.C.
References ImplicitSystem::_matrices.
00246 { 00247 // Make sure the matrix exists 00248 matrices_iterator pos = _matrices.find (mat_name); 00249 00250 if (pos == _matrices.end()) 00251 { 00252 std::cerr << "ERROR: matrix " 00253 << mat_name 00254 << " does not exist in this system!" 00255 << std::endl; 00256 libmesh_error(); 00257 } 00258 00259 return *(pos->second); 00260 }
| const SparseMatrix< Number > & ImplicitSystem::get_matrix | ( | const std::string & | mat_name | ) | const [inherited] |
- Returns:
- a const reference to this system's additional matrix named
mat_name. None of these matrices is involved in the solution process. Access is only granted when the matrix is already properly initialized.
Definition at line 226 of file implicit_system.C.
References ImplicitSystem::_matrices.
Referenced by NewmarkSystem::compute_matrix(), EigenTimeSolver::solve(), and NewmarkSystem::update_rhs().
00227 { 00228 // Make sure the matrix exists 00229 const_matrices_iterator pos = _matrices.find (mat_name); 00230 00231 if (pos == _matrices.end()) 00232 { 00233 std::cerr << "ERROR: matrix " 00234 << mat_name 00235 << " does not exist in this system!" 00236 << std::endl; 00237 libmesh_error(); 00238 } 00239 00240 return *(pos->second); 00241 }
| MeshBase & System::get_mesh | ( | ) | [inline, inherited] |
- Returns:
- a reference to this systems's
_mesh.
Definition at line 1348 of file system.h.
References System::_mesh.
01349 { 01350 return _mesh; 01351 }
| const MeshBase & System::get_mesh | ( | ) | const [inline, inherited] |
- Returns:
- a constant reference to this systems's
_mesh.
Definition at line 1340 of file system.h.
References System::_mesh.
Referenced by ExactSolution::_compute_error(), HPCoarsenTest::add_projection(), FEMSystem::assemble_qoi(), FEMSystem::assemble_qoi_derivative(), FEMSystem::assembly(), System::calculate_norm(), PatchRecoveryErrorEstimator::estimate_error(), JumpErrorEstimator::estimate_error(), ExactErrorEstimator::estimate_error(), AdjointResidualErrorEstimator::estimate_error(), System::init_data(), EigenSystem::init_data(), ImplicitSystem::init_matrices(), System::local_dof_indices(), DofMap::max_constraint_error(), FEMSystem::mesh_position_get(), FEMSystem::mesh_position_set(), System::ProjectVector::operator()(), PatchRecoveryErrorEstimator::EstimateError::operator()(), FEMSystem::postprocess(), System::project_vector(), System::read_header(), System::read_legacy_data(), System::read_parallel_data(), System::read_serialized_vector(), HPSingularity::select_refinement(), HPCoarsenTest::select_refinement(), System::write_header(), System::write_parallel_data(), System::write_serialized_vector(), and System::zero_variable().
01341 { 01342 return _mesh; 01343 }
| const NumericVector< Number > & System::get_sensitivity_rhs | ( | unsigned int | i = 0 |
) | const [inherited] |
- Returns:
- a reference to one of the system's sensitivity rhs vectors, by default the one corresponding to the first parameter.
Definition at line 874 of file system.C.
References System::get_vector().
00875 { 00876 OStringStream sensitivity_rhs_name; 00877 sensitivity_rhs_name << "sensitivity_rhs" << i; 00878 00879 return this->get_vector(sensitivity_rhs_name.str()); 00880 }
| NumericVector< Number > & System::get_sensitivity_rhs | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's sensitivity rhs vectors, by default the one corresponding to the first parameter. By default these vectors are built by the library, using finite differences, when
assemble_residual_derivatives()is called.
Definition at line 864 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::sensitivity_solve().
00865 { 00866 OStringStream sensitivity_rhs_name; 00867 sensitivity_rhs_name << "sensitivity_rhs" << i; 00868 00869 return this->get_vector(sensitivity_rhs_name.str()); 00870 }
| const NumericVector< Number > & System::get_sensitivity_solution | ( | unsigned int | i = 0 |
) | const [inherited] |
- Returns:
- a reference to one of the system's solution sensitivity vectors, by default the one corresponding to the first parameter.
Definition at line 733 of file system.C.
References System::get_vector().
00734 { 00735 OStringStream sensitivity_name; 00736 sensitivity_name << "sensitivity_solution" << i; 00737 00738 return this->get_vector(sensitivity_name.str()); 00739 }
| NumericVector< Number > & System::get_sensitivity_solution | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's solution sensitivity vectors, by default the one corresponding to the first parameter.
Definition at line 723 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::sensitivity_solve().
00724 { 00725 OStringStream sensitivity_name; 00726 sensitivity_name << "sensitivity_solution" << i; 00727 00728 return this->get_vector(sensitivity_name.str()); 00729 }
| NumericVector< Number > & System::get_vector | ( | const unsigned int | vec_num | ) | [inherited] |
- Returns:
- a writeable reference to this system's additional vector number
vec_num(where the vectors are counted starting with 0).
Definition at line 682 of file system.C.
References System::vectors_begin(), and System::vectors_end().
00683 { 00684 vectors_iterator v = vectors_begin(); 00685 vectors_iterator v_end = vectors_end(); 00686 unsigned int num = 0; 00687 while((num<vec_num) && (v!=v_end)) 00688 { 00689 num++; 00690 ++v; 00691 } 00692 libmesh_assert(v!=v_end); 00693 return *(v->second); 00694 }
| const NumericVector< Number > & System::get_vector | ( | const unsigned int | vec_num | ) | const [inherited] |
- Returns:
- a const reference to this system's additional vector number
vec_num(where the vectors are counted starting with 0).
Definition at line 666 of file system.C.
References System::vectors_begin(), and System::vectors_end().
00667 { 00668 const_vectors_iterator v = vectors_begin(); 00669 const_vectors_iterator v_end = vectors_end(); 00670 unsigned int num = 0; 00671 while((num<vec_num) && (v!=v_end)) 00672 { 00673 num++; 00674 ++v; 00675 } 00676 libmesh_assert(v!=v_end); 00677 return *(v->second); 00678 }
| NumericVector< Number > & System::get_vector | ( | const std::string & | vec_name | ) | [inherited] |
- Returns:
- a writeable reference to this system's additional vector named
vec_name. Access is only granted when the vector is already properly initialized.
Definition at line 647 of file system.C.
References System::_vectors.
00648 { 00649 // Make sure the vector exists 00650 vectors_iterator pos = _vectors.find(vec_name); 00651 00652 if (pos == _vectors.end()) 00653 { 00654 std::cerr << "ERROR: vector " 00655 << vec_name 00656 << " does not exist in this system!" 00657 << std::endl; 00658 libmesh_error(); 00659 } 00660 00661 return *(pos->second); 00662 }
| const NumericVector< Number > & System::get_vector | ( | const std::string & | vec_name | ) | const [inherited] |
- Returns:
- a const reference to this system's additional vector named
vec_name. Access is only granted when the vector is already properly initialized.
Definition at line 628 of file system.C.
References System::_vectors.
Referenced by System::add_weighted_sensitivity_adjoint_solution(), UnsteadySolver::advance_timestep(), AdaptiveTimeSolver::advance_timestep(), System::compare(), UnsteadySolver::du(), System::get_adjoint_rhs(), System::get_adjoint_solution(), System::get_sensitivity_rhs(), System::get_sensitivity_solution(), System::get_weighted_sensitivity_adjoint_solution(), System::get_weighted_sensitivity_solution(), NewmarkSystem::initial_conditions(), UnsteadySolver::solve(), TwostepTimeSolver::solve(), FrequencySystem::solve(), NewmarkSystem::update_rhs(), and NewmarkSystem::update_u_v_a().
00629 { 00630 // Make sure the vector exists 00631 const_vectors_iterator pos = _vectors.find(vec_name); 00632 00633 if (pos == _vectors.end()) 00634 { 00635 std::cerr << "ERROR: vector " 00636 << vec_name 00637 << " does not exist in this system!" 00638 << std::endl; 00639 libmesh_error(); 00640 } 00641 00642 return *(pos->second); 00643 }
| const NumericVector< Number > & System::get_weighted_sensitivity_adjoint_solution | ( | unsigned int | i = 0 |
) | const [inherited] |
- Returns:
- a reference to one of the system's weighted sensitivity adjoint solution vectors, by default the one corresponding to the first qoi.
Definition at line 814 of file system.C.
References System::get_vector().
00815 { 00816 OStringStream adjoint_name; 00817 adjoint_name << "weighted_sensitivity_adjoint_solution" << i; 00818 00819 return this->get_vector(adjoint_name.str()); 00820 }
| NumericVector< Number > & System::get_weighted_sensitivity_adjoint_solution | ( | unsigned int | i = 0 |
) | [inherited] |
- Returns:
- a reference to one of the system's weighted sensitivity adjoint solution vectors, by default the one corresponding to the first qoi.
Definition at line 804 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::weighted_sensitivity_adjoint_solve().
00805 { 00806 OStringStream adjoint_name; 00807 adjoint_name << "weighted_sensitivity_adjoint_solution" << i; 00808 00809 return this->get_vector(adjoint_name.str()); 00810 }
| const NumericVector< Number > & System::get_weighted_sensitivity_solution | ( | ) | const [inherited] |
- Returns:
- a reference to the solution of the last weighted sensitivity solve
Definition at line 757 of file system.C.
References System::get_vector().
00758 { 00759 return this->get_vector("weighted_sensitivity_solution"); 00760 }
| NumericVector< Number > & System::get_weighted_sensitivity_solution | ( | ) | [inherited] |
- Returns:
- a reference to the solution of the last weighted sensitivity solve
Definition at line 750 of file system.C.
References System::get_vector().
Referenced by ImplicitSystem::weighted_sensitivity_solve().
00751 { 00752 return this->get_vector("weighted_sensitivity_solution"); 00753 }
| bool System::has_variable | ( | const std::string & | var | ) | const [inherited] |
- Returns:
- true if a variable named
varexists in this System
Definition at line 935 of file system.C.
References System::_variable_numbers.
Referenced by GMVIO::copy_nodal_solution().
00936 { 00937 return _variable_numbers.count(var); 00938 }
| bool ImplicitSystem::have_matrix | ( | const std::string & | mat_name | ) | const [inline, inherited] |
- Returns:
trueif thisSystemhas a matrix associated with the given name,falseotherwise.
Definition at line 369 of file implicit_system.h.
References ImplicitSystem::_matrices.
Referenced by ImplicitSystem::add_matrix(), and EigenTimeSolver::init().
00370 { 00371 return (_matrices.count(mat_name)); 00372 }
| bool System::have_vector | ( | const std::string & | vec_name | ) | const [inline, inherited] |
- Returns:
trueif thisSystemhas a vector associated with the given name,falseotherwise.
Definition at line 1450 of file system.h.
References System::_vectors.
Referenced by System::add_vector().
01451 { 01452 return (_vectors.count(vec_name)); 01453 }
| void ReferenceCounter::increment_constructor_count | ( | const std::string & | name | ) | [inline, protected, inherited] |
Increments the construction counter. Should be called in the constructor of any derived class that will be reference counted.
Definition at line 149 of file reference_counter.h.
References ReferenceCounter::_counts, and Threads::spin_mtx.
Referenced by ReferenceCountedObject< SparseMatrix< T > >::ReferenceCountedObject().
00150 { 00151 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 00152 std::pair<unsigned int, unsigned int>& p = _counts[name]; 00153 00154 p.first++; 00155 }
| void ReferenceCounter::increment_destructor_count | ( | const std::string & | name | ) | [inline, protected, inherited] |
Increments the destruction counter. Should be called in the destructor of any derived class that will be reference counted.
Definition at line 167 of file reference_counter.h.
References ReferenceCounter::_counts, and Threads::spin_mtx.
Referenced by ReferenceCountedObject< SparseMatrix< T > >::~ReferenceCountedObject().
00168 { 00169 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 00170 std::pair<unsigned int, unsigned int>& p = _counts[name]; 00171 00172 p.second++; 00173 }
| void System::init | ( | ) | [inherited] |
Initializes degrees of freedom on the current mesh. Sets the
Definition at line 158 of file system.C.
References System::init_data(), System::n_vars(), and System::user_initialization().
00159 { 00160 // First initialize any required data 00161 this->init_data(); 00162 00163 //If no variables have been added to this system 00164 //don't do anything 00165 if(!this->n_vars()) 00166 return; 00167 00168 // Then call the user-provided intialization function 00169 this->user_initialization(); 00170 }
| void FEMSystem::init_context | ( | DiffContext & | c | ) | [virtual, inherited] |
Reimplemented from DifferentiableSystem.
Definition at line 749 of file fem_system.C.
References DifferentiableSystem::_time_evolving, FEMContext::element_fe_var, DifferentiableSystem::init_context(), and System::n_vars().
Referenced by FEMSystem::mesh_position_get().
00750 { 00751 Parent::init_context(c); 00752 00753 FEMContext &context = libmesh_cast_ref<FEMContext&>(c); 00754 00755 // Make sure we're prepared to do mass integration 00756 for (unsigned int var = 0; var != this->n_vars(); ++var) 00757 if (_time_evolving[var]) 00758 { 00759 context.element_fe_var[var]->get_JxW(); 00760 context.element_fe_var[var]->get_phi(); 00761 } 00762 }
| void ContinuationSystem::init_data | ( | ) | [protected, virtual] |
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
Reimplemented from FEMSystem.
Definition at line 84 of file continuation_system.C.
References System::add_vector(), delta_u, du_ds, FEMSystem::init_data(), previous_du_ds, previous_u, y, y_old, and z.
00085 { 00086 // Add a vector which stores the tangent "du/ds" to the system and save its pointer. 00087 du_ds = &(add_vector("du_ds")); 00088 00089 // Add a vector which stores the tangent "du/ds" to the system and save its pointer. 00090 previous_du_ds = &(add_vector("previous_du_ds")); 00091 00092 // Add a vector to keep track of the previous nonlinear solution 00093 // at the old value of lambda. 00094 previous_u = &(add_vector("previous_u")); 00095 00096 // Add a vector to keep track of the temporary solution "y" of Ay=G_{\lambda}. 00097 y = &(add_vector("y")); 00098 00099 // Add a vector to keep track of the "old value" of "y" which is the solution of Ay=G_{\lambda}. 00100 y_old = &(add_vector("y_old")); 00101 00102 // Add a vector to keep track of the temporary solution "z" of Az=-G. 00103 z = &(add_vector("z")); 00104 00105 // Add a vector to keep track of the Newton update during the constrained PDE solves. 00106 delta_u = &(add_vector("delta_u")); 00107 00108 // Call the Parent's initialization routine. 00109 Parent::init_data(); 00110 }
| void ImplicitSystem::init_matrices | ( | ) | [protected, virtual, inherited] |
Initializes the matrices associated with this system.
Definition at line 99 of file implicit_system.C.
References ImplicitSystem::_can_add_matrices, ImplicitSystem::_matrices, DofMap::attach_matrix(), DofMap::compute_sparsity(), System::get_dof_map(), System::get_mesh(), and ImplicitSystem::matrix.
Referenced by ImplicitSystem::init_data(), and ImplicitSystem::reinit().
00100 { 00101 libmesh_assert (matrix != NULL); 00102 00103 // Check for quick return in case the system matrix 00104 // (and by extension all the matrices) has already 00105 // been initialized 00106 if (matrix->initialized()) 00107 return; 00108 00109 // Get a reference to the DofMap 00110 DofMap& dof_map = this->get_dof_map(); 00111 00112 // no chance to add other matrices 00113 _can_add_matrices = false; 00114 00115 // Tell the matrices about the dof map, and vice versa 00116 for (matrices_iterator pos = _matrices.begin(); 00117 pos != _matrices.end(); ++pos) 00118 { 00119 libmesh_assert (!pos->second->initialized()); 00120 dof_map.attach_matrix (*(pos->second)); 00121 } 00122 00123 // Compute the sparsity pattern for the current 00124 // mesh and DOF distribution. This also updates 00125 // additional matrices, \p DofMap now knows them 00126 dof_map.compute_sparsity (this->get_mesh()); 00127 00128 // Initialize matrices 00129 for (matrices_iterator pos = _matrices.begin(); 00130 pos != _matrices.end(); ++pos) 00131 pos->second->init (); 00132 00133 // Set the additional matrices to 0. 00134 for (matrices_iterator pos = _matrices.begin(); 00135 pos != _matrices.end(); ++pos) 00136 pos->second->zero (); 00137 }
| void ContinuationSystem::initialize_tangent | ( | ) | [private] |
Before starting arclength continuation, we need at least 2 prior solutions (both solution and u_previous should be filled with meaningful values) And we need to initialize the tangent vector. This only needs to be called once.
Definition at line 125 of file continuation_system.C.
References continuation_parameter, dlambda_ds, ds_current, du_ds, old_continuation_parameter, previous_u, quiet, set_Theta(), System::solution, solve_tangent(), tangent_initialized, Theta, Theta_LOCA, update_solution(), and y.
Referenced by continuation_solve().
00126 { 00127 // Be sure the tangent was not already initialized. 00128 libmesh_assert (!tangent_initialized); 00129 00130 // Compute delta_s_zero, the initial arclength travelled during the 00131 // first step. Here we assume that previous_u and lambda_old store 00132 // the previous solution and control parameter. You may need to 00133 // read in an old solution (or solve the non-continuation system) 00134 // first and call save_current_solution() before getting here. 00135 00136 // 1.) Compute delta_s_zero as ||u|| - ||u_old|| + ... 00137 // Compute norms of the current and previous solutions 00138 // Real norm_u = solution->l2_norm(); 00139 // Real norm_previous_u = previous_u->l2_norm(); 00140 00141 // if (!quiet) 00142 // { 00143 // std::cout << "norm_u=" << norm_u << std::endl; 00144 // std::cout << "norm_previous_u=" << norm_previous_u << std::endl; 00145 // } 00146 00147 // if (norm_u == norm_previous_u) 00148 // { 00149 // std::cerr << "Warning, it appears u and previous_u are the " 00150 // << "same, are you sure this is correct?" 00151 // << "It's possible you forgot to set one or the other..." 00152 // << std::endl; 00153 // } 00154 00155 // Real delta_s_zero = std::sqrt( 00156 // (norm_u - norm_previous_u)*(norm_u - norm_previous_u) + 00157 // (*continuation_parameter-old_continuation_parameter)* 00158 // (*continuation_parameter-old_continuation_parameter) 00159 // ); 00160 00161 // // 2.) Compute delta_s_zero as ||u -u_old|| + ... 00162 // *delta_u = *solution; 00163 // delta_u->add(-1., *previous_u); 00164 // delta_u->close(); 00165 // Real norm_delta_u = delta_u->l2_norm(); 00166 // Real norm_u = solution->l2_norm(); 00167 // Real norm_previous_u = previous_u->l2_norm(); 00168 00169 // // Scale norm_delta_u by the bigger of either norm_u or norm_previous_u 00170 // norm_delta_u /= std::max(norm_u, norm_previous_u); 00171 00172 // if (!quiet) 00173 // { 00174 // std::cout << "norm_u=" << norm_u << std::endl; 00175 // std::cout << "norm_previous_u=" << norm_previous_u << std::endl; 00176 // //std::cout << "norm_delta_u=" << norm_delta_u << std::endl; 00177 // std::cout << "norm_delta_u/max(|u|,|u_old|)=" << norm_delta_u << std::endl; 00178 // std::cout << "|norm_u-norm_previous_u|=" << std::abs(norm_u - norm_previous_u) << std::endl; 00179 // } 00180 00181 // const Real dlambda = *continuation_parameter-old_continuation_parameter; 00182 00183 // if (!quiet) 00184 // std::cout << "dlambda=" << dlambda << std::endl; 00185 00186 // Real delta_s_zero = std::sqrt( 00187 // (norm_delta_u*norm_delta_u) + 00188 // (dlambda*dlambda) 00189 // ); 00190 00191 // if (!quiet) 00192 // std::cout << "delta_s_zero=" << delta_s_zero << std::endl; 00193 00194 // 1.) + 2.) 00195 // // Now approximate the initial tangent d(lambda)/ds 00196 // this->dlambda_ds = (*continuation_parameter-old_continuation_parameter) / delta_s_zero; 00197 00198 00199 // // We can also approximate the deriv. wrt s by finite differences: 00200 // // du/ds = (u1 - u0) / delta_s_zero. 00201 // // FIXME: Use delta_u from above if we decide to keep that method. 00202 // *du_ds = *solution; 00203 // du_ds->add(-1., *previous_u); 00204 // du_ds->scale(1./delta_s_zero); 00205 // du_ds->close(); 00206 00207 00208 // 3.) Treating (u-previous_u)/(lambda - lambda_old) as an approximation to du/d(lambda), 00209 // we follow the same technique as Carnes and Shadid. 00210 // const Real dlambda = *continuation_parameter-old_continuation_parameter; 00211 // libmesh_assert (dlambda > 0.); 00212 00213 // // Use delta_u for temporary calculation of du/d(lambda) 00214 // *delta_u = *solution; 00215 // delta_u->add(-1., *previous_u); 00216 // delta_u->scale(1. / dlambda); 00217 // delta_u->close(); 00218 00219 // // Determine initial normalization parameter 00220 // const Real solution_size = std::max(solution->l2_norm(), previous_u->l2_norm()); 00221 // if (solution_size > 1.) 00222 // { 00223 // Theta = 1./solution_size; 00224 00225 // if (!quiet) 00226 // std::cout << "Setting Normalization Parameter Theta=" << Theta << std::endl; 00227 // } 00228 00229 // // Compute d(lambda)/ds 00230 // // The correct sign of d(lambda)/ds should be positive, since we assume that (lambda > lambda_old) 00231 // // but we could always double-check that as well. 00232 // Real norm_delta_u = delta_u->l2_norm(); 00233 // this->dlambda_ds = 1. / std::sqrt(1. + Theta*Theta*norm_delta_u*norm_delta_u); 00234 00235 // // Finally, compute du/ds = d(lambda)/ds * du/d(lambda) 00236 // *du_ds = *delta_u; 00237 // du_ds->scale(dlambda_ds); 00238 // du_ds->close(); 00239 00240 00241 // 4.) Use normalized arclength formula to estimate delta_s_zero 00242 // // Determine initial normalization parameter 00243 // set_Theta(); 00244 00245 // // Compute (normalized) delta_s_zero 00246 // *delta_u = *solution; 00247 // delta_u->add(-1., *previous_u); 00248 // delta_u->close(); 00249 // Real norm_delta_u = delta_u->l2_norm(); 00250 00251 // const Real dlambda = *continuation_parameter-old_continuation_parameter; 00252 00253 // if (!quiet) 00254 // std::cout << "dlambda=" << dlambda << std::endl; 00255 00256 // Real delta_s_zero = std::sqrt( 00257 // (Theta_LOCA*Theta_LOCA*Theta*norm_delta_u*norm_delta_u) + 00258 // (dlambda*dlambda) 00259 // ); 00260 // *du_ds = *delta_u; 00261 // du_ds->scale(1./delta_s_zero); 00262 // dlambda_ds = dlambda / delta_s_zero; 00263 00264 // if (!quiet) 00265 // { 00266 // std::cout << "delta_s_zero=" << delta_s_zero << std::endl; 00267 // std::cout << "initial d(lambda)/ds|_0 = " << dlambda_ds << std::endl; 00268 // std::cout << "initial ||du_ds||_0 = " << du_ds->l2_norm() << std::endl; 00269 // } 00270 00271 // // FIXME: Also store the initial finite-differenced approximation to -du/dlambda as y. 00272 // // We stick to the convention of storing negative y, since that is what we typically 00273 // // solve for anyway. 00274 // *y = *delta_u; 00275 // y->scale(-1./dlambda); 00276 // y->close(); 00277 00278 00279 00280 // 5.) Assume dlambda/ds_0 ~ 1/sqrt(2) and determine the value of Theta_LOCA which 00281 // will satisfy this criterion 00282 00283 // Initial change in parameter 00284 const Real dlambda = *continuation_parameter-old_continuation_parameter; 00285 libmesh_assert (dlambda != 0.0); 00286 00287 // Ideal initial value of dlambda_ds 00288 dlambda_ds = 1. / std::sqrt(2.); 00289 if (dlambda < 0.) 00290 dlambda_ds *= -1.; 00291 00292 // This also implies the initial value of ds 00293 ds_current = dlambda / dlambda_ds; 00294 00295 if (!quiet) 00296 std::cout << "Setting ds_current|_0=" << ds_current << std::endl; 00297 00298 // Set y = -du/dlambda using finite difference approximation 00299 *y = *solution; 00300 y->add(-1., *previous_u); 00301 y->scale(-1./dlambda); 00302 y->close(); 00303 const Real ynorm=y->l2_norm(); 00304 00305 // Finally, set the value of du_ds to be used in the upcoming 00306 // tangent calculation. du/ds = du/dlambda * dlambda/ds 00307 *du_ds = *y; 00308 du_ds->scale(-dlambda_ds); 00309 du_ds->close(); 00310 00311 // Determine additional solution normalization parameter 00312 // (Since we just set du/ds, it will be: ||du||*||du/ds||) 00313 set_Theta(); 00314 00315 // The value of Theta_LOCA which makes dlambda_ds = 1/sqrt(2), 00316 // assuming our Theta = ||du||^2. 00317 // Theta_LOCA = std::abs(dlambda); 00318 00319 // Assuming general Theta 00320 Theta_LOCA = std::sqrt(1./Theta/ynorm/ynorm); 00321 00322 00323 if (!quiet) 00324 { 00325 std::cout << "Setting initial Theta_LOCA = " << Theta_LOCA << std::endl; 00326 std::cout << "Theta_LOCA^2*Theta = " << Theta_LOCA*Theta_LOCA*Theta << std::endl; 00327 std::cout << "initial d(lambda)/ds|_0 = " << dlambda_ds << std::endl; 00328 std::cout << "initial ||du_ds||_0 = " << du_ds->l2_norm() << std::endl; 00329 } 00330 00331 00332 00333 // OK, we estimated the tangent at point u0. 00334 // Now, to estimate the tangent at point u1, we call the solve_tangent routine. 00335 00336 // Set the flag which tells us the method has been initialized. 00337 tangent_initialized = true; 00338 00339 solve_tangent(); 00340 00341 // Advance the solution and the parameter to the next value. 00342 update_solution(); 00343 }
| void System::local_dof_indices | ( | const unsigned int | var, | |
| std::set< unsigned int > & | var_indices | |||
| ) | const [inherited] |
Fills the std::set with the degrees of freedom on the local processor corresponding the the variable number passed in.
Definition at line 962 of file system.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), DofMap::dof_indices(), DofMap::end_dof(), DofMap::first_dof(), System::get_dof_map(), and System::get_mesh().
Referenced by System::discrete_var_norm().
00963 { 00964 // Make sure the set is clear 00965 var_indices.clear(); 00966 00967 std::vector<unsigned int> dof_indices; 00968 00969 // Begin the loop over the elements 00970 MeshBase::const_element_iterator el = 00971 this->get_mesh().active_local_elements_begin(); 00972 const MeshBase::const_element_iterator end_el = 00973 this->get_mesh().active_local_elements_end(); 00974 00975 const unsigned int 00976 first_local = this->get_dof_map().first_dof(), 00977 end_local = this->get_dof_map().end_dof(); 00978 00979 for ( ; el != end_el; ++el) 00980 { 00981 const Elem* elem = *el; 00982 this->get_dof_map().dof_indices (elem, dof_indices, var); 00983 00984 for(unsigned int i=0; i<dof_indices.size(); i++) 00985 { 00986 unsigned int dof = dof_indices[i]; 00987 00988 //If the dof is owned by the local processor 00989 if(first_local <= dof && dof < end_local) 00990 var_indices.insert(dof_indices[i]); 00991 } 00992 } 00993 }
| bool FEMSystem::mass_residual | ( | bool | request_jacobian, | |
| DiffContext & | context | |||
| ) | [virtual, inherited] |
Adds a mass vector contribution on elem to elem_residual. If this method receives request_jacobian = true, then it should compute elem_jacobian and return true if possible. If elem_jacobian has not been computed then the method should return false.
Most problems can use the FEMSystem::mass_residual implementation, which calculates the residual (u, phi_i) and jacobian (phi_i, phi_j); few users will need to reimplement this themselves. Using a custom mass matrix (e.g. for divergence-free elements or mass lumping) requires reimplementing mass_residual().
Reimplemented from DifferentiableSystem.
Definition at line 1021 of file fem_system.C.
References DifferentiableSystem::_time_evolving, DiffContext::dof_indices_var, DiffContext::elem_solution_derivative, DiffContext::elem_subjacobians, DiffContext::elem_subresiduals, FEMContext::element_fe_var, FEMContext::element_qrule, FEMContext::interior_value(), System::n_dofs(), QBase::n_points(), and System::n_vars().
01023 { 01024 FEMContext &context = libmesh_cast_ref<FEMContext&>(c); 01025 01026 unsigned int n_qpoints = context.element_qrule->n_points(); 01027 01028 for (unsigned int var = 0; var != this->n_vars(); ++var) 01029 { 01030 if (!_time_evolving[var]) 01031 continue; 01032 01033 const std::vector<Real> &JxW = 01034 context.element_fe_var[var]->get_JxW(); 01035 01036 const std::vector<std::vector<Real> > &phi = 01037 context.element_fe_var[var]->get_phi(); 01038 01039 const unsigned int n_dofs = context.dof_indices_var[var].size(); 01040 01041 DenseSubVector<Number> &Fu = *context.elem_subresiduals[var]; 01042 DenseSubMatrix<Number> &Kuu = *context.elem_subjacobians[var][var]; 01043 01044 for (unsigned int qp = 0; qp != n_qpoints; ++qp) 01045 { 01046 Number u = context.interior_value(var, qp); 01047 Number JxWxU = JxW[qp] * u; 01048 for (unsigned int i = 0; i != n_dofs; ++i) 01049 { 01050 Fu(i) += JxWxU * phi[i][qp]; 01051 if (request_jacobian && context.elem_solution_derivative) 01052 { 01053 libmesh_assert (context.elem_solution_derivative == 1.0); 01054 01055 Number JxWxPhiI = JxW[qp] * phi[i][qp]; 01056 Kuu(i,i) += JxWxPhiI * phi[i][qp]; 01057 for (unsigned int j = i+1; j < n_dofs; ++j) 01058 { 01059 Number Kij = JxWxPhiI * phi[j][qp]; 01060 Kuu(i,j) += Kij; 01061 Kuu(j,i) += Kij; 01062 } 01063 } 01064 } 01065 } 01066 } 01067 01068 return request_jacobian; 01069 }
| void FEMSystem::mesh_position_get | ( | ) | [inherited] |
Tells the FEMSystem to set the degree of freedom coefficients which should correspond to mesh nodal coordinates.
Definition at line 810 of file fem_system.C.
References FEMSystem::_mesh_sys, FEMSystem::_mesh_x_var, FEMSystem::_mesh_y_var, FEMSystem::_mesh_z_var, MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), FEMSystem::build_context(), DofMap::dof_indices(), DiffContext::dof_indices_var, FEMContext::elem, FEMContext::elem_position_get(), DiffContext::elem_subsolutions, System::get_dof_map(), System::get_mesh(), FEMSystem::init_context(), libMesh::invalid_uint, mesh, System::n_vars(), System::number(), System::solution, and System::update().
00811 { 00812 // This function makes no sense unless we've already picked out some 00813 // variable(s) to reflect mesh position coordinates 00814 if (_mesh_sys == libMesh::invalid_uint) 00815 libmesh_error(); 00816 00817 // We currently assume mesh variables are in our own system 00818 if (_mesh_sys != this->number()) 00819 libmesh_not_implemented(); 00820 00821 // Loop over every active mesh element on this processor 00822 const MeshBase& mesh = this->get_mesh(); 00823 00824 const DofMap& dof_map = this->get_dof_map(); 00825 00826 MeshBase::const_element_iterator el = 00827 mesh.active_local_elements_begin(); 00828 const MeshBase::const_element_iterator end_el = 00829 mesh.active_local_elements_end(); 00830 00831 AutoPtr<DiffContext> con = this->build_context(); 00832 FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con); 00833 this->init_context(_femcontext); 00834 00835 // Get the solution's mesh variables from every element 00836 for ( ; el != end_el; ++el) 00837 { 00838 _femcontext.elem = *el; 00839 00840 // Initialize the per-variable data for elem. 00841 for (unsigned int i=0; i != this->n_vars(); ++i) 00842 { 00843 dof_map.dof_indices (_femcontext.elem, 00844 _femcontext.dof_indices_var[i], i); 00845 } 00846 00847 _femcontext.elem_position_get(); 00848 if (_mesh_x_var != libMesh::invalid_uint) 00849 this->solution->insert(*_femcontext.elem_subsolutions[_mesh_x_var], 00850 _femcontext.dof_indices_var[_mesh_x_var]); 00851 if (_mesh_y_var != libMesh::invalid_uint) 00852 this->solution->insert(*_femcontext.elem_subsolutions[_mesh_y_var], 00853 _femcontext.dof_indices_var[_mesh_y_var]); 00854 if (_mesh_z_var != libMesh::invalid_uint) 00855 this->solution->insert(*_femcontext.elem_subsolutions[_mesh_z_var], 00856 _femcontext.dof_indices_var[_mesh_z_var]); 00857 } 00858 00859 // And make sure the current_local_solution is up to date too 00860 this->update(); 00861 }
| void FEMSystem::mesh_position_set | ( | ) | [inherited] |
Tells the FEMSystem to set the mesh nodal coordinates which should correspond to degree of freedom coefficients.
Definition at line 392 of file fem_system.C.
References FEMSystem::_mesh_sys, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), FEMSystem::build_context(), FEMContext::elem, FEMContext::elem_position_set(), System::get_mesh(), Elem::has_children(), MeshBase::is_serial(), mesh, System::number(), and FEMContext::reinit().
Referenced by FEMSystem::solve().
00393 { 00394 // If we don't need to move the mesh, we're done 00395 if (_mesh_sys != this->number()) 00396 return; 00397 00398 const MeshBase& mesh = this->get_mesh(); 00399 00400 // This code won't work on a parallelized mesh yet - 00401 // it won't get ancestor elements right. 00402 libmesh_assert(mesh.is_serial()); 00403 00404 AutoPtr<DiffContext> con = this->build_context(); 00405 FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con); 00406 00407 // Move every mesh element we can 00408 MeshBase::const_element_iterator el = 00409 mesh.active_elements_begin(); 00410 const MeshBase::const_element_iterator end_el = 00411 mesh.active_elements_end(); 00412 00413 for ( ; el != end_el; ++el) 00414 { 00415 _femcontext.reinit(*this, *el); 00416 00417 // This code won't handle moving subactive elements 00418 libmesh_assert(!_femcontext.elem->has_children()); 00419 00420 _femcontext.elem_position_set(0.); 00421 } 00422 }
| void FEMSystem::mesh_x_position | ( | unsigned int | sysnum, | |
| unsigned int | var | |||
| ) | [virtual, inherited] |
Tells the FEMSystem that variable var from system number sysnum should be used to update the x coordinate of mesh nodes, in problems where the mesh itself is expected to move in time.
The system with mesh coordinate data (which may be this system itself, for fully coupled moving mesh problems) is currently assumed to have new (end of time step) mesh coordinates stored in solution, old (beginning of time step) mesh coordinates stored in _old_nonlinear_solution, and constant velocity motion during each time step.
Activating this function ensures that local (but not neighbor!) element geometry is correctly repositioned when evaluating element residuals.
Definition at line 774 of file fem_system.C.
References FEMSystem::_mesh_sys, FEMSystem::_mesh_x_var, libMesh::invalid_uint, and System::number().
00775 { 00776 if (_mesh_sys != libMesh::invalid_uint && _mesh_sys != sysnum) 00777 libmesh_error(); 00778 if (sysnum != this->number()) 00779 libmesh_not_implemented(); 00780 _mesh_sys = sysnum; 00781 _mesh_x_var = var; 00782 }
| void FEMSystem::mesh_y_position | ( | unsigned int | sysnum, | |
| unsigned int | var | |||
| ) | [virtual, inherited] |
Tells the FEMSystem that variable var from system number sysnum should be used to update the y coordinate of mesh nodes.
Definition at line 786 of file fem_system.C.
References FEMSystem::_mesh_sys, FEMSystem::_mesh_y_var, libMesh::invalid_uint, and System::number().
00787 { 00788 if (_mesh_sys != libMesh::invalid_uint && _mesh_sys != sysnum) 00789 libmesh_error(); 00790 if (sysnum != this->number()) 00791 libmesh_not_implemented(); 00792 _mesh_sys = sysnum; 00793 _mesh_y_var = var; 00794 }
| void FEMSystem::mesh_z_position | ( | unsigned int | sysnum, | |
| unsigned int | var | |||
| ) | [virtual, inherited] |
Tells the FEMSystem that variable var from system number sysnum should be used to update the z coordinate of mesh nodes.
Definition at line 798 of file fem_system.C.
References FEMSystem::_mesh_sys, FEMSystem::_mesh_z_var, libMesh::invalid_uint, and System::number().
00799 { 00800 if (_mesh_sys != libMesh::invalid_uint && _mesh_sys != sysnum) 00801 libmesh_error(); 00802 if (sysnum != this->number()) 00803 libmesh_not_implemented(); 00804 _mesh_sys = sysnum; 00805 _mesh_z_var = var; 00806 }
| unsigned int System::n_active_dofs | ( | ) | const [inline, inherited] |
Returns the number of active degrees of freedom for this System.
Definition at line 1442 of file system.h.
References System::n_constrained_dofs(), and System::n_dofs().
01443 { 01444 return this->n_dofs() - this->n_constrained_dofs(); 01445 }
| unsigned int System::n_constrained_dofs | ( | ) | const [inherited] |
- Returns:
- the number of constrained degrees of freedom in the system.
Definition at line 95 of file system.C.
References System::_dof_map.
Referenced by System::get_info(), and System::n_active_dofs().
00096 { 00097 #ifdef LIBMESH_ENABLE_AMR 00098 00099 return _dof_map->n_constrained_dofs(); 00100 00101 #else 00102 00103 return 0; 00104 00105 #endif 00106 }
| unsigned int System::n_dofs | ( | ) | const [inherited] |
- Returns:
- the number of degrees of freedom in the system
Definition at line 88 of file system.C.
References System::_dof_map.
Referenced by System::add_vector(), System::current_solution(), System::get_info(), System::init_data(), FEMSystem::mass_residual(), System::n_active_dofs(), System::ProjectVector::operator()(), System::project_vector(), System::read_legacy_data(), System::reinit(), System::restrict_vectors(), and UnsteadySolver::solve().
00089 { 00090 return _dof_map->n_dofs(); 00091 }
| unsigned int System::n_local_dofs | ( | ) | const [inherited] |
- Returns:
- the number of degrees of freedom local to this processor
Definition at line 110 of file system.C.
References System::_dof_map, and libMesh::processor_id().
Referenced by System::add_vector(), System::get_info(), System::init_data(), System::project_vector(), System::read_serialized_blocked_dof_objects(), System::reinit(), System::restrict_vectors(), and UnsteadySolver::solve().
00111 { 00112 return _dof_map->n_dofs_on_processor (libMesh::processor_id()); 00113 }
| unsigned int ImplicitSystem::n_matrices | ( | ) | const [inline, inherited] |
- Returns:
- the number of matrices handled by this system
Definition at line 376 of file implicit_system.h.
References ImplicitSystem::_matrices.
00377 { 00378 return _matrices.size(); 00379 }
| static unsigned int ReferenceCounter::n_objects | ( | ) | [inline, static, inherited] |
Prints the number of outstanding (created, but not yet destroyed) objects.
Definition at line 76 of file reference_counter.h.
References ReferenceCounter::_n_objects.
00077 { return _n_objects; }
| unsigned int System::n_vars | ( | ) | const [inline, inherited] |
- Returns:
- the number of variables in the system
Definition at line 1396 of file system.h.
References System::_variables.
Referenced by System::add_variable(), EquationSystems::build_discontinuous_solution_vector(), EquationSystems::build_solution_vector(), System::calculate_norm(), DiffContext::DiffContext(), JumpErrorEstimator::estimate_error(), ExactErrorEstimator::estimate_error(), ErrorEstimator::estimate_errors(), FEMSystem::eulerian_residual(), ExactSolution::ExactSolution(), FEMContext::FEMContext(), System::get_info(), System::init(), FEMSystem::init_context(), DifferentiableSystem::init_data(), FEMSystem::mass_residual(), FEMSystem::mesh_position_get(), System::ProjectVector::operator()(), PatchRecoveryErrorEstimator::EstimateError::operator()(), System::project_vector(), System::re_update(), System::read_header(), System::read_legacy_data(), System::read_parallel_data(), System::read_serialized_vector(), System::reinit(), FEMContext::reinit(), EquationSystems::reinit(), HPCoarsenTest::select_refinement(), VTKIO::solution_to_vtk(), System::write_header(), System::write_parallel_data(), System::write_serialized_vector(), and System::zero_variable().
01397 { 01398 return _variables.size(); 01399 }
| unsigned int System::n_vectors | ( | ) | const [inline, inherited] |
- Returns:
- the number of vectors (in addition to the solution) handled by this system This is the size of the
_vectorsmap
Definition at line 1458 of file system.h.
References System::_vectors.
Referenced by ExplicitSystem::add_system_rhs(), System::compare(), System::get_info(), System::read_header(), and System::write_header().
01459 { 01460 return _vectors.size(); 01461 }
| const std::string & System::name | ( | ) | const [inline, inherited] |
- Returns:
- the system name.
Definition at line 1324 of file system.h.
References System::_sys_name.
Referenced by System::compare(), ExactErrorEstimator::estimate_error(), ExactSolution::ExactSolution(), ExactErrorEstimator::find_squared_element_error(), System::get_info(), System::ProjectVector::operator()(), System::project_vector(), FrequencySystem::solve(), System::user_assembly(), System::user_constrain(), System::user_initialization(), System::user_QOI(), System::user_QOI_derivative(), System::write_header(), System::write_parallel_data(), and System::write_serialized_data().
01325 { 01326 return _sys_name; 01327 }
| unsigned int System::number | ( | ) | const [inline, inherited] |
- Returns:
- the system number.
Definition at line 1332 of file system.h.
References System::_sys_number.
Referenced by System::add_variable(), FEMSystem::eulerian_residual(), FEMSystem::mesh_position_get(), FEMSystem::mesh_position_set(), FEMSystem::mesh_x_position(), FEMSystem::mesh_y_position(), FEMSystem::mesh_z_position(), FEMSystem::numerical_jacobian(), System::read_legacy_data(), System::read_parallel_data(), System::read_serialized_blocked_dof_objects(), HPCoarsenTest::select_refinement(), System::write_parallel_data(), System::write_serialized_blocked_dof_objects(), and System::zero_variable().
01333 { 01334 return _sys_number; 01335 }
| void FEMSystem::numerical_elem_jacobian | ( | FEMContext & | context | ) | [protected, inherited] |
Uses the results of multiple element_residual() calls to numerically differentiate the corresponding jacobian on an element.
Definition at line 724 of file fem_system.C.
References TimeSolver::element_residual(), and FEMSystem::numerical_jacobian().
Referenced by FEMSystem::assembly().
00725 { 00726 START_LOG("numerical_elem_jacobian()", "FEMSystem"); 00727 this->numerical_jacobian(&TimeSolver::element_residual, context); 00728 STOP_LOG("numerical_elem_jacobian()", "FEMSystem"); 00729 }
| void FEMSystem::numerical_jacobian | ( | TimeSolverResPtr | res, | |
| FEMContext & | context | |||
| ) | [protected, inherited] |
Uses the results of multiple res calls to numerically differentiate the corresponding jacobian.
Definition at line 621 of file fem_system.C.
References FEMSystem::_mesh_sys, FEMSystem::_mesh_x_var, FEMSystem::_mesh_y_var, FEMSystem::_mesh_z_var, DiffContext::dof_indices, DiffContext::dof_indices_var, FEMContext::elem, DiffContext::elem_jacobian, DiffContext::elem_residual, DiffContext::elem_solution, Elem::hmin(), libMesh::invalid_uint, libmesh_real(), System::number(), FEMSystem::numerical_jacobian_h, and Elem::point().
Referenced by FEMSystem::numerical_elem_jacobian(), and FEMSystem::numerical_side_jacobian().
00623 { 00624 // Logging is done by numerical_elem_jacobian 00625 // or numerical_side_jacobian 00626 00627 DenseVector<Number> original_residual(context.elem_residual); 00628 DenseVector<Number> backwards_residual(context.elem_residual); 00629 DenseMatrix<Number> numerical_jacobian(context.elem_jacobian); 00630 #ifdef DEBUG 00631 DenseMatrix<Number> old_jacobian(context.elem_jacobian); 00632 #endif 00633 00634 Real numerical_point_h = 0.; 00635 if (_mesh_sys == this->number()) 00636 numerical_point_h = numerical_jacobian_h * context.elem->hmin(); 00637 00638 for (unsigned int j = 0; j != context.dof_indices.size(); ++j) 00639 { 00640 // Take the "minus" side of a central differenced first derivative 00641 Number original_solution = context.elem_solution(j); 00642 context.elem_solution(j) -= numerical_jacobian_h; 00643 00644 // Make sure to catch any moving mesh terms 00645 // FIXME - this could be less ugly 00646 Real *coord = NULL; 00647 if (_mesh_sys == this->number()) 00648 { 00649 if (_mesh_x_var != libMesh::invalid_uint) 00650 for (unsigned int k = 0; 00651 k != context.dof_indices_var[_mesh_x_var].size(); ++k) 00652 if (context.dof_indices_var[_mesh_x_var][k] == 00653 context.dof_indices[j]) 00654 coord = &(context.elem->point(k)(0)); 00655 if (_mesh_y_var != libMesh::invalid_uint) 00656 for (unsigned int k = 0; 00657 k != context.dof_indices_var[_mesh_y_var].size(); ++k) 00658 if (context.dof_indices_var[_mesh_y_var][k] == 00659 context.dof_indices[j]) 00660 coord = &(context.elem->point(k)(1)); 00661 if (_mesh_z_var != libMesh::invalid_uint) 00662 for (unsigned int k = 0; 00663 k != context.dof_indices_var[_mesh_z_var].size(); ++k) 00664 if (context.dof_indices_var[_mesh_z_var][k] == 00665 context.dof_indices[j]) 00666 coord = &(context.elem->point(k)(2)); 00667 } 00668 if (coord) 00669 { 00670 // We have enough information to scale the perturbations 00671 // here appropriately 00672 context.elem_solution(j) = original_solution - numerical_point_h; 00673 *coord = libmesh_real(context.elem_solution(j)); 00674 } 00675 00676 context.elem_residual.zero(); 00677 ((*time_solver).*(res))(false, context); 00678 #ifdef DEBUG 00679 libmesh_assert(old_jacobian == context.elem_jacobian); 00680 #endif 00681 backwards_residual = context.elem_residual; 00682 00683 // Take the "plus" side of a central differenced first derivative 00684 context.elem_solution(j) = original_solution + numerical_jacobian_h; 00685 if (coord) 00686 { 00687 context.elem_solution(j) = original_solution + numerical_point_h; 00688 *coord = libmesh_real(context.elem_solution(j)); 00689 } 00690 context.elem_residual.zero(); 00691 ((*time_solver).*(res))(false, context); 00692 #ifdef DEBUG 00693 libmesh_assert(old_jacobian == context.elem_jacobian); 00694 #endif 00695 00696 context.elem_solution(j) = original_solution; 00697 if (coord) 00698 { 00699 *coord = libmesh_real(context.elem_solution(j)); 00700 for (unsigned int i = 0; i != context.dof_indices.size(); ++i) 00701 { 00702 numerical_jacobian(i,j) = 00703 (context.elem_residual(i) - backwards_residual(i)) / 00704 2. / numerical_point_h; 00705 } 00706 } 00707 else 00708 { 00709 for (unsigned int i = 0; i != context.dof_indices.size(); ++i) 00710 { 00711 numerical_jacobian(i,j) = 00712 (context.elem_residual(i) - backwards_residual(i)) / 00713 2. / numerical_jacobian_h; 00714 } 00715 } 00716 } 00717 00718 context.elem_residual = original_residual; 00719 context.elem_jacobian = numerical_jacobian; 00720 }
| void FEMSystem::numerical_side_jacobian | ( | FEMContext & | context | ) | [protected, inherited] |
Uses the results of multiple side_residual() calls to numerically differentiate the corresponding jacobian on an element's side.
Definition at line 733 of file fem_system.C.
References FEMSystem::numerical_jacobian(), and TimeSolver::side_residual().
Referenced by FEMSystem::assembly().
00734 { 00735 START_LOG("numerical_side_jacobian()", "FEMSystem"); 00736 this->numerical_jacobian(&TimeSolver::side_residual, context); 00737 STOP_LOG("numerical_side_jacobian()", "FEMSystem"); 00738 }
| void FEMSystem::postprocess | ( | ) | [virtual, inherited] |
Runs a postprocessing loop over all elements, and if postprocess_sides is true over all sides.
Implements DifferentiableSystem.
Definition at line 426 of file fem_system.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), FEMSystem::build_context(), DifferentiableSystem::compute_internal_sides, FEMContext::elem, DifferentiableSystem::element_postprocess(), FEMSystem::fe_reinit_during_postprocess, System::get_mesh(), mesh, Elem::n_sides(), Elem::neighbor(), DifferentiableSystem::postprocess_sides, FEMContext::reinit(), FEMContext::side, FEMContext::side_fe, DifferentiableSystem::side_postprocess(), and System::update().
00427 { 00428 START_LOG("postprocess()", "FEMSystem"); 00429 00430 const MeshBase& mesh = this->get_mesh(); 00431 00432 this->update(); 00433 00434 AutoPtr<DiffContext> con = this->build_context(); 00435 FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con); 00436 00437 // Loop over every active mesh element on this processor 00438 MeshBase::const_element_iterator el = 00439 mesh.active_local_elements_begin(); 00440 const MeshBase::const_element_iterator end_el = 00441 mesh.active_local_elements_end(); 00442 00443 for ( ; el != end_el; ++el) 00444 { 00445 _femcontext.reinit(*this, *el); 00446 00447 // Optionally initialize all the interior FE objects on elem. 00448 // if (fe_reinit_during_postprocess) 00449 // _femcontext.elem_fe_reinit(); 00450 00451 this->element_postprocess(_femcontext); 00452 00453 for (_femcontext.side = 0; 00454 _femcontext.side != _femcontext.elem->n_sides(); 00455 ++_femcontext.side) 00456 { 00457 // Don't compute on non-boundary sides unless requested 00458 if (!postprocess_sides || 00459 (!compute_internal_sides && 00460 _femcontext.elem->neighbor(_femcontext.side) != NULL)) 00461 continue; 00462 00463 // Optionally initialize all the interior FE objects on elem/side. 00464 // Logging of FE::reinit is done in the FE functions 00465 if (fe_reinit_during_postprocess) 00466 { 00467 std::map<FEType, FEBase *>::iterator fe_end = 00468 _femcontext.side_fe.end(); 00469 for (std::map<FEType, FEBase *>::iterator i = 00470 _femcontext.side_fe.begin(); 00471 i != fe_end; ++i) 00472 { 00473 i->second->reinit(_femcontext.elem, _femcontext.side); 00474 } 00475 } 00476 00477 this->side_postprocess(_femcontext); 00478 } 00479 } 00480 00481 STOP_LOG("postprocess()", "FEMSystem"); 00482 }
| void ReferenceCounter::print_info | ( | ) | [static, inherited] |
Prints the reference information to std::cout.
Definition at line 83 of file reference_counter.C.
References ReferenceCounter::get_info().
00084 { 00085 #if defined(LIBMESH_ENABLE_REFERENCE_COUNTING) && defined(DEBUG) 00086 00087 std::cout << ReferenceCounter::get_info(); 00088 00089 #endif 00090 }
| void System::project_solution | ( | Number | fptrconst Point &p,const Parameters ¶meters,const std::string &sys_name,const std::string &unknown_name, | |
| Gradient | gptrconst Point &p,const Parameters ¶meters,const std::string &sys_name,const std::string &unknown_name, | |||
| Parameters & | parameters | |||
| ) | const [inherited] |
Projects the continuous functions onto the current solution.
This method projects an analytic function onto the solution via L2 projections and nodal interpolations on each element.
Definition at line 237 of file system_projection.C.
References System::current_local_solution, System::project_vector(), and System::solution.
00246 { 00247 this->project_vector(fptr, gptr, parameters, *solution); 00248 00249 solution->localize(*current_local_solution); 00250 }
| bool& System::project_solution_on_reinit | ( | void | ) | [inline, inherited] |
Tells the System whether or not to project the solution vector onto new grids when the system is reinitialized. The solution will be projected unless project_solution_on_reinit() = false is called.
Definition at line 451 of file system.h.
References System::_solution_projection.
00452 { return _solution_projection; }
| void System::project_vector | ( | const NumericVector< Number > & | old_v, | |
| NumericVector< Number > & | new_v | |||
| ) | const [protected, inherited] |
Projects the vector defined on the old mesh onto the new mesh. The original vector is unchanged and the new vector is passed through the second argument.
This method projects the vector via L2 projections or nodal interpolations on each element.
This method projects a solution from an old mesh to a current, refined mesh. The input vector old_v gives the solution on the old mesh, while the new_v gives the solution (to be computed) on the new mesh.
Definition at line 60 of file system_projection.C.
References NumericVector< T >::clear(), NumericVector< T >::close(), DofMap::enforce_constraints_exactly(), FEType::family, AutoPtr< Tp >::get(), System::get_dof_map(), System::get_mesh(), libMeshEnums::GHOSTED, NumericVector< T >::init(), NumericVector< T >::local_size(), NumericVector< T >::localize(), System::n_dofs(), System::n_local_dofs(), libMesh::n_processors(), System::n_vars(), libMeshEnums::PARALLEL, Threads::parallel_for(), Threads::parallel_reduce(), libMesh::processor_id(), libMeshEnums::SCALAR, DofMap::SCALAR_dof_indices(), System::BuildProjectionList::send_list, libMeshEnums::SERIAL, NumericVector< T >::set(), NumericVector< T >::size(), System::Variable::type(), NumericVector< T >::type(), System::BuildProjectionList::unique(), and System::variable().
00062 { 00063 START_LOG ("project_vector()", "System"); 00064 00071 new_v.clear(); 00072 00073 #ifdef LIBMESH_ENABLE_AMR 00074 00075 // Resize the new vector and get a serial version. 00076 NumericVector<Number> *new_vector_ptr = NULL; 00077 AutoPtr<NumericVector<Number> > new_vector_built; 00078 NumericVector<Number> *local_old_vector; 00079 AutoPtr<NumericVector<Number> > local_old_vector_built; 00080 const NumericVector<Number> *old_vector_ptr = NULL; 00081 00082 ConstElemRange active_local_elem_range 00083 (this->get_mesh().active_local_elements_begin(), 00084 this->get_mesh().active_local_elements_end()); 00085 00086 // If the old vector was uniprocessor, make the new 00087 // vector uniprocessor 00088 if (old_v.type() == SERIAL) 00089 { 00090 new_v.init (this->n_dofs(), false, SERIAL); 00091 new_vector_ptr = &new_v; 00092 old_vector_ptr = &old_v; 00093 } 00094 00095 // Otherwise it is a parallel, distributed vector, which 00096 // we need to localize. 00097 else if (old_v.type() == PARALLEL) 00098 { 00099 // Build a send list for efficient localization 00100 BuildProjectionList projection_list(*this); 00101 Threads::parallel_reduce (active_local_elem_range, 00102 projection_list); 00103 00104 // Create a sorted, unique send_list 00105 projection_list.unique(); 00106 00107 new_v.init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL); 00108 new_vector_built = NumericVector<Number>::build(); 00109 local_old_vector_built = NumericVector<Number>::build(); 00110 new_vector_ptr = new_vector_built.get(); 00111 local_old_vector = local_old_vector_built.get(); 00112 new_vector_ptr->init(this->n_dofs(), false, SERIAL); 00113 local_old_vector->init(old_v.size(), false, SERIAL); 00114 old_v.localize(*local_old_vector, projection_list.send_list); 00115 local_old_vector->close(); 00116 old_vector_ptr = local_old_vector; 00117 } 00118 else if (old_v.type() == GHOSTED) 00119 { 00120 // Build a send list for efficient localization 00121 BuildProjectionList projection_list(*this); 00122 Threads::parallel_reduce (active_local_elem_range, 00123 projection_list); 00124 00125 // Create a sorted, unique send_list 00126 projection_list.unique(); 00127 00128 new_v.init (this->n_dofs(), this->n_local_dofs(), 00129 this->get_dof_map().get_send_list(), false, GHOSTED); 00130 00131 local_old_vector_built = NumericVector<Number>::build(); 00132 new_vector_ptr = &new_v; 00133 local_old_vector = local_old_vector_built.get(); 00134 local_old_vector->init(old_v.size(), old_v.local_size(), 00135 projection_list.send_list, false, GHOSTED); 00136 old_v.localize(*local_old_vector, projection_list.send_list); 00137 local_old_vector->close(); 00138 old_vector_ptr = local_old_vector; 00139 } 00140 else // unknown old_v.type() 00141 { 00142 std::cerr << "ERROR: Unknown old_v.type() == " << old_v.type() 00143 << std::endl; 00144 libmesh_error(); 00145 } 00146 00147 // Note that the above will have zeroed the new_vector. 00148 // Just to be sure, assert that new_vector_ptr and old_vector_ptr 00149 // were successfully set before trying to deref them. 00150 libmesh_assert(new_vector_ptr); 00151 libmesh_assert(old_vector_ptr); 00152 00153 NumericVector<Number> &new_vector = *new_vector_ptr; 00154 const NumericVector<Number> &old_vector = *old_vector_ptr; 00155 00156 Threads::parallel_for (active_local_elem_range, 00157 ProjectVector(*this, 00158 old_vector, 00159 new_vector) 00160 ); 00161 00162 // Copy the SCALAR dofs from old_vector to new_vector 00163 // Note: We assume that all SCALAR dofs are on the 00164 // processor with highest ID 00165 if(libMesh::processor_id() == (libMesh::n_processors()-1)) 00166 { 00167 const DofMap& dof_map = this->get_dof_map(); 00168 for (unsigned int var=0; var<this->n_vars(); var++) 00169 if(this->variable(var).type().family == SCALAR) 00170 { 00171 // We can just map SCALAR dofs directly across 00172 std::vector<unsigned int> new_SCALAR_indices, old_SCALAR_indices; 00173 dof_map.SCALAR_dof_indices (new_SCALAR_indices, var, false); 00174 dof_map.SCALAR_dof_indices (old_SCALAR_indices, var, true); 00175 const unsigned int new_n_dofs = new_SCALAR_indices.size(); 00176 00177 for (unsigned int i=0; i<new_n_dofs; i++) 00178 { 00179 new_vector.set( new_SCALAR_indices[i], old_vector(old_SCALAR_indices[i]) ); 00180 } 00181 } 00182 } 00183 00184 new_vector.close(); 00185 00186 // If the old vector was serial, we probably need to send our values 00187 // to other processors 00188 // 00189 // FIXME: I'm not sure how to make a NumericVector do that without 00190 // creating a temporary parallel vector to use localize! - RHS 00191 if (old_v.type() == SERIAL) 00192 { 00193 AutoPtr<NumericVector<Number> > dist_v = NumericVector<Number>::build(); 00194 dist_v->init(this->n_dofs(), this->n_local_dofs(), false, PARALLEL); 00195 dist_v->close(); 00196 00197 for (unsigned int i=0; i!=dist_v->size(); i++) 00198 if (new_vector(i) != 0.0) 00199 dist_v->set(i, new_vector(i)); 00200 00201 dist_v->close(); 00202 00203 dist_v->localize (new_v, this->get_dof_map().get_send_list()); 00204 new_v.close(); 00205 } 00206 // If the old vector was parallel, we need to update it 00207 // and free the localized copies 00208 else if (old_v.type() == PARALLEL) 00209 { 00210 // We may have to set dof values that this processor doesn't 00211 // own in certain special cases, like LAGRANGE FIRST or 00212 // HERMITE THIRD elements on second-order meshes 00213 for (unsigned int i=0; i!=new_v.size(); i++) 00214 if (new_vector(i) != 0.0) 00215 new_v.set(i, new_vector(i)); 00216 new_v.close(); 00217 } 00218 00219 this->get_dof_map().enforce_constraints_exactly(*this, &new_v); 00220 00221 #else 00222 00223 // AMR is disabled: simply copy the vector 00224 new_v = old_v; 00225 00226 #endif // #ifdef LIBMESH_ENABLE_AMR 00227 00228 STOP_LOG("project_vector()", "System"); 00229 }
| void System::project_vector | ( | NumericVector< Number > & | vector | ) | const [protected, inherited] |
Projects the vector defined on the old mesh onto the new mesh.
Definition at line 43 of file system_projection.C.
References NumericVector< T >::clone(), and System::project_vector().
00044 { 00045 // Create a copy of the vector, which currently 00046 // contains the old data. 00047 AutoPtr<NumericVector<Number> > 00048 old_vector (vector.clone()); 00049 00050 // Project the old vector to the new vector 00051 this->project_vector (*old_vector, vector); 00052 }
| void System::project_vector | ( | Number | fptrconst Point &p,const Parameters ¶meters,const std::string &sys_name,const std::string &unknown_name, | |
| Gradient | gptrconst Point &p,const Parameters ¶meters,const std::string &sys_name,const std::string &unknown_name, | |||
| Parameters & | parameters, | |||
| NumericVector< Number > & | new_vector | |||
| ) | const [inherited] |
Projects the continuous functions onto the current mesh.
This method projects an analytic function via L2 projections and nodal interpolations on each element.
Definition at line 258 of file system_projection.C.
References NumericVector< T >::close(), DofMap::enforce_constraints_exactly(), FEType::family, System::get_dof_map(), System::get_mesh(), libMesh::n_processors(), System::n_vars(), System::name(), Threads::parallel_for(), libMesh::processor_id(), libMeshEnums::SCALAR, DofMap::SCALAR_dof_indices(), NumericVector< T >::set(), System::Variable::type(), System::variable(), and System::variable_name().
Referenced by System::project_solution(), System::project_vector(), and System::restrict_vectors().
00268 { 00269 START_LOG ("project_vector()", "System"); 00270 00271 Threads::parallel_for (ConstElemRange (this->get_mesh().active_local_elements_begin(), 00272 this->get_mesh().active_local_elements_end(), 00273 1000), 00274 ProjectSolution(*this, 00275 fptr, 00276 gptr, 00277 parameters, 00278 new_vector) 00279 ); 00280 00281 // Also, load values into the SCALAR dofs 00282 // Note: We assume that all SCALAR dofs are on the 00283 // processor with highest ID 00284 if(libMesh::processor_id() == (libMesh::n_processors()-1)) 00285 { 00286 const DofMap& dof_map = this->get_dof_map(); 00287 for (unsigned int var=0; var<this->n_vars(); var++) 00288 if(this->variable(var).type().family == SCALAR) 00289 { 00290 std::vector<unsigned int> SCALAR_indices; 00291 dof_map.SCALAR_dof_indices (SCALAR_indices, var); 00292 const unsigned int n_SCALAR_dofs = SCALAR_indices.size(); 00293 00294 for (unsigned int i=0; i<n_SCALAR_dofs; i++) 00295 { 00296 const unsigned int index = SCALAR_indices[i]; 00297 00298 // We pass the point (i,0,0) to the fptr to distinguish 00299 // the different scalars within the SCALAR variable 00300 Point p_i(i,0,0); 00301 new_vector.set( index, fptr(p_i, 00302 parameters, 00303 this->name(), 00304 this->variable_name(var)) 00305 ); 00306 } 00307 } 00308 } 00309 00310 new_vector.close(); 00311 00312 #ifdef LIBMESH_ENABLE_AMR 00313 this->get_dof_map().enforce_constraints_exactly(*this, &new_vector); 00314 #endif 00315 00316 STOP_LOG("project_vector()", "System"); 00317 }
| void System::prolong_vectors | ( | ) | [virtual, inherited] |
Prolong vectors after the mesh has refined
Definition at line 255 of file system.C.
References System::restrict_vectors().
Referenced by EquationSystems::reinit().
00256 { 00257 #ifdef LIBMESH_ENABLE_AMR 00258 // Currently project_vector handles both restriction and prolongation 00259 this->restrict_vectors(); 00260 #endif 00261 }
| void ImplicitSystem::qoi_parameter_hessian | ( | const QoISet & | qoi_indices, | |
| const ParameterVector & | parameters, | |||
| SensitivityData & | hessian | |||
| ) | [virtual, inherited] |
For each of the system's quantities of interest q in qoi[qoi_indices], and for a vector of parameters p, the parameter sensitivity Hessian H_ij is defined as H_ij = (d^2 q)/(d p_i d p_j) This Hessian is the output of this method, where for each q_i, H_jk is stored in hessian.second_derivative(i,j,k).
Reimplemented from System.
Definition at line 1004 of file implicit_system.C.
References SensitivityData::allocate_hessian_data(), QoISet::has_index(), SensitivityData::second_derivative(), and ParameterVector::size().
01007 { 01008 // We currently get partial derivatives via finite differencing 01009 const Real delta_p = TOLERANCE; 01010 01011 // We'll use one temporary vector for matrix-vector-vector products 01012 AutoPtr<NumericVector<Number> > tempvec = this->solution->zero_clone(); 01013 01014 // And another temporary vector to hold a copy of the true solution 01015 // so we can safely perturb this->solution. 01016 AutoPtr<NumericVector<Number> > oldsolution = this->solution->clone(); 01017 01018 const unsigned int Np = parameters.size(); 01019 const unsigned int Nq = qoi.size(); 01020 01021 // For each quantity of interest q, the parameter sensitivity 01022 // Hessian is defined as q''_{kl} = {d^2 q}/{d p_k d p_l}. 01023 // 01024 // We calculate it from values and partial derivatives of the 01025 // quantity of interest function Q, solution u, adjoint solution z, 01026 // and residual R, as: 01027 // 01028 // q''_{kl} = 01029 // Q''_{kl} + Q''_{uk}(u)*u'_l + Q''_{ul}(u) * u'_k + 01030 // Q''_{uu}(u)*u'_k*u'_l - 01031 // R''_{kl}(u,z) - 01032 // R''_{uk}(u,z)*u'_l - R''_{ul}(u,z)*u'_k - 01033 // R''_{uu}(u,z)*u'_k*u'_l 01034 // 01035 // See the adjoints model document for more details. 01036 01037 // We first do an adjoint solve to get z for each quantity of 01038 // interest 01039 01040 this->adjoint_solve(qoi_indices); 01041 01042 // And a sensitivity solve to get u_k for each parameter 01043 this->sensitivity_solve(parameters); 01044 01045 // Get ready to fill in second derivatives: 01046 sensitivities.allocate_hessian_data(qoi_indices, *this, parameters); 01047 01048 for (unsigned int k=0; k != Np; ++k) 01049 { 01050 Number old_parameterk = *parameters[k]; 01051 01052 // The Hessian is symmetric, so we just calculate the lower 01053 // triangle and the diagonal, and we get the upper triangle from 01054 // the transpose of the lower 01055 01056 for (unsigned int l=0; l != k+1; ++l) 01057 { 01058 // The second partial derivatives with respect to parameters 01059 // are all calculated via a central finite difference 01060 // stencil: 01061 // F''_{kl} ~= (F(p+dp*e_k+dp*e_l) - F(p+dp*e_k-dp*e_l) - 01062 // F(p-dp*e_k+dp*e_l) - F(p-dp*e_k-dp*e_l))/(4*dp^2) 01063 // We will add Q''_{kl}(u) and subtract R''_{kl}(u,z) at the 01064 // same time. 01065 01066 Number old_parameterl = *parameters[l]; 01067 01068 *parameters[k] = old_parameterk + delta_p; 01069 *parameters[l] = old_parameterl + delta_p; 01070 this->assemble_qoi(qoi_indices); 01071 this->assembly(true, false); 01072 std::vector<Number> partial2q_term = this->qoi; 01073 std::vector<Number> partial2R_term(this->qoi.size()); 01074 for (unsigned int i=0; i != Nq; ++i) 01075 if (qoi_indices.has_index(i)) 01076 partial2R_term[i] = this->rhs->dot(this->get_adjoint_solution(i)); 01077 01078 *parameters[l] = old_parameterl - delta_p; 01079 this->assemble_qoi(qoi_indices); 01080 this->assembly(true, false); 01081 for (unsigned int i=0; i != Nq; ++i) 01082 if (qoi_indices.has_index(i)) 01083 { 01084 partial2q_term[i] -= this->qoi[i]; 01085 partial2R_term[i] -= this->rhs->dot(this->get_adjoint_solution(i)); 01086 } 01087 01088 *parameters[k] = old_parameterk - delta_p; 01089 this->assemble_qoi(qoi_indices); 01090 this->assembly(true, false); 01091 for (unsigned int i=0; i != Nq; ++i) 01092 if (qoi_indices.has_index(i)) 01093 { 01094 partial2q_term[i] += this->qoi[i]; 01095 partial2R_term[i] += this->rhs->dot(this->get_adjoint_solution(i)); 01096 } 01097 01098 *parameters[l] = old_parameterl + delta_p; 01099 this->assemble_qoi(qoi_indices); 01100 this->assembly(true, false); 01101 for (unsigned int i=0; i != Nq; ++i) 01102 if (qoi_indices.has_index(i)) 01103 { 01104 partial2q_term[i] -= this->qoi[i]; 01105 partial2R_term[i] -= this->rhs->dot(this->get_adjoint_solution(i)); 01106 partial2q_term[i] /= (4. * delta_p * delta_p); 01107 partial2R_term[i] /= (4. * delta_p * delta_p); 01108 } 01109 01110 for (unsigned int i=0; i != Nq; ++i) 01111 if (qoi_indices.has_index(i)) 01112 { 01113 Number current_terms = partial2q_term[i] - partial2R_term[i]; 01114 sensitivities.second_derivative(i,k,l) += current_terms; 01115 if (k != l) 01116 sensitivities.second_derivative(i,l,k) += current_terms; 01117 } 01118 01119 // Don't leave the parameters perturbed 01120 *parameters[l] = old_parameterl; 01121 *parameters[k] = old_parameterk; 01122 } 01123 01124 // We get (partial q / partial u) and 01125 // (partial R / partial u) from the user, but centrally 01126 // difference to get q_uk and R_uk terms: 01127 // (partial^2 q / partial u partial k) 01128 // q_uk*u'_l = (q_u(p+dp*e_k)*u'_l - q_u(p-dp*e_k)*u'_l)/(2*dp) 01129 // R_uk*z*u'_l = (R_u(p+dp*e_k)*z*u'_l - R_u(p-dp*e_k)*z*u'_l)/(2*dp) 01130 // 01131 // To avoid creating Nq temporary vectors, we add these 01132 // subterms to the sensitivities output one by one. 01133 // 01134 // FIXME: this is probably a bad order of operations for 01135 // controlling floating point error. 01136 01137 *parameters[k] = old_parameterk + delta_p; 01138 this->assembly(false, true); 01139 this->assemble_qoi_derivative(qoi_indices); 01140 01141 for (unsigned int l=0; l != Np; ++l) 01142 { 01143 this->matrix->vector_mult(*tempvec, this->get_sensitivity_solution(l)); 01144 for (unsigned int i=0; i != Nq; ++i) 01145 if (qoi_indices.has_index(i)) 01146 { 01147 Number current_terms = 01148 (this->get_adjoint_rhs(i).dot(this->get_sensitivity_solution(l)) - 01149 tempvec->dot(this->get_adjoint_solution(i))) / (2.*delta_p); 01150 sensitivities.second_derivative(i,k,l) += current_terms; 01151 01152 // We use the _uk terms twice; symmetry lets us reuse 01153 // these calculations for the _ul terms. 01154 01155 sensitivities.second_derivative(i,l,k) += current_terms; 01156 } 01157 } 01158 01159 *parameters[k] = old_parameterk - delta_p; 01160 this->assembly(false, true); 01161 this->assemble_qoi_derivative(qoi_indices); 01162 01163 for (unsigned int l=0; l != Np; ++l) 01164 { 01165 this->matrix->vector_mult(*tempvec, this->get_sensitivity_solution(l)); 01166 for (unsigned int i=0; i != Nq; ++i) 01167 if (qoi_indices.has_index(i)) 01168 { 01169 Number current_terms = 01170 (-this->get_adjoint_rhs(i).dot(this->get_sensitivity_solution(l)) + 01171 tempvec->dot(this->get_adjoint_solution(i))) / (2.*delta_p); 01172 sensitivities.second_derivative(i,k,l) += current_terms; 01173 01174 // We use the _uk terms twice; symmetry lets us reuse 01175 // these calculations for the _ul terms. 01176 01177 sensitivities.second_derivative(i,l,k) += current_terms; 01178 } 01179 } 01180 01181 // Don't leave the parameter perturbed 01182 *parameters[k] = old_parameterk; 01183 01184 // Our last remaining terms are -R_uu(u,z)*u_k*u_l and 01185 // Q_uu(u)*u_k*u_l 01186 // 01187 // We take directional central finite differences of R_u and Q_u 01188 // to approximate these terms, e.g.: 01189 // 01190 // Q_uu(u)*u_k ~= (Q_u(u+dp*u_k) - Q_u(u-dp*u_k))/(2*dp) 01191 01192 *this->solution = this->get_sensitivity_solution(k); 01193 *this->solution *= delta_p; 01194 *this->solution += *oldsolution; 01195 this->assembly(false, true); 01196 this->assemble_qoi_derivative(qoi_indices); 01197 01198 // The Hessian is symmetric, so we just calculate the lower 01199 // triangle and the diagonal, and we get the upper triangle from 01200 // the transpose of the lower 01201 // 01202 // Note that, because we took the directional finite difference 01203 // with respect to k and not l, we've added an O(delta_p^2) 01204 // error to any permutational symmetry in the Hessian... 01205 for (unsigned int l=0; l != k+1; ++l) 01206 { 01207 this->matrix->vector_mult(*tempvec, this->get_sensitivity_solution(l)); 01208 for (unsigned int i=0; i != Nq; ++i) 01209 if (qoi_indices.has_index(i)) 01210 { 01211 Number current_terms = 01212 (this->get_adjoint_rhs(i).dot(this->get_sensitivity_solution(l)) - 01213 tempvec->dot(this->get_adjoint_solution(i))) / (2.*delta_p); 01214 sensitivities.second_derivative(i,k,l) += current_terms; 01215 if (k != l) 01216 sensitivities.second_derivative(i,l,k) += current_terms; 01217 } 01218 } 01219 01220 *this->solution = this->get_sensitivity_solution(k); 01221 *this->solution *= -delta_p; 01222 *this->solution += *oldsolution; 01223 this->assembly(false, true); 01224 this->assemble_qoi_derivative(qoi_indices); 01225 01226 for (unsigned int l=0; l != k+1; ++l) 01227 { 01228 this->matrix->vector_mult(*tempvec, this->get_sensitivity_solution(l)); 01229 for (unsigned int i=0; i != Nq; ++i) 01230 if (qoi_indices.has_index(i)) 01231 { 01232 Number current_terms = 01233 (-this->get_adjoint_rhs(i).dot(this->get_sensitivity_solution(l)) + 01234 tempvec->dot(this->get_adjoint_solution(i))) / (2.*delta_p); 01235 sensitivities.second_derivative(i,k,l) += current_terms; 01236 if (k != l) 01237 sensitivities.second_derivative(i,l,k) += current_terms; 01238 } 01239 } 01240 01241 // Don't leave the solution perturbed 01242 *this->solution = *oldsolution; 01243 } 01244 01245 // All parameters have been reset. 01246 // Don't leave the qoi or system changed - principle of least 01247 // surprise. 01248 this->assembly(true, true); 01249 this->assemble_qoi(qoi_indices); 01250 }
| void ImplicitSystem::qoi_parameter_hessian_vector_product | ( | const QoISet & | qoi_indices, | |
| const ParameterVector & | parameters, | |||
| const ParameterVector & | vector, | |||
| SensitivityData & | product | |||
| ) | [virtual, inherited] |
For each of the system's quantities of interest q in qoi[qoi_indices], and for a vector of parameters p, the parameter sensitivity Hessian H_ij is defined as H_ij = (d^2 q)/(d p_i d p_j) The Hessian-vector product, for a vector v_k in parameter space, is S_j = H_jk v_k This product is the output of this method, where for each q_i, S_j is stored in sensitivities[i][j].
Reimplemented from System.
Definition at line 825 of file implicit_system.C.
References SensitivityData::allocate_data(), ParameterVector::deep_copy(), QoISet::has_index(), ParameterVector::size(), and ParameterVector::value_copy().
00829 { 00830 // We currently get partial derivatives via finite differencing 00831 const Real delta_p = TOLERANCE; 00832 00833 // We'll use a single temporary vector for matrix-vector-vector products 00834 AutoPtr<NumericVector<Number> > tempvec = this->solution->zero_clone(); 00835 00836 const unsigned int Np = parameters.size(); 00837 const unsigned int Nq = qoi.size(); 00838 00839 // For each quantity of interest q, the parameter sensitivity 00840 // Hessian is defined as q''_{kl} = {d^2 q}/{d p_k d p_l}. 00841 // Given a vector of parameter perturbation weights w_l, this 00842 // function evaluates the hessian-vector product sum_l(q''_{kl}*w_l) 00843 // 00844 // We calculate it from values and partial derivatives of the 00845 // quantity of interest function Q, solution u, adjoint solution z, 00846 // parameter sensitivity adjoint solutions z^l, and residual R, as: 00847 // 00848 // sum_l(q''_{kl}*w_l) = 00849 // sum_l(w_l * Q''_{kl}) + Q''_{uk}(u)*(sum_l(w_l u'_l)) - 00850 // R'_k(u, sum_l(w_l*z^l)) - R'_{uk}(u,z)*(sum_l(w_l u'_l) - 00851 // sum_l(w_l*R''_{kl}(u,z)) 00852 // 00853 // See the adjoints model document for more details. 00854 00855 // We first do an adjoint solve to get z for each quantity of 00856 // interest 00857 00858 this->adjoint_solve(qoi_indices); 00859 00860 // Get ready to fill in senstivities: 00861 sensitivities.allocate_data(qoi_indices, *this, parameters); 00862 00863 // We can't solve for all the solution sensitivities u'_l or for all 00864 // of the parameter sensitivity adjoint solutions z^l without 00865 // requiring O(Nq*Np) linear solves. So we'll solve directly for their 00866 // weighted sum - this is just O(Nq) solves. 00867 00868 // First solve for sum_l(w_l u'_l). 00869 this->weighted_sensitivity_solve(parameters, vector); 00870 00871 // Then solve for sum_l(w_l z^l). 00872 this->weighted_sensitivity_adjoint_solve(parameters, vector, qoi_indices); 00873 00874 for (unsigned int k=0; k != Np; ++k) 00875 { 00876 // We approximate sum_l(w_l * Q''_{kl}) with a central 00877 // differencing pertubation: 00878 // sum_l(w_l * Q''_{kl}) ~= 00879 // (Q(p + dp*w_l*e_l + dp*e_k) - Q(p - dp*w_l*e_l + dp*e_k) - 00880 // Q(p + dp*w_l*e_l - dp*e_k) + Q(p - dp*w_l*e_l - dp*e_k))/(4*dp^2) 00881 00882 // The sum(w_l*R''_kl) term requires the same sort of pertubation, 00883 // and so we subtract it in at the same time: 00884 // sum_l(w_l * R''_{kl}) ~= 00885 // (R(p + dp*w_l*e_l + dp*e_k) - R(p - dp*w_l*e_l + dp*e_k) - 00886 // R(p + dp*w_l*e_l - dp*e_k) + R(p - dp*w_l*e_l - dp*e_k))/(4*dp^2) 00887 00888 ParameterVector oldparameters, parameterperturbation; 00889 parameters.deep_copy(oldparameters); 00890 vector.deep_copy(parameterperturbation); 00891 parameterperturbation *= delta_p; 00892 parameters += parameterperturbation; 00893 00894 Number old_parameter = *parameters[k]; 00895 00896 *parameters[k] = old_parameter + delta_p; 00897 this->assemble_qoi(qoi_indices); 00898 this->assembly(true, false); 00899 std::vector<Number> partial2q_term = this->qoi; 00900 std::vector<Number> partial2R_term(this->qoi.size()); 00901 for (unsigned int i=0; i != Nq; ++i) 00902 if (qoi_indices.has_index(i)) 00903 partial2R_term[i] = this->rhs->dot(this->get_adjoint_solution(i)); 00904 00905 *parameters[k] = old_parameter - delta_p; 00906 this->assemble_qoi(qoi_indices); 00907 this->assembly(true, false); 00908 for (unsigned int i=0; i != Nq; ++i) 00909 if (qoi_indices.has_index(i)) 00910 { 00911 partial2q_term[i] += this->qoi[i]; 00912 partial2R_term[i] += this->rhs->dot(this->get_adjoint_solution(i)); 00913 } 00914 00915 oldparameters.value_copy(parameters); 00916 parameterperturbation *= -1.0; 00917 parameters += parameterperturbation; 00918 00919 // Re-center old_parameter, which may be affected by vector 00920 old_parameter = *parameters[k]; 00921 00922 *parameters[k] = old_parameter + delta_p; 00923 this->assemble_qoi(qoi_indices); 00924 this->assembly(true, false); 00925 for (unsigned int i=0; i != Nq; ++i) 00926 if (qoi_indices.has_index(i)) 00927 { 00928 partial2q_term[i] += this->qoi[i]; 00929 partial2R_term[i] += this->rhs->dot(this->get_adjoint_solution(i)); 00930 } 00931 00932 *parameters[k] = old_parameter - delta_p; 00933 this->assemble_qoi(qoi_indices); 00934 this->assembly(true, false); 00935 for (unsigned int i=0; i != Nq; ++i) 00936 if (qoi_indices.has_index(i)) 00937 { 00938 partial2q_term[i] += this->qoi[i]; 00939 partial2R_term[i] += this->rhs->dot(this->get_adjoint_solution(i)); 00940 } 00941 00942 for (unsigned int i=0; i != Nq; ++i) 00943 if (qoi_indices.has_index(i)) 00944 { 00945 partial2q_term[i] /= (4. * delta_p * delta_p); 00946 partial2R_term[i] /= (4. * delta_p * delta_p); 00947 } 00948 00949 for (unsigned int i=0; i != Nq; ++i) 00950 if (qoi_indices.has_index(i)) 00951 sensitivities[i][k] = partial2q_term[i] - partial2R_term[i]; 00952 00953 // We get (partial q / partial u), R, and 00954 // (partial R / partial u) from the user, but centrally 00955 // difference to get q_uk, R_k, and R_uk terms: 00956 // (partial R / partial k) 00957 // R_k*sum(w_l*z^l) = (R(p+dp*e_k)*sum(w_l*z^l) - R(p-dp*e_k)*sum(w_l*z^l))/(2*dp) 00958 // (partial^2 q / partial u partial k) 00959 // q_uk = (q_u(p+dp*e_k) - q_u(p-dp*e_k))/(2*dp) 00960 // (partial^2 R / partial u partial k) 00961 // R_uk*z*sum(w_l*u'_l) = (R_u(p+dp*e_k)*z*sum(w_l*u'_l) - R_u(p-dp*e_k)*z*sum(w_l*u'_l))/(2*dp) 00962 00963 // To avoid creating Nq temporary vectors for q_uk or R_uk, we add 00964 // subterms to the sensitivities output one by one. 00965 // 00966 // FIXME: this is probably a bad order of operations for 00967 // controlling floating point error. 00968 00969 *parameters[k] = old_parameter + delta_p; 00970 this->assembly(true, true); 00971 this->assemble_qoi_derivative(qoi_indices); 00972 00973 this->matrix->vector_mult(*tempvec, this->get_weighted_sensitivity_solution()); 00974 00975 for (unsigned int i=0; i != Nq; ++i) 00976 if (qoi_indices.has_index(i)) 00977 sensitivities[i][k] += (this->get_adjoint_rhs(i).dot(this->get_weighted_sensitivity_solution()) - 00978 this->rhs->dot(this->get_weighted_sensitivity_adjoint_solution(i)) - 00979 this->get_adjoint_solution(i).dot(*tempvec)) / (2.*delta_p); 00980 00981 *parameters[k] = old_parameter - delta_p; 00982 this->assembly(true, true); 00983 this->assemble_qoi_derivative(qoi_indices); 00984 00985 this->matrix->vector_mult(*tempvec, this->get_weighted_sensitivity_solution()); 00986 00987 for (unsigned int i=0; i != Nq; ++i) 00988 if (qoi_indices.has_index(i)) 00989 sensitivities[i][k] += (-this->get_adjoint_rhs(i).dot(this->get_weighted_sensitivity_solution()) + 00990 this->rhs->dot(this->get_weighted_sensitivity_adjoint_solution(i)) + 00991 this->get_adjoint_solution(i).dot(*tempvec)) / (2.*delta_p); 00992 } 00993 00994 // All parameters have been reset. 00995 // Don't leave the qoi or system changed - principle of least 00996 // surprise. 00997 this->assembly(true, true); 00998 this->assemble_qoi(qoi_indices); 00999 }
| void System::qoi_parameter_sensitivity | ( | const QoISet & | qoi_indices, | |
| const ParameterVector & | parameters, | |||
| SensitivityData & | sensitivities | |||
| ) | [virtual, inherited] |
Solves for the derivative of each of the system's quantities of interest q in qoi[qoi_indices] with respect to each parameter in parameters, placing the result for qoi i and parameter j into sensitivities[i][j].
Note that parameters is a const vector, not a vector-of-const; parameter values in this vector need to be mutable for finite differencing to work.
Automatically chooses the forward method for problems with more quantities of interest than parameters, or the adjoint method otherwise.
This method is only usable in derived classes which overload an implementation.
Definition at line 383 of file system.C.
References ParameterVector::size(), and QoISet::size().
00386 { 00387 // Forward sensitivities are more efficient for Nq > Np 00388 if (qoi_indices.size(*this) > parameters.size()) 00389 forward_qoi_parameter_sensitivity(qoi_indices, parameters, sensitivities); 00390 // Adjoint sensitivities are more efficient for Np > Nq, 00391 // and an adjoint may be more reusable than a forward 00392 // solution sensitivity in the Np == Nq case. 00393 else 00394 adjoint_qoi_parameter_sensitivity(qoi_indices, parameters, sensitivities); 00395 }
| void System::re_update | ( | ) | [virtual, inherited] |
Re-update the local values when the mesh has changed. This method takes the data updated by update() and makes it up-to-date on the current mesh.
Definition at line 314 of file system.C.
References System::current_local_solution, Utility::iota(), System::n_vars(), and System::solution.
00315 { 00316 //const std::vector<unsigned int>& send_list = _dof_map->get_send_list (); 00317 00318 // If this system is empty... don't do anything! 00319 if(!this->n_vars()) 00320 return; 00321 00322 // Explicitly build a send_list 00323 std::vector<unsigned int> send_list(solution->size()); 00324 Utility::iota (send_list.begin(), send_list.end(), 0); 00325 00326 // Check sizes 00327 libmesh_assert (current_local_solution->size() == solution->size()); 00328 // Not true with ghosted vectors 00329 // libmesh_assert (current_local_solution->local_size() == solution->size()); 00330 libmesh_assert (!send_list.empty()); 00331 libmesh_assert (send_list.size() <= solution->size()); 00332 00333 // Create current_local_solution from solution. This will 00334 // put a local copy of solution into current_local_solution. 00335 solution->localize (*current_local_solution, send_list); 00336 }
| void System::read_header | ( | Xdr & | io, | |
| const std::string & | version, | |||
| const bool | read_header = true, |
|||
| const bool | read_additional_data = true, |
|||
| const bool | read_legacy_format = false | |||
| ) | [inherited] |
Reads the basic data header for this System.
Definition at line 78 of file system_io.C.
References System::_additional_data_written, System::_can_add_vectors, System::add_variable(), System::add_vector(), System::clear(), Xdr::data(), FEType::family, System::get_mesh(), FEType::inf_map, MeshBase::mesh_dimension(), libMeshEnums::MONOMIAL, System::n_vars(), System::n_vectors(), libMesh::on_command_line(), FEType::order, libMesh::processor_id(), FEType::radial_family, FEType::radial_order, Xdr::reading(), type, and libMeshEnums::XYZ.
Referenced by EquationSystems::_read_impl().
00083 { 00084 // This method implements the input of a 00085 // System object, embedded in the output of 00086 // an EquationSystems<T_sys>. This warrants some 00087 // documentation. The output file essentially 00088 // consists of 5 sections: 00089 // 00090 // for this system 00091 // 00092 // 5.) The number of variables in the system (unsigned int) 00093 // 00094 // for each variable in the system 00095 // 00096 // 6.) The name of the variable (string) 00097 // 00098 // 7.) Combined in an FEType: 00099 // - The approximation order(s) of the variable 00100 // (Order Enum, cast to int/s) 00101 // - The finite element family/ies of the variable 00102 // (FEFamily Enum, cast to int/s) 00103 // 00104 // end variable loop 00105 // 00106 // 8.) The number of additional vectors (unsigned int), 00107 // 00108 // for each additional vector in the system object 00109 // 00110 // 9.) the name of the additional vector (string) 00111 // 00112 // end system 00113 libmesh_assert (io.reading()); 00114 00115 // Possibly clear data structures and start from scratch. 00116 if (read_header) 00117 this->clear (); 00118 00119 // Figure out if we need to read infinite element information. 00120 // This will be true if the version string contains " with infinite elements" 00121 const bool read_ifem_info = 00122 (version.rfind(" with infinite elements") < version.size()) || 00123 libMesh::on_command_line ("--read_ifem_systems"); 00124 00125 00126 { 00127 // 5.) 00128 // Read the number of variables in the system 00129 unsigned int n_vars=0; 00130 if (libMesh::processor_id() == 0) io.data (n_vars); 00131 Parallel::broadcast(n_vars); 00132 00133 for (unsigned int var=0; var<n_vars; var++) 00134 { 00135 // 6.) 00136 // Read the name of the var-th variable 00137 std::string var_name; 00138 if (libMesh::processor_id() == 0) io.data (var_name); 00139 Parallel::broadcast(var_name); 00140 00141 // 7.) 00142 // Read the approximation order(s) of the var-th variable 00143 int order=0; 00144 if (libMesh::processor_id() == 0) io.data (order); 00145 Parallel::broadcast(order); 00146 00147 00148 // do the same for infinite element radial_order 00149 int rad_order=0; 00150 if (read_ifem_info) 00151 { 00152 if (libMesh::processor_id() == 0) io.data(rad_order); 00153 Parallel::broadcast(rad_order); 00154 } 00155 00156 00157 // Read the finite element type of the var-th variable 00158 int fam=0; 00159 if (libMesh::processor_id() == 0) io.data (fam); 00160 Parallel::broadcast(fam); 00161 FEType type; 00162 type.order = static_cast<Order>(order); 00163 type.family = static_cast<FEFamily>(fam); 00164 00165 // Check for incompatibilities. The shape function indexing was 00166 // changed for the monomial and xyz finite element families to 00167 // simplify extension to arbitrary p. The consequence is that 00168 // old restart files will not be read correctly. This is expected 00169 // to be an unlikely occurance, but catch it anyway. 00170 if (read_legacy_format) 00171 if ((type.family == MONOMIAL || type.family == XYZ) && 00172 ((type.order > 2 && this->get_mesh().mesh_dimension() == 2) || 00173 (type.order > 1 && this->get_mesh().mesh_dimension() == 3))) 00174 { 00175 libmesh_here(); 00176 std::cout << "*****************************************************************\n" 00177 << "* WARNING: reading a potentially incompatible restart file!!! *\n" 00178 << "* contact libmesh-users@lists.sourceforge.net for more details *\n" 00179 << "*****************************************************************" 00180 << std::endl; 00181 } 00182 00183 // Read additional information for infinite elements 00184 int radial_fam=0; 00185 int i_map=0; 00186 if (read_ifem_info) 00187 { 00188 if (libMesh::processor_id() == 0) io.data (radial_fam); 00189 Parallel::broadcast(radial_fam); 00190 if (libMesh::processor_id() == 0) io.data (i_map); 00191 Parallel::broadcast(i_map); 00192 } 00193 00194 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00195 00196 type.radial_order = static_cast<Order>(rad_order); 00197 type.radial_family = static_cast<FEFamily>(radial_fam); 00198 type.inf_map = static_cast<InfMapType>(i_map); 00199 00200 #endif 00201 00202 if (read_header) 00203 this->add_variable (var_name, type); 00204 } 00205 } 00206 00207 // 8.) 00208 // Read the number of additional vectors. 00209 unsigned int n_vectors=0; 00210 if (libMesh::processor_id() == 0) io.data (n_vectors); 00211 Parallel::broadcast(n_vectors); 00212 00213 // If n_vectors > 0, this means that write_additional_data 00214 // was true when this file was written. We will need to 00215 // make use of this fact later. 00216 if (n_vectors > 0) 00217 this->_additional_data_written = true; 00218 00219 for (unsigned int vec=0; vec<n_vectors; vec++) 00220 { 00221 // 9.) 00222 // Read the name of the vec-th additional vector 00223 std::string vec_name; 00224 if (libMesh::processor_id() == 0) io.data (vec_name); 00225 Parallel::broadcast(vec_name); 00226 00227 if (read_additional_data) 00228 { 00229 // sanity checks 00230 libmesh_assert(this->_can_add_vectors); 00231 // Some systems may have added their own vectors already 00232 // libmesh_assert(this->_vectors.count(vec_name) == 0); 00233 00234 this->add_vector(vec_name); 00235 } 00236 } 00237 }
| void System::read_legacy_data | ( | Xdr & | io, | |
| const bool | read_additional_data = true | |||
| ) | [inherited] |
Reads additional data, namely vectors, for this System.
Definition at line 241 of file system_io.C.
References System::_additional_data_written, System::_vectors, MeshBase::active_elements_begin(), MeshBase::active_elements_end(), Xdr::data(), System::get_mesh(), DofObject::invalid_id, System::n_dofs(), System::n_vars(), MeshBase::nodes_begin(), MeshBase::nodes_end(), System::number(), libMesh::processor_id(), Xdr::reading(), System::solution, and libMesh::zero.
00243 { 00244 libmesh_deprecated(); 00245 00246 // This method implements the output of the vectors 00247 // contained in this System object, embedded in the 00248 // output of an EquationSystems<T_sys>. 00249 // 00250 // 10.) The global solution vector, re-ordered to be node-major 00251 // (More on this later.) 00252 // 00253 // for each additional vector in the object 00254 // 00255 // 11.) The global additional vector, re-ordered to be 00256 // node-major (More on this later.) 00257 libmesh_assert (io.reading()); 00258 00259 // read and reordering buffers 00260 std::vector<Number> global_vector; 00261 std::vector<Number> reordered_vector; 00262 00263 // 10.) 00264 // Read and set the solution vector 00265 { 00266 if (libMesh::processor_id() == 0) io.data (global_vector); 00267 Parallel::broadcast(global_vector); 00268 00269 // Remember that the stored vector is node-major. 00270 // We need to put it into whatever application-specific 00271 // ordering we may have using the dof_map. 00272 reordered_vector.resize(global_vector.size()); 00273 00274 //std::cout << "global_vector.size()=" << global_vector.size() << std::endl; 00275 //std::cout << "this->n_dofs()=" << this->n_dofs() << std::endl; 00276 00277 libmesh_assert (global_vector.size() == this->n_dofs()); 00278 00279 unsigned int cnt=0; 00280 00281 const unsigned int sys = this->number(); 00282 const unsigned int n_vars = this->n_vars(); 00283 00284 for (unsigned int var=0; var<n_vars; var++) 00285 { 00286 // First reorder the nodal DOF values 00287 { 00288 MeshBase::node_iterator 00289 it = this->get_mesh().nodes_begin(), 00290 end = this->get_mesh().nodes_end(); 00291 00292 for (; it != end; ++it) 00293 for (unsigned int index=0; index<(*it)->n_comp(sys,var); index++) 00294 { 00295 libmesh_assert ((*it)->dof_number(sys, var, index) != 00296 DofObject::invalid_id); 00297 00298 libmesh_assert (cnt < global_vector.size()); 00299 00300 reordered_vector[(*it)->dof_number(sys, var, index)] = 00301 global_vector[cnt++]; 00302 } 00303 } 00304 00305 // Then reorder the element DOF values 00306 { 00307 MeshBase::element_iterator 00308 it = this->get_mesh().active_elements_begin(), 00309 end = this->get_mesh().active_elements_end(); 00310 00311 for (; it != end; ++it) 00312 for (unsigned int index=0; index<(*it)->n_comp(sys,var); index++) 00313 { 00314 libmesh_assert ((*it)->dof_number(sys, var, index) != 00315 DofObject::invalid_id); 00316 00317 libmesh_assert (cnt < global_vector.size()); 00318 00319 reordered_vector[(*it)->dof_number(sys, var, index)] = 00320 global_vector[cnt++]; 00321 } 00322 } 00323 } 00324 00325 *(this->solution) = reordered_vector; 00326 } 00327 00328 // For each additional vector, simply go through the list. 00329 // ONLY attempt to do this IF additional data was actually 00330 // written to the file for this system (controlled by the 00331 // _additional_data_written flag). 00332 if (this->_additional_data_written) 00333 { 00334 std::map<std::string, NumericVector<Number>* >::iterator 00335 pos = this->_vectors.begin(); 00336 00337 for (; pos != this->_vectors.end(); ++pos) 00338 { 00339 // 11.) 00340 // Read the values of the vec-th additional vector. 00341 // Prior do _not_ clear, but fill with zero, since the 00342 // additional vectors _have_ to have the same size 00343 // as the solution vector 00344 std::fill (global_vector.begin(), global_vector.end(), libMesh::zero); 00345 00346 if (libMesh::processor_id() == 0) io.data (global_vector); 00347 Parallel::broadcast(global_vector); 00348 00349 // If read_additional_data==true, then we will keep this vector, otherwise 00350 // we are going to throw it away. 00351 if (read_additional_data) 00352 { 00353 // Remember that the stored vector is node-major. 00354 // We need to put it into whatever application-specific 00355 // ordering we may have using the dof_map. 00356 std::fill (reordered_vector.begin(), 00357 reordered_vector.end(), 00358 libMesh::zero); 00359 00360 reordered_vector.resize(global_vector.size()); 00361 00362 libmesh_assert (global_vector.size() == this->n_dofs()); 00363 00364 unsigned int cnt=0; 00365 00366 const unsigned int sys = this->number(); 00367 const unsigned int n_vars = this->n_vars(); 00368 00369 for (unsigned int var=0; var<n_vars; var++) 00370 { 00371 // First reorder the nodal DOF values 00372 { 00373 MeshBase::node_iterator 00374 it = this->get_mesh().nodes_begin(), 00375 end = this->get_mesh().nodes_end(); 00376 00377 for (; it!=end; ++it) 00378 for (unsigned int index=0; index<(*it)->n_comp(sys,var); index++) 00379 { 00380 libmesh_assert ((*it)->dof_number(sys, var, index) != 00381 DofObject::invalid_id); 00382 00383 libmesh_assert (cnt < global_vector.size()); 00384 00385 reordered_vector[(*it)->dof_number(sys, var, index)] = 00386 global_vector[cnt++]; 00387 } 00388 } 00389 00390 // Then reorder the element DOF values 00391 { 00392 MeshBase::element_iterator 00393 it = this->get_mesh().active_elements_begin(), 00394 end = this->get_mesh().active_elements_end(); 00395 00396 for (; it!=end; ++it) 00397 for (unsigned int index=0; index<(*it)->n_comp(sys,var); index++) 00398 { 00399 libmesh_assert ((*it)->dof_number(sys, var, index) != 00400 DofObject::invalid_id); 00401 00402 libmesh_assert (cnt < global_vector.size()); 00403 00404 reordered_vector[(*it)->dof_number(sys, var, index)] = 00405 global_vector[cnt++]; 00406 } 00407 } 00408 } 00409 00410 // use the overloaded operator=(std::vector) to assign the values 00411 *(pos->second) = reordered_vector; 00412 } 00413 } 00414 } // end if (_additional_data_written) 00415 }
| void System::read_parallel_data | ( | Xdr & | io, | |
| const bool | read_additional_data | |||
| ) | [inherited] |
Reads additional data, namely vectors, for this System. This method may safely be called on a distributed-memory mesh. This method will read an individual file for each processor in the simulation where the local solution components for that processor are stored.
This method implements the output of the vectors contained in this System object, embedded in the output of an EquationSystems<T_sys>.
9.) The global solution vector, re-ordered to be node-major (More on this later.)
for each additional vector in the object
10.) The global additional vector, re-ordered to be node-major (More on this later.)
Note that the actual IO is handled through the Xdr class (to be renamed later?) which provides a uniform interface to both the XDR (eXternal Data Representation) interface and standard ASCII output. Thus this one section of code will read XDR or ASCII files with no changes.
Definition at line 419 of file system_io.C.
References System::_vectors, Xdr::data(), System::get_mesh(), DofObject::invalid_id, Xdr::is_open(), System::n_vars(), System::number(), Xdr::reading(), and System::solution.
00421 { 00441 libmesh_assert (io.reading()); 00442 libmesh_assert (io.is_open()); 00443 00444 // build the ordered nodes and element maps. 00445 // when writing/reading parallel files we need to iterate 00446 // over our nodes/elements in order of increasing global id(). 00447 // however, this is not guaranteed to be ordering we obtain 00448 // by using the node_iterators/element_iterators directly. 00449 // so build a set, sorted by id(), that provides the ordering. 00450 // further, for memory economy build the set but then transfer 00451 // its contents to vectors, which will be sorted. 00452 std::vector<const DofObject*> ordered_nodes, ordered_elements; 00453 { 00454 std::set<const DofObject*, CompareDofObjectsByID> 00455 ordered_nodes_set (this->get_mesh().local_nodes_begin(), 00456 this->get_mesh().local_nodes_end()); 00457 00458 ordered_nodes.insert(ordered_nodes.end(), 00459 ordered_nodes_set.begin(), 00460 ordered_nodes_set.end()); 00461 } 00462 { 00463 std::set<const DofObject*, CompareDofObjectsByID> 00464 ordered_elements_set (this->get_mesh().local_elements_begin(), 00465 this->get_mesh().local_elements_end()); 00466 00467 ordered_elements.insert(ordered_elements.end(), 00468 ordered_elements_set.begin(), 00469 ordered_elements_set.end()); 00470 } 00471 00472 std::vector<Number> io_buffer; 00473 00474 // 9.) 00475 // 00476 // Actually read the solution components 00477 // for the ith system to disk 00478 io.data(io_buffer); 00479 00480 const unsigned int sys_num = this->number(); 00481 const unsigned int n_vars = this->n_vars(); 00482 00483 unsigned int cnt=0; 00484 00485 // Loop over each variable and each node, and read out the value. 00486 for (unsigned int var=0; var<n_vars; var++) 00487 { 00488 // First read the node DOF values 00489 for (std::vector<const DofObject*>::const_iterator 00490 it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) 00491 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 00492 { 00493 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 00494 DofObject::invalid_id); 00495 libmesh_assert (cnt < io_buffer.size()); 00496 this->solution->set((*it)->dof_number(sys_num, var, comp), io_buffer[cnt++]); 00497 } 00498 00499 // Then read the element DOF values 00500 for (std::vector<const DofObject*>::const_iterator 00501 it = ordered_elements.begin(); it != ordered_elements.end(); ++it) 00502 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 00503 { 00504 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 00505 DofObject::invalid_id); 00506 libmesh_assert (cnt < io_buffer.size()); 00507 this->solution->set((*it)->dof_number(sys_num, var, comp), io_buffer[cnt++]); 00508 } 00509 } 00510 00511 // Only read additional vectors if wanted 00512 if (read_additional_data) 00513 { 00514 std::map<std::string, NumericVector<Number>* >::const_iterator 00515 pos = _vectors.begin(); 00516 00517 for(; pos != this->_vectors.end(); ++pos) 00518 { 00519 cnt=0; 00520 io_buffer.clear(); 00521 00522 // 10.) 00523 // 00524 // Actually read the additional vector components 00525 // for the ith system to disk 00526 io.data(io_buffer); 00527 00528 // Loop over each variable and each node, and read out the value. 00529 for (unsigned int var=0; var<n_vars; var++) 00530 { 00531 // First read the node DOF values 00532 for (std::vector<const DofObject*>::const_iterator 00533 it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) 00534 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 00535 { 00536 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 00537 DofObject::invalid_id); 00538 libmesh_assert (cnt < io_buffer.size()); 00539 this->solution->set((*it)->dof_number(sys_num, var, comp), io_buffer[cnt++]); 00540 } 00541 00542 // Then read the element DOF values 00543 for (std::vector<const DofObject*>::const_iterator 00544 it = ordered_elements.begin(); it != ordered_elements.end(); ++it) 00545 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 00546 { 00547 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 00548 DofObject::invalid_id); 00549 libmesh_assert (cnt < io_buffer.size()); 00550 this->solution->set((*it)->dof_number(sys_num, var, comp), io_buffer[cnt++]); 00551 } 00552 } 00553 } 00554 } 00555 }
| void System::read_serialized_data | ( | Xdr & | io, | |
| const bool | read_additional_data = true | |||
| ) | [inherited] |
Reads additional data, namely vectors, for this System. This method may safely be called on a distributed-memory mesh.
Definition at line 559 of file system_io.C.
References System::_vectors, Xdr::comment(), libMesh::processor_id(), System::read_serialized_vector(), and System::solution.
00561 { 00562 // This method implements the input of the vectors 00563 // contained in this System object, embedded in the 00564 // output of an EquationSystems<T_sys>. 00565 // 00566 // 10.) The global solution vector, re-ordered to be node-major 00567 // (More on this later.) 00568 // 00569 // for each additional vector in the object 00570 // 00571 // 11.) The global additional vector, re-ordered to be 00572 // node-major (More on this later.) 00573 parallel_only(); 00574 std::string comment; 00575 00576 // 10.) 00577 // Read the global solution vector 00578 { 00579 this->read_serialized_vector(io, *this->solution); 00580 00581 // get the comment 00582 if (libMesh::processor_id() == 0) 00583 io.comment (comment); 00584 } 00585 00586 // 11.) 00587 // Only read additional vectors if wanted 00588 if (read_additional_data) 00589 { 00590 std::map<std::string, NumericVector<Number>* >::const_iterator 00591 pos = _vectors.begin(); 00592 00593 for(; pos != this->_vectors.end(); ++pos) 00594 { 00595 this->read_serialized_vector(io, *pos->second); 00596 00597 // get the comment 00598 if (libMesh::processor_id() == 0) 00599 io.comment (comment); 00600 00601 } 00602 } 00603 }
| void DifferentiableSystem::reinit | ( | ) | [virtual, inherited] |
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be used.
Reimplemented from ImplicitSystem.
Definition at line 71 of file diff_system.C.
References ImplicitSystem::reinit(), and DifferentiableSystem::time_solver.
00072 { 00073 Parent::reinit(); 00074 00075 time_solver->reinit(); 00076 }
| void DifferentiableSystem::release_linear_solver | ( | LinearSolver< Number > * | s | ) | const [virtual, inherited] |
Releases a pointer to a linear solver acquired by this->get_linear_solver()
Reimplemented from ImplicitSystem.
Definition at line 131 of file diff_system.C.
| SparseMatrix< Number > * ImplicitSystem::request_matrix | ( | const std::string & | mat_name | ) | [inherited] |
- Returns:
- a writable pointer to this system's additional matrix named
mat_name, or returnsNULLif no matrix by that name exists.
Definition at line 213 of file implicit_system.C.
References ImplicitSystem::_matrices.
00214 { 00215 // Make sure the matrix exists 00216 matrices_iterator pos = _matrices.find (mat_name); 00217 00218 if (pos == _matrices.end()) 00219 return NULL; 00220 00221 return pos->second; 00222 }
| const SparseMatrix< Number > * ImplicitSystem::request_matrix | ( | const std::string & | mat_name | ) | const [inherited] |
- Returns:
- a const pointer to this system's additional matrix named
mat_name, or returnsNULLif no matrix by that name exists.
Definition at line 200 of file implicit_system.C.
References ImplicitSystem::_matrices.
Referenced by ImplicitSystem::sensitivity_solve(), NewtonSolver::solve(), and LinearImplicitSystem::solve().
00201 { 00202 // Make sure the matrix exists 00203 const_matrices_iterator pos = _matrices.find (mat_name); 00204 00205 if (pos == _matrices.end()) 00206 return NULL; 00207 00208 return pos->second; 00209 }
| NumericVector< Number > * System::request_vector | ( | const unsigned int | vec_num | ) | [inherited] |
- Returns:
- a writeable pointer to this system's additional vector number
vec_num(where the vectors are counted starting with 0), or returnsNULLif the system has no such vector.
Definition at line 611 of file system.C.
References System::vectors_begin(), and System::vectors_end().
00612 { 00613 vectors_iterator v = vectors_begin(); 00614 vectors_iterator v_end = vectors_end(); 00615 unsigned int num = 0; 00616 while((num<vec_num) && (v!=v_end)) 00617 { 00618 num++; 00619 ++v; 00620 } 00621 if (v==v_end) 00622 return NULL; 00623 return v->second; 00624 }
| const NumericVector< Number > * System::request_vector | ( | const unsigned int | vec_num | ) | const [inherited] |
- Returns:
- a const pointer to this system's additional vector number
vec_num(where the vectors are counted starting with 0), or returnsNULLif the system has no such vector.
Definition at line 594 of file system.C.
References System::vectors_begin(), and System::vectors_end().
00595 { 00596 const_vectors_iterator v = vectors_begin(); 00597 const_vectors_iterator v_end = vectors_end(); 00598 unsigned int num = 0; 00599 while((num<vec_num) && (v!=v_end)) 00600 { 00601 num++; 00602 ++v; 00603 } 00604 if (v==v_end) 00605 return NULL; 00606 return v->second; 00607 }
| NumericVector< Number > * System::request_vector | ( | const std::string & | vec_name | ) | [inherited] |
- Returns:
- a pointer to the vector if this
Systemhas a vector associated with the given name,NULLotherwise.
Definition at line 582 of file system.C.
References System::_vectors.
00583 { 00584 vectors_iterator pos = _vectors.find(vec_name); 00585 00586 if (pos == _vectors.end()) 00587 return NULL; 00588 00589 return pos->second; 00590 }
| const NumericVector< Number > * System::request_vector | ( | const std::string & | vec_name | ) | const [inherited] |
- Returns:
- a const pointer to the vector if this
Systemhas a vector associated with the given name,NULLotherwise.
Definition at line 570 of file system.C.
References System::_vectors.
00571 { 00572 const_vectors_iterator pos = _vectors.find(vec_name); 00573 00574 if (pos == _vectors.end()) 00575 return NULL; 00576 00577 return pos->second; 00578 }
| void System::restrict_vectors | ( | ) | [virtual, inherited] |
Restrict vectors after the mesh has coarsened
Definition at line 219 of file system.C.
References System::_dof_map, System::_solution_projection, System::_vector_projections, System::_vectors, System::current_local_solution, libMeshEnums::GHOSTED, NumericVector< T >::init(), System::n_dofs(), System::n_local_dofs(), libMeshEnums::PARALLEL, System::project_vector(), and System::solution.
Referenced by System::prolong_vectors(), and EquationSystems::reinit().
00220 { 00221 #ifdef LIBMESH_ENABLE_AMR 00222 // Restrict the _vectors on the coarsened cells 00223 for (vectors_iterator pos = _vectors.begin(); pos != _vectors.end(); ++pos) 00224 { 00225 NumericVector<Number>* v = pos->second; 00226 00227 if (_vector_projections[pos->first]) 00228 this->project_vector (*v); 00229 else 00230 v->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL); 00231 } 00232 00233 const std::vector<unsigned int>& send_list = _dof_map->get_send_list (); 00234 00235 // Restrict the solution on the coarsened cells 00236 if (_solution_projection) 00237 this->project_vector (*solution); 00238 00239 #ifdef LIBMESH_ENABLE_GHOSTED 00240 current_local_solution->init(this->n_dofs(), 00241 this->n_local_dofs(), send_list, 00242 false, GHOSTED); 00243 #else 00244 current_local_solution->init(this->n_dofs()); 00245 #endif 00246 00247 if (_solution_projection) 00248 solution->localize (*current_local_solution, send_list); 00249 00250 #endif // LIBMESH_ENABLE_AMR 00251 }
| void ContinuationSystem::save_current_solution | ( | ) |
Stores the current solution and continuation parameter (as "previous_u" and "old_continuation_paramter") for later referral. You may need to call this e.g. after the first regular solve, in order to store the first solution, before computing a second solution and beginning arclength continuation.
Definition at line 1373 of file continuation_system.C.
References continuation_parameter, old_continuation_parameter, previous_u, and System::solution.
Referenced by update_solution().
01374 { 01375 // Save the old solution vector 01376 *previous_u = *solution; 01377 01378 // Save the old value of lambda 01379 old_continuation_parameter = *continuation_parameter; 01380 }
| std::pair< unsigned int, Real > ImplicitSystem::sensitivity_solve | ( | const ParameterVector & | parameters | ) | [virtual, inherited] |
Assembles & solves the linear system(s) (dR/du)*u_p = -dR/dp, for those parameters contained within parameters.
Returns a pair with the total number of linear iterations performed and the (sum of the) final residual norms
Reimplemented from System.
Definition at line 282 of file implicit_system.C.
References System::assemble_before_solve, ImplicitSystem::assemble_residual_derivatives(), ImplicitSystem::assembly(), DofMap::enforce_constraints_exactly(), System::get_dof_map(), ImplicitSystem::get_linear_solve_parameters(), ImplicitSystem::get_linear_solver(), System::get_sensitivity_rhs(), System::get_sensitivity_solution(), ImplicitSystem::matrix, ImplicitSystem::release_linear_solver(), ImplicitSystem::request_matrix(), ParameterVector::size(), and LinearSolver< T >::solve().
00283 { 00284 // Log how long the linear solve takes. 00285 START_LOG("sensitivity_solve()", "ImplicitSystem"); 00286 00287 // The forward system should now already be solved. 00288 // Now assemble the corresponding sensitivity system. 00289 00290 if (this->assemble_before_solve) 00291 { 00292 // Build the Jacobian 00293 this->assembly(false, true); 00294 this->matrix->close(); 00295 00296 // Reset and build the RHS from the residual derivatives 00297 this->assemble_residual_derivatives(parameters); 00298 } 00299 00300 // The sensitivity problem is linear 00301 LinearSolver<Number> *linear_solver = this->get_linear_solver(); 00302 00303 // Our iteration counts and residuals will be sums of the individual 00304 // results 00305 std::pair<unsigned int, Real> solver_params = 00306 this->get_linear_solve_parameters(); 00307 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0); 00308 00309 // Solve the linear system. 00310 SparseMatrix<Number> *pc = this->request_matrix("Preconditioner"); 00311 for (unsigned int p=0; p != parameters.size(); ++p) 00312 { 00313 std::pair<unsigned int, Real> rval = 00314 linear_solver->solve (*matrix, pc, 00315 this->get_sensitivity_solution(p), 00316 this->get_sensitivity_rhs(p), 00317 solver_params.second, 00318 solver_params.first); 00319 00320 totalrval.first += rval.first; 00321 totalrval.second += rval.second; 00322 } 00323 00324 // The linear solver may not have fit our constraints exactly 00325 #ifdef LIBMESH_ENABLE_AMR 00326 for (unsigned int p=0; p != parameters.size(); ++p) 00327 this->get_dof_map().enforce_constraints_exactly 00328 (*this, &this->get_sensitivity_solution(p)); 00329 #endif 00330 00331 this->release_linear_solver(linear_solver); 00332 00333 // Stop logging the nonlinear solve 00334 STOP_LOG("sensitivity_solve()", "ImplicitSystem"); 00335 00336 return totalrval; 00337 }
| void ContinuationSystem::set_max_arclength_stepsize | ( | Real | maxds | ) | [inline] |
Sets (initializes) the max-allowable ds value and the current ds value. Call this before beginning arclength continuation. The default max stepsize is 0.1
Definition at line 129 of file continuation_system.h.
References ds, and ds_current.
00129 { ds=maxds; ds_current=maxds; }
| void ContinuationSystem::set_Theta | ( | ) | [private] |
A centralized function for setting the normalization parameter theta
Definition at line 1074 of file continuation_system.C.
Referenced by initialize_tangent(), and update_solution().
01075 { 01076 // // Use the norm of the latest solution, squared. 01077 //const Real normu = solution->l2_norm(); 01078 //libmesh_assert (normu != 0.0); 01079 //Theta = 1./normu/normu; 01080 01081 // // 1.) Use the norm of du, squared 01082 // *delta_u = *solution; 01083 // delta_u->add(-1, *previous_u); 01084 // delta_u->close(); 01085 // const Real normdu = delta_u->l2_norm(); 01086 01087 // if (normdu < 1.) // don't divide by zero or make a huge scaling parameter. 01088 // Theta = 1.; 01089 // else 01090 // Theta = 1./normdu/normdu; 01091 01092 // 2.) Use 1.0, i.e. don't scale 01093 Theta=1.; 01094 01095 // 3.) Use a formula which attempts to make the "solution triangle" isosceles. 01096 // libmesh_assert (std::abs(dlambda_ds) < 1.); 01097 01098 // *delta_u = *solution; 01099 // delta_u->add(-1, *previous_u); 01100 // delta_u->close(); 01101 // const Real normdu = delta_u->l2_norm(); 01102 01103 // Theta = std::sqrt(1. - dlambda_ds*dlambda_ds) / normdu * tau * ds; 01104 01105 01106 // // 4.) Use the norm of du and the norm of du/ds 01107 // *delta_u = *solution; 01108 // delta_u->add(-1, *previous_u); 01109 // delta_u->close(); 01110 // const Real normdu = delta_u->l2_norm(); 01111 // du_ds->close(); 01112 // const Real normduds = du_ds->l2_norm(); 01113 01114 // if (normduds < 1.e-12) 01115 // { 01116 // std::cout << "Setting initial Theta= 1./normdu/normdu" << std::endl; 01117 // std::cout << "normdu=" << normdu << std::endl; 01118 01119 // // Don't use this scaling if the solution delta is already O(1) 01120 // if (normdu > 1.) 01121 // Theta = 1./normdu/normdu; 01122 // else 01123 // Theta = 1.; 01124 // } 01125 // else 01126 // { 01127 // std::cout << "Setting Theta= 1./normdu/normduds" << std::endl; 01128 // std::cout << "normdu=" << normdu << std::endl; 01129 // std::cout << "normduds=" << normduds << std::endl; 01130 01131 // // Don't use this scaling if the solution delta is already O(1) 01132 // if ((normdu>1.) || (normduds>1.)) 01133 // Theta = 1./normdu/normduds; 01134 // else 01135 // Theta = 1.; 01136 // } 01137 01138 if (!quiet) 01139 std::cout << "Setting Normalization Parameter Theta=" << Theta << std::endl; 01140 }
| void ContinuationSystem::set_Theta_LOCA | ( | ) | [private] |
A centralized function for setting the other normalization parameter, i.e. the one suggested by the LOCA developers.
Definition at line 1144 of file continuation_system.C.
References dlambda_ds, quiet, and Theta_LOCA.
Referenced by update_solution().
01145 { 01146 // We also recompute the LOCA normalization parameter based on the 01147 // most recently computed value of dlambda_ds 01148 // if (!quiet) 01149 // std::cout << "(Theta_LOCA) dlambda_ds=" << dlambda_ds << std::endl; 01150 01151 // Formula makes no sense if |dlambda_ds| > 1 01152 libmesh_assert (std::abs(dlambda_ds) < 1.); 01153 01154 // 1.) Attempt to implement the method in LOCA paper 01155 // const Real g = 1./std::sqrt(2.); // "desired" dlambda_ds 01156 01157 // // According to the LOCA people, we only renormalize for 01158 // // when |dlambda_ds| exceeds some pre-selected maximum (which they take to be zero, btw). 01159 // if (std::abs(dlambda_ds) > .9) 01160 // { 01161 // // Note the *= ... This is updating the previous value of Theta_LOCA 01162 // // Note: The LOCA people actually use Theta_LOCA^2 to normalize their arclength constraint. 01163 // Theta_LOCA *= std::abs( (dlambda_ds/g)*std::sqrt( (1.-g*g) / (1.-dlambda_ds*dlambda_ds) ) ); 01164 01165 // // Suggested max-allowable value for Theta_LOCA 01166 // if (Theta_LOCA > 1.e8) 01167 // { 01168 // Theta_LOCA = 1.e8; 01169 01170 // if (!quiet) 01171 // std::cout << "max Theta_LOCA=" << Theta_LOCA << " has been selected." << std::endl; 01172 // } 01173 // } 01174 // else 01175 // Theta_LOCA=1.0; 01176 01177 // 2.) FIXME: Should we do *= or just =? This function is of dlambda_ds is 01178 // < 1, |dlambda_ds| < 1/sqrt(2) ~~ .7071 01179 // > 1, |dlambda_ds| > 1/sqrt(2) ~~ .7071 01180 Theta_LOCA *= std::abs( dlambda_ds / std::sqrt( (1.-dlambda_ds*dlambda_ds) ) ); 01181 01182 // Suggested max-allowable value for Theta_LOCA. I've never come close 01183 // to this value in my code. 01184 if (Theta_LOCA > 1.e8) 01185 { 01186 Theta_LOCA = 1.e8; 01187 01188 if (!quiet) 01189 std::cout << "max Theta_LOCA=" << Theta_LOCA << " has been selected." << std::endl; 01190 } 01191 01192 // 3.) Use 1.0, i.e. don't scale 01193 //Theta_LOCA=1.0; 01194 01195 if (!quiet) 01196 std::cout << "Setting Theta_LOCA=" << Theta_LOCA << std::endl; 01197 }
| virtual bool DifferentiableSystem::side_constraint | ( | bool | request_jacobian, | |
| DiffContext & | ||||
| ) | [inline, virtual, inherited] |
Adds the time derivative contribution on side of elem to elem_residual. If this method receives request_jacobian = true, then it should compute elem_jacobian and return true if possible. If elem_jacobian has not been computed then the method should return false.
Users may need to reimplement this for their particular PDE depending on the boundary conditions.
Definition at line 197 of file diff_system.h.
Referenced by SteadySolver::side_residual(), EulerSolver::side_residual(), Euler2Solver::side_residual(), and EigenTimeSolver::side_residual().
| virtual bool DifferentiableSystem::side_mass_residual | ( | bool | request_jacobian, | |
| DiffContext & | ||||
| ) | [inline, virtual, inherited] |
Adds a mass vector contribution on side of elem to elem_residual. If this method receives request_jacobian = true, then it should compute elem_jacobian and return true if possible. If elem_jacobian has not been computed then the method should return false.
For most problems, the default implementation of "do nothing" is correct; users with boundary conditions including time derivatives may need to reimplement this themselves.
Definition at line 336 of file diff_system.h.
Referenced by EulerSolver::side_residual(), Euler2Solver::side_residual(), and EigenTimeSolver::side_residual().
| virtual void DifferentiableSystem::side_postprocess | ( | DiffContext & | ) | [inline, virtual, inherited] |
Does any work that needs to be done on side of elem in a postprocessing loop.
Definition at line 231 of file diff_system.h.
Referenced by FEMSystem::postprocess().
| virtual void DifferentiableSystem::side_qoi | ( | DiffContext & | , | |
| const QoISet & | ||||
| ) | [inline, virtual, inherited] |
Does any work that needs to be done on side of elem in a quantity of interest assembly loop, outputting to elem_qoi.
Only qois included in the supplied QoISet need to be assembled.
Definition at line 263 of file diff_system.h.
Referenced by FEMSystem::assemble_qoi().
| virtual void DifferentiableSystem::side_qoi_derivative | ( | DiffContext & | , | |
| const QoISet & | ||||
| ) | [inline, virtual, inherited] |
Does any work that needs to be done on side of elem in a quantity of interest derivative assembly loop, outputting to elem_qoi_derivative.
Only qois included in the supplied QoISet need their derivatives assembled.
Definition at line 275 of file diff_system.h.
Referenced by FEMSystem::assemble_qoi_derivative().
| virtual bool DifferentiableSystem::side_time_derivative | ( | bool | request_jacobian, | |
| DiffContext & | ||||
| ) | [inline, virtual, inherited] |
Adds the time derivative contribution on side of elem to elem_residual. If this method receives request_jacobian = true, then it should compute elem_jacobian and return true if possible. If elem_jacobian has not been computed then the method should return false.
Users may need to reimplement this for their particular PDE depending on the boundary conditions.
Definition at line 181 of file diff_system.h.
Referenced by SteadySolver::side_residual(), EulerSolver::side_residual(), Euler2Solver::side_residual(), and EigenTimeSolver::side_residual().
| void ContinuationSystem::solve | ( | ) | [virtual] |
Perform a standard "solve" of the system, without doing continuation.
Reimplemented from FEMSystem.
Definition at line 115 of file continuation_system.C.
References Residual, and rhs_mode.
00116 { 00117 // Set the Residual RHS mode, and call the normal solve routine. 00118 rhs_mode = Residual; 00119 DifferentiableSystem::solve(); 00120 }
| void ContinuationSystem::solve_tangent | ( | ) | [private] |
Special solve algorithm for solving the tangent system.
Definition at line 965 of file continuation_system.C.
References FEMSystem::assembly(), continuation_parameter, delta_u, dlambda_ds, du_ds, G_Lambda, AutoPtr< Tp >::get(), libmesh_real(), linear_solver, ImplicitSystem::matrix, DiffSolver::max_linear_iterations, newton_solver, old_continuation_parameter, previous_dlambda_ds, previous_du_ds, previous_u, quiet, ExplicitSystem::rhs, rhs_mode, System::solution, tangent_initialized, Theta, Theta_LOCA, DifferentiableSystem::time_solver, and y.
Referenced by advance_arcstep(), and initialize_tangent().
00966 { 00967 // We shouldn't call this unless the current tangent already makes sense. 00968 libmesh_assert (tangent_initialized); 00969 00970 // Set pointer to underlying Newton solver 00971 if (!newton_solver) 00972 newton_solver = 00973 libmesh_cast_ptr<NewtonSolver*> (this->time_solver->diff_solver().get()); 00974 00975 // Assemble the system matrix AND rhs, with rhs = G_{\lambda} 00976 this->rhs_mode = G_Lambda; 00977 00978 // Assemble Residual and Jacobian 00979 this->assembly(true, // Residual 00980 true); // Jacobian 00981 00982 // Not sure if this is really necessary 00983 rhs->close(); 00984 00985 // Solve G_u*y = G_{\lambda} 00986 std::pair<unsigned int, Real> rval = 00987 linear_solver->solve(*matrix, 00988 *y, 00989 *rhs, 00990 1.e-12, // relative linear tolerance 00991 2*newton_solver->max_linear_iterations); // max linear iterations 00992 00993 // FIXME: If this doesn't converge at all, the new tangent vector is 00994 // going to be really bad... 00995 00996 if (!quiet) 00997 std::cout << "G_u*y = G_{lambda} solver converged at step " 00998 << rval.first 00999 << " linear tolerance = " 01000 << rval.second 01001 << "." 01002 << std::endl; 01003 01004 // Save old solution and parameter tangents for possible use in higher-order 01005 // predictor schemes. 01006 previous_dlambda_ds = dlambda_ds; 01007 *previous_du_ds = *du_ds; 01008 01009 01010 // 1.) Previous, probably wrong, technique! 01011 // // Solve for the updated d(lambda)/ds 01012 // // denom = N_{lambda} - (du_ds)^t y 01013 // // = d(lambda)/ds - (du_ds)^t y 01014 // Real denom = dlambda_ds - du_ds->dot(*y); 01015 01016 // //std::cout << "denom=" << denom << std::endl; 01017 // libmesh_assert (denom != 0.0); 01018 01019 // dlambda_ds = 1.0 / denom; 01020 01021 01022 // if (!quiet) 01023 // std::cout << "dlambda_ds=" << dlambda_ds << std::endl; 01024 01025 // // Compute the updated value of du/ds = -_dlambda_ds * y 01026 // du_ds->zero(); 01027 // du_ds->add(-dlambda_ds, *y); 01028 // du_ds->close(); 01029 01030 01031 // 2.) From Brian Carnes' paper... 01032 // According to Carnes, y comes from solving G_u * y = -G_{\lambda} 01033 y->scale(-1.); 01034 const Real ynorm = y->l2_norm(); 01035 dlambda_ds = 1. / std::sqrt(1. + Theta_LOCA*Theta_LOCA*Theta*ynorm*ynorm); 01036 01037 // Determine the correct sign for dlambda_ds. 01038 01039 // We will use delta_u to temporarily compute this sign. 01040 *delta_u = *solution; 01041 delta_u->add(-1., *previous_u); 01042 delta_u->close(); 01043 01044 const Real sgn_dlambda_ds = 01045 libmesh_real(Theta_LOCA*Theta_LOCA*Theta*y->dot(*delta_u) + 01046 (*continuation_parameter-old_continuation_parameter)); 01047 01048 if (sgn_dlambda_ds < 0.) 01049 { 01050 if (!quiet) 01051 std::cout << "dlambda_ds is negative." << std::endl; 01052 01053 dlambda_ds *= -1.; 01054 } 01055 01056 // Finally, set the new tangent vector, du/ds = dlambda/ds * y. 01057 du_ds->zero(); 01058 du_ds->add(dlambda_ds, *y); 01059 du_ds->close(); 01060 01061 if (!quiet) 01062 { 01063 std::cout << "d(lambda)/ds = " << dlambda_ds << std::endl; 01064 std::cout << "||du_ds|| = " << du_ds->l2_norm() << std::endl; 01065 } 01066 01067 // Our next solve expects y ~ -du/dlambda, so scale it back by -1 again now. 01068 y->scale(-1.); 01069 y->close(); 01070 }
| sys_type& ImplicitSystem::system | ( | ) | [inline, inherited] |
- Returns:
- a clever pointer to the system.
Reimplemented from ExplicitSystem.
Reimplemented in LinearImplicitSystem, and NonlinearImplicitSystem.
Definition at line 72 of file implicit_system.h.
| virtual std::string ImplicitSystem::system_type | ( | ) | const [inline, virtual, inherited] |
Assembles & solves the linear system Ax=b.
- Returns:
"Implicit". Helps in identifying the system type in an equation system file.
Reimplemented from ExplicitSystem.
Reimplemented in FrequencySystem, LinearImplicitSystem, NewmarkSystem, and NonlinearImplicitSystem.
Definition at line 107 of file implicit_system.h.
| void FEMSystem::time_evolving | ( | unsigned int | var | ) | [virtual, inherited] |
Tells the FEMSystem that variable var is evolving with respect to time. In general, the user's init() function should call time_evolving() for any variables which behave like du/dt = F(u), and should not call time_evolving() for any variables which behave like 0 = G(u).
Most derived systems will not have to reimplment this function; however any system which reimplements mass_residual() may have to reimplement time_evolving() to prepare data structures.
Reimplemented from DifferentiableSystem.
Definition at line 766 of file fem_system.C.
References DifferentiableSystem::time_evolving().
00767 { 00768 // Call the parent function 00769 Parent::time_evolving(var); 00770 }
| void System::update | ( | ) | [virtual, inherited] |
Update the local values to reflect the solution on neighboring processors.
Definition at line 295 of file system.C.
References System::_dof_map, System::current_local_solution, and System::solution.
Referenced by __libmesh_petsc_diff_solver_jacobian(), __libmesh_petsc_diff_solver_residual(), FEMSystem::assemble_qoi(), FEMSystem::assemble_qoi_derivative(), FEMSystem::assembly(), Problem_Interface::computeF(), GMVIO::copy_nodal_solution(), FEMSystem::mesh_position_get(), FEMSystem::postprocess(), NonlinearImplicitSystem::solve(), NewtonSolver::solve(), LinearImplicitSystem::solve(), and ExplicitSystem::solve().
00296 { 00297 const std::vector<unsigned int>& send_list = _dof_map->get_send_list (); 00298 00299 // Check sizes 00300 libmesh_assert (current_local_solution->size() == solution->size()); 00301 // More processors than elements => empty send_list 00302 // libmesh_assert (!send_list.empty()); 00303 libmesh_assert (send_list.size() <= solution->size()); 00304 00305 // Create current_local_solution from solution. This will 00306 // put a local copy of solution into current_local_solution. 00307 // Only the necessary values (specified by the send_list) 00308 // are copied to minimize communication 00309 solution->localize (*current_local_solution, send_list); 00310 }
| void System::update_global_solution | ( | std::vector< Number > & | global_soln, | |
| const unsigned int | dest_proc | |||
| ) | const [inherited] |
Fill the input vector global_soln so that it contains the global solution on processor dest_proc. Requires communication with all other processors.
Definition at line 539 of file system.C.
References System::solution.
00541 { 00542 global_soln.resize (solution->size()); 00543 00544 solution->localize_to_one (global_soln, dest_proc); 00545 }
| void System::update_global_solution | ( | std::vector< Number > & | global_soln | ) | const [inherited] |
Fill the input vector global_soln so that it contains the global solution on all processors. Requires communication with all other processors.
Definition at line 530 of file system.C.
References System::solution.
Referenced by ExactSolution::_compute_error(), EquationSystems::build_discontinuous_solution_vector(), EquationSystems::build_solution_vector(), and ExactErrorEstimator::estimate_error().
00531 { 00532 global_soln.resize (solution->size()); 00533 00534 solution->localize (global_soln); 00535 }
| void ContinuationSystem::update_solution | ( | ) | [private] |
This function (which assumes the most recent tangent vector has been computed) updates the solution and the control parameter with the initial guess for the next point on the continuation path.
Definition at line 1201 of file continuation_system.C.
References apply_predictor(), continuation_parameter, delta_u, ds, ds_current, ds_min, DiffSolver::max_nonlinear_iterations, newton_solver, newton_step, newton_stepgrowth_aggressiveness, old_continuation_parameter, previous_ds, previous_u, quiet, save_current_solution(), set_Theta(), set_Theta_LOCA(), System::solution, tangent_initialized, Theta, Theta_LOCA, y, and y_old.
Referenced by advance_arcstep(), and initialize_tangent().
01202 { 01203 // Set some stream formatting flags 01204 unsigned int old_precision = std::cout.precision(); 01205 std::cout.precision(16); 01206 std::cout.setf(std::ios_base::scientific); 01207 01208 // We must have a tangent that makes sense before we can update the solution. 01209 libmesh_assert (tangent_initialized); 01210 01211 // Compute tau, the stepsize scaling parameter which attempts to 01212 // reduce ds when the angle between the most recent two tangent 01213 // vectors becomes large. tau is actually the (absolute value of 01214 // the) cosine of the angle between these two vectors... so if tau ~ 01215 // 0 the angle is ~ 90 degrees, while if tau ~ 1 the angle is ~ 0 01216 // degrees. 01217 y_old->close(); 01218 y->close(); 01219 const Real yoldnorm = y_old->l2_norm(); 01220 const Real ynorm = y->l2_norm(); 01221 const Number yoldy = y_old->dot(*y); 01222 const Real yold_over_y = yoldnorm/ynorm; 01223 01224 if (!quiet) 01225 { 01226 std::cout << "yoldnorm=" << yoldnorm << std::endl; 01227 std::cout << "ynorm=" << ynorm << std::endl; 01228 std::cout << "yoldy=" << yoldy << std::endl; 01229 std::cout << "yoldnorm/ynorm=" << yoldnorm/ynorm << std::endl; 01230 } 01231 01232 // Save the current value of ds before updating it 01233 previous_ds = ds_current; 01234 01235 // // 1.) Cosine method (for some reason this always predicts the angle is ~0) 01236 // // Don't try divinding by zero 01237 // if ((yoldnorm > 1.e-12) && (ynorm > 1.e-12)) 01238 // tau = std::abs(yoldy) / yoldnorm / ynorm; 01239 // else 01240 // tau = 1.; 01241 01242 // // 2.) Relative size of old and new du/dlambda method with cutoff of 0.9 01243 // if ((yold_over_y < 0.9) && (yold_over_y > 1.e-6)) 01244 // tau = yold_over_y; 01245 // else 01246 // tau = 1.; 01247 01248 // 3.) Grow (or shrink) the arclength stepsize by the ratio of du/dlambda, but do not 01249 // exceed the user-specified value of ds. 01250 if (yold_over_y > 1.e-6) 01251 { 01252 // // 1.) Scale current ds by the ratio of successive tangents. 01253 // ds_current *= yold_over_y; 01254 // if (ds_current > ds) 01255 // ds_current = ds; 01256 01257 // 2.) Technique 1 tends to shrink the step fairly well (and even if it doesn't 01258 // get very small, we still have step reduction) but it seems to grow the step 01259 // very slowly. Another possible technique is step-doubling: 01260 // if (yold_over_y > 1.) 01261 // ds_current *= 2.; 01262 // else 01263 // ds_current *= yold_over_y; 01264 01265 // 3.) Technique 2 may over-zealous when we are also using the Newton stepgrowth 01266 // factor. For technique 3 we multiply by yold_over_y unless yold_over_y > 2 01267 // in which case we use 2. 01268 // if (yold_over_y > 2.) 01269 // ds_current *= 2.; 01270 // else 01271 // ds_current *= yold_over_y; 01272 01273 // 4.) Double-or-halve. We double the arc-step if the ratio of successive tangents 01274 // is larger than 'double_threshold', halve it if it is less than 'halve_threshold' 01275 const Real double_threshold = 0.5; 01276 const Real halve_threshold = 0.5; 01277 if (yold_over_y > double_threshold) 01278 ds_current *= 2.; 01279 else if (yold_over_y < halve_threshold) 01280 ds_current *= 0.5; 01281 01282 01283 // Also possibly use the number of Newton iterations required to compute the previous 01284 // step (relative to the maximum-allowed number of Newton iterations) to grow the step. 01285 if (newton_stepgrowth_aggressiveness > 0.) 01286 { 01287 libmesh_assert (newton_solver != NULL); 01288 const unsigned int Nmax = newton_solver->max_nonlinear_iterations; 01289 01290 // // The LOCA Newton step growth technique (note: only grows step length) 01291 // const Real stepratio = static_cast<Real>(Nmax-(newton_step+1))/static_cast<Real>(Nmax-1.); 01292 // const Real newtonstep_growthfactor = 1. + newton_stepgrowth_aggressiveness*stepratio*stepratio; 01293 01294 // The "Nopt/N" method, may grow or shrink the step. Assume Nopt=Nmax/2. 01295 const Real newtonstep_growthfactor = 01296 newton_stepgrowth_aggressiveness * 0.5 * 01297 static_cast<Real>(Nmax) / static_cast<Real>(newton_step+1); 01298 01299 if (!quiet) 01300 std::cout << "newtonstep_growthfactor=" << newtonstep_growthfactor << std::endl; 01301 01302 ds_current *= newtonstep_growthfactor; 01303 } 01304 } 01305 01306 01307 // Don't let the stepsize get above the user's maximum-allowed stepsize. 01308 if (ds_current > ds) 01309 ds_current = ds; 01310 01311 // Check also for a minimum allowed stepsize. 01312 if (ds_current < ds_min) 01313 { 01314 std::cout << "Enforcing minimum-allowed arclength stepsize of " << ds_min << std::endl; 01315 ds_current = ds_min; 01316 } 01317 01318 if (!quiet) 01319 { 01320 std::cout << "Current step size: ds_current=" << ds_current << std::endl; 01321 } 01322 01323 // Recompute scaling factor Theta for 01324 // the current solution before updating. 01325 set_Theta(); 01326 01327 // Also, recompute the LOCA scaling factor, which attempts to 01328 // maintain a reasonable value of dlambda/ds 01329 set_Theta_LOCA(); 01330 01331 std::cout << "Theta*Theta_LOCA^2=" << Theta*Theta_LOCA*Theta_LOCA << std::endl; 01332 01333 // Based on the asymptotic singular behavior of du/dlambda near simple turning points, 01334 // we can compute a single parameter which may suggest that we are close to a singularity. 01335 *delta_u = *solution; 01336 delta_u->add(-1, *previous_u); 01337 delta_u->close(); 01338 const Real normdu = delta_u->l2_norm(); 01339 const Real C = (std::log (Theta_LOCA*normdu) / 01340 std::log (std::abs(*continuation_parameter-old_continuation_parameter))) - 1.0; 01341 if (!quiet) 01342 std::cout << "C=" << C << std::endl; 01343 01344 // Save the current value of u and lambda before updating. 01345 save_current_solution(); 01346 01347 if (!quiet) 01348 { 01349 std::cout << "Updating the solution with the tangent guess." << std::endl; 01350 std::cout << "||u_old||=" << this->solution->l2_norm() << std::endl; 01351 std::cout << "lambda_old=" << *continuation_parameter << std::endl; 01352 } 01353 01354 // Since we solved for the tangent vector, now we can compute an 01355 // initial guess for the new solution, and an initial guess for the 01356 // new value of lambda. 01357 apply_predictor(); 01358 01359 if (!quiet) 01360 { 01361 std::cout << "||u_new||=" << this->solution->l2_norm() << std::endl; 01362 std::cout << "lambda_new=" << *continuation_parameter << std::endl; 01363 } 01364 01365 // Unset previous stream flags 01366 std::cout.precision(old_precision); 01367 std::cout.unsetf(std::ios_base::scientific); 01368 }
| void System::user_assembly | ( | ) | [virtual, inherited] |
Calls user's attached assembly function, or is overloaded by the user in derived classes.
Definition at line 1367 of file system.C.
References System::_assemble_system, System::_equation_systems, and System::name().
Referenced by System::assemble().
01368 { 01369 // Call the user-provided assembly function, 01370 // if it was provided 01371 if (_assemble_system != NULL) 01372 this->_assemble_system (_equation_systems, this->name()); 01373 }
| void System::user_constrain | ( | ) | [virtual, inherited] |
Calls user's attached constraint function, or is overloaded by the user in derived classes.
Definition at line 1377 of file system.C.
References System::_constrain_system, System::_equation_systems, and System::name().
Referenced by System::init_data(), and EquationSystems::reinit().
01378 { 01379 // Call the user-provided constraint function, 01380 // if it was provided 01381 if(_constrain_system!= NULL) 01382 this->_constrain_system(_equation_systems, this->name()); 01383 }
| void System::user_initialization | ( | ) | [virtual, inherited] |
Calls user's attached initialization function, or is overloaded by the user in derived classes.
Definition at line 1358 of file system.C.
References System::_equation_systems, System::_init_system, and System::name().
Referenced by System::init(), and NewmarkSystem::initial_conditions().
01359 { 01360 // Call the user-provided intialization function, 01361 // if it was provided 01362 if (_init_system != NULL) 01363 this->_init_system (_equation_systems, this->name()); 01364 }
| void System::user_QOI | ( | const QoISet & | qoi_indices | ) | [virtual, inherited] |
Calls user's attached quantity of interest function, or is overloaded by the user in derived classes.
Definition at line 1387 of file system.C.
References System::_equation_systems, System::_qoi_evaluate, and System::name().
Referenced by System::assemble_qoi().
01388 { 01389 // Call the user-provided quantity of interest function, 01390 // if it was provided 01391 if(_qoi_evaluate != NULL) 01392 this->_qoi_evaluate(_equation_systems, this->name(), qoi_indices); 01393 }
| void System::user_QOI_derivative | ( | const QoISet & | qoi_indices | ) | [virtual, inherited] |
Calls user's attached quantity of interest derivative function, or is overloaded by the user in derived classes.
Definition at line 1397 of file system.C.
References System::_equation_systems, System::_qoi_evaluate_derivative, and System::name().
Referenced by System::assemble_qoi_derivative().
01398 { 01399 // Call the user-provided quantity of interest derivative, 01400 // if it was provided 01401 if(_qoi_evaluate_derivative != NULL) 01402 this->_qoi_evaluate_derivative(_equation_systems, this->name(), qoi_indices); 01403 }
| const System::Variable & System::variable | ( | unsigned int | var | ) | const [inline, inherited] |
Return a constant reference to Variable var.
Definition at line 1404 of file system.h.
References System::_variables.
Referenced by EquationSystems::build_solution_vector(), and System::project_vector().
01405 { 01406 libmesh_assert (i < _variables.size()); 01407 01408 return _variables[i]; 01409 }
| const std::string & System::variable_name | ( | const unsigned int | i | ) | const [inline, inherited] |
- Returns:
- the name of variable
i.
Definition at line 1414 of file system.h.
References System::_variables.
Referenced by System::add_variable(), KellyErrorEstimator::boundary_side_integration(), DiscontinuityMeasure::boundary_side_integration(), ExactErrorEstimator::estimate_error(), ExactSolution::ExactSolution(), System::get_info(), System::ProjectVector::operator()(), System::project_vector(), VTKIO::solution_to_vtk(), and System::write_header().
01415 { 01416 libmesh_assert (i < _variables.size()); 01417 01418 return _variables[i].name(); 01419 }
| unsigned short int System::variable_number | ( | const std::string & | var | ) | const [inherited] |
- Returns:
- the variable number assoicated with the user-specified variable named
var.
Definition at line 942 of file system.C.
References System::_variable_numbers, and System::_variables.
Referenced by ExactSolution::_compute_error(), GMVIO::copy_nodal_solution(), ExactErrorEstimator::estimate_error(), ExactErrorEstimator::find_squared_element_error(), System::variable_type(), EnsightIO::write_scalar_ascii(), and EnsightIO::write_vector_ascii().
00943 { 00944 // Make sure the variable exists 00945 std::map<std::string, unsigned short int>::const_iterator 00946 pos = _variable_numbers.find(var); 00947 00948 if (pos == _variable_numbers.end()) 00949 { 00950 std::cerr << "ERROR: variable " 00951 << var 00952 << " does not exist in this system!" 00953 << std::endl; 00954 libmesh_error(); 00955 } 00956 libmesh_assert (_variables[pos->second].name() == var); 00957 00958 return pos->second; 00959 }
| const FEType & System::variable_type | ( | const std::string & | var | ) | const [inline, inherited] |
- Returns:
- the finite element type for variable
var.
Definition at line 1434 of file system.h.
References System::_variables, and System::variable_number().
01435 { 01436 return _variables[this->variable_number(var)].type(); 01437 }
| const FEType & System::variable_type | ( | const unsigned int | i | ) | const [inline, inherited] |
- Returns:
- the finite element type variable number
i.
Definition at line 1424 of file system.h.
References System::_variables.
Referenced by System::add_variable(), EquationSystems::build_discontinuous_solution_vector(), EquationSystems::build_solution_vector(), GMVIO::copy_nodal_solution(), FEMContext::FEMContext(), System::write_header(), EnsightIO::write_scalar_ascii(), and EnsightIO::write_vector_ascii().
01425 { 01426 libmesh_assert (i < _variables.size()); 01427 01428 return _variables[i].type(); 01429 }
| const std::string & System::vector_name | ( | const unsigned int | vec_num | ) | [inherited] |
- Returns:
- the name of this system's additional vector number
vec_num(where the vectors are counted starting with 0).
Definition at line 698 of file system.C.
References System::vectors_begin(), and System::vectors_end().
00699 { 00700 const_vectors_iterator v = vectors_begin(); 00701 const_vectors_iterator v_end = vectors_end(); 00702 unsigned int num = 0; 00703 while((num<vec_num) && (v!=v_end)) 00704 { 00705 num++; 00706 ++v; 00707 } 00708 libmesh_assert(v!=v_end); 00709 return v->first; 00710 }
| System::const_vectors_iterator System::vectors_begin | ( | ) | const [inline, inherited] |
Beginning of vectors container
Definition at line 1470 of file system.h.
References System::_vectors.
01471 { 01472 return _vectors.begin(); 01473 }
| System::vectors_iterator System::vectors_begin | ( | ) | [inline, inherited] |
Beginning of vectors container
Definition at line 1464 of file system.h.
References System::_vectors.
Referenced by System::get_vector(), System::request_vector(), VTKIO::system_vectors_to_vtk(), and System::vector_name().
01465 { 01466 return _vectors.begin(); 01467 }
| System::const_vectors_iterator System::vectors_end | ( | ) | const [inline, inherited] |
End of vectors container
Definition at line 1482 of file system.h.
References System::_vectors.
01483 { 01484 return _vectors.end(); 01485 }
| System::vectors_iterator System::vectors_end | ( | ) | [inline, inherited] |
End of vectors container
Definition at line 1476 of file system.h.
References System::_vectors.
Referenced by System::get_vector(), System::request_vector(), VTKIO::system_vectors_to_vtk(), and System::vector_name().
01477 { 01478 return _vectors.end(); 01479 }
| std::pair< unsigned int, Real > ImplicitSystem::weighted_sensitivity_adjoint_solve | ( | const ParameterVector & | parameters, | |
| const ParameterVector & | weights, | |||
| const QoISet & | qoi_indices = QoISet() | |||
| ) | [virtual, inherited] |
Assembles & solves the linear system(s) (dR/du)^T*z_w = sum(w_p*(d^2q/dudp - d^2R/dudp*z)), for those parameters p contained within parameters, weighted by the values w_p found within weights.
Assumes that adjoint_solve has already calculated z for each qoi in qoi_indices.
Returns a pair with the total number of linear iterations performed and the (sum of the) final residual norms
Reimplemented from System.
Definition at line 404 of file implicit_system.C.
References System::add_weighted_sensitivity_adjoint_solution(), System::assemble_before_solve, ExplicitSystem::assemble_qoi_derivative(), ImplicitSystem::assembly(), ParameterVector::deep_copy(), DofMap::enforce_constraints_exactly(), System::get_adjoint_rhs(), System::get_adjoint_solution(), System::get_dof_map(), ImplicitSystem::get_linear_solve_parameters(), ImplicitSystem::get_linear_solver(), System::get_weighted_sensitivity_adjoint_solution(), QoISet::has_index(), ImplicitSystem::matrix, System::qoi, ImplicitSystem::release_linear_solver(), ExplicitSystem::rhs, LinearSolver< T >::solve(), and ParameterVector::value_copy().
00407 { 00408 // Log how long the linear solve takes. 00409 START_LOG("weighted_sensitivity_adjoint_solve()", "ImplicitSystem"); 00410 00411 // We currently get partial derivatives via central differencing 00412 const Real delta_p = TOLERANCE; 00413 00414 // The forward system should now already be solved. 00415 // The adjoint system should now already be solved. 00416 // Now we're assembling a weighted sum of adjoint-adjoint systems: 00417 // 00418 // dR/du (u, sum_l(w_l*z^l)) = sum_l(w_l*(Q''_ul - R''_ul (u, z))) 00419 00420 // We'll assemble the rhs first, because the R'' term will require 00421 // perturbing the jacobian 00422 00423 // We'll use temporary rhs vectors, because we haven't (yet) found 00424 // any good reasons why users might want to save these: 00425 00426 std::vector<NumericVector<Number> *> temprhs(this->qoi.size()); 00427 for (unsigned int i=0; i != this->qoi.size(); ++i) 00428 if (qoi_indices.has_index(i)) 00429 temprhs[i] = this->rhs->zero_clone().release(); 00430 00431 // We approximate the _l partial derivatives via a central 00432 // differencing perturbation in the w_l direction: 00433 // 00434 // sum_l(w_l*v_l) ~= (v(p + dp*w_l*e_l) - v(p - dp*w_l*e_l))/(2*dp) 00435 00436 // PETSc doesn't implement SGEMX, so neither does NumericVector, 00437 // so we want to avoid calculating f -= R'*z. We'll thus evaluate 00438 // the above equation by first adding -v(p+dp...), then multiplying 00439 // the intermediate result vectors by -1, then adding -v(p-dp...), 00440 // then finally dividing by 2*dp. 00441 00442 ParameterVector oldparameters, parameterperturbation; 00443 parameters.deep_copy(oldparameters); 00444 weights.deep_copy(parameterperturbation); 00445 parameterperturbation *= delta_p; 00446 parameters += parameterperturbation; 00447 00448 this->assembly(false, true); 00449 this->matrix->close(); 00450 00451 // Take the discrete adjoint, so that we can calculate R_u(u,z) with 00452 // a matrix-vector product of R_u and z. 00453 matrix->get_transpose(*matrix); 00454 00455 this->assemble_qoi_derivative(qoi_indices); 00456 for (unsigned int i=0; i != this->qoi.size(); ++i) 00457 if (qoi_indices.has_index(i)) 00458 { 00459 *(temprhs[i]) -= this->get_adjoint_rhs(i); 00460 this->matrix->vector_mult_add(*(temprhs[i]), this->get_adjoint_solution(i)); 00461 *(temprhs[i]) *= -1.0; 00462 } 00463 00464 oldparameters.value_copy(parameters); 00465 parameterperturbation *= -1.0; 00466 parameters += parameterperturbation; 00467 00468 this->assembly(false, true); 00469 this->matrix->close(); 00470 matrix->get_transpose(*matrix); 00471 00472 this->assemble_qoi_derivative(qoi_indices); 00473 for (unsigned int i=0; i != this->qoi.size(); ++i) 00474 if (qoi_indices.has_index(i)) 00475 { 00476 *(temprhs[i]) -= this->get_adjoint_rhs(i); 00477 this->matrix->vector_mult_add(*(temprhs[i]), this->get_adjoint_solution(i)); 00478 *(temprhs[i]) /= (2.0*delta_p); 00479 } 00480 00481 // Finally, assemble the jacobian at the non-perturbed parameter 00482 // values 00483 oldparameters.value_copy(parameters); 00484 00485 if (this->assemble_before_solve) 00486 { 00487 // Build the Jacobian 00488 this->assembly(false, true); 00489 this->matrix->close(); 00490 00491 // Take the discrete adjoint 00492 matrix->get_transpose(*matrix); 00493 } 00494 00495 // The weighted adjoint-adjoint problem is linear 00496 LinearSolver<Number> *linear_solver = this->get_linear_solver(); 00497 00498 // Our iteration counts and residuals will be sums of the individual 00499 // results 00500 std::pair<unsigned int, Real> solver_params = 00501 this->get_linear_solve_parameters(); 00502 std::pair<unsigned int, Real> totalrval = std::make_pair(0,0.0); 00503 00504 for (unsigned int i=0; i != this->qoi.size(); ++i) 00505 if (qoi_indices.has_index(i)) 00506 { 00507 const std::pair<unsigned int, Real> rval = 00508 linear_solver->solve (*matrix, this->add_weighted_sensitivity_adjoint_solution(i), 00509 *(temprhs[i]), 00510 solver_params.second, 00511 solver_params.first); 00512 00513 totalrval.first += rval.first; 00514 totalrval.second += rval.second; 00515 } 00516 00517 this->release_linear_solver(linear_solver); 00518 00519 for (unsigned int i=0; i != this->qoi.size(); ++i) 00520 if (qoi_indices.has_index(i)) 00521 delete temprhs[i]; 00522 00523 // The linear solver may not have fit our constraints exactly 00524 #ifdef LIBMESH_ENABLE_AMR 00525 for (unsigned int i=0; i != this->qoi.size(); ++i) 00526 if (qoi_indices.has_index(i)) 00527 this->get_dof_map().enforce_constraints_exactly 00528 (*this, &this->get_weighted_sensitivity_adjoint_solution(i)); 00529 #endif 00530 00531 // Stop logging the nonlinear solve 00532 STOP_LOG("weighted_sensitivity_adjoint_solve()", "ImplicitSystem"); 00533 00534 return totalrval; 00535 }
| std::pair< unsigned int, Real > ImplicitSystem::weighted_sensitivity_solve | ( | const ParameterVector & | parameters, | |
| const ParameterVector & | weights | |||
| ) | [virtual, inherited] |
Assembles & solves the linear system(s) (dR/du)*u_w = sum(w_p*-dR/dp), for those parameters p contained within parameters weighted by the values w_p found within weights.
Returns a pair with the total number of linear iterations performed and the (sum of the) final residual norms
Reimplemented from System.
Definition at line 540 of file implicit_system.C.
References System::add_weighted_sensitivity_solution(), ImplicitSystem::assembly(), ParameterVector::deep_copy(), DofMap::enforce_constraints_exactly(), System::get_dof_map(), ImplicitSystem::get_linear_solve_parameters(), ImplicitSystem::get_linear_solver(), System::get_weighted_sensitivity_solution(), ImplicitSystem::matrix, ImplicitSystem::release_linear_solver(), ExplicitSystem::rhs, LinearSolver< T >::solve(), and ParameterVector::value_copy().
00542 { 00543 // Log how long the linear solve takes. 00544 START_LOG("weighted_sensitivity_solve()", "ImplicitSystem"); 00545 00546 // We currently get partial derivatives via central differencing 00547 const Real delta_p = TOLERANCE; 00548 00549 // The forward system should now already be solved. 00550 00551 // Now we're assembling a weighted sum of sensitivity systems: 00552 // 00553 // dR/du (u, v)(sum(w_l*u'_l)) = -sum_l(w_l*R'_l (u, v)) forall v 00554 00555 // We'll assemble the rhs first, because the R' term will require 00556 // perturbing the system, and some applications may not be able to 00557 // assemble a perturbed residual without simultaneously constructing 00558 // a perturbed jacobian. 00559 00560 // We approximate the _l partial derivatives via a central 00561 // differencing perturbation in the w_l direction: 00562 // 00563 // sum_l(w_l*v_l) ~= (v(p + dp*w_l*e_l) - v(p - dp*w_l*e_l))/(2*dp) 00564 00565 ParameterVector oldparameters, parameterperturbation; 00566 parameters.deep_copy(oldparameters); 00567 weights.deep_copy(parameterperturbation); 00568 parameterperturbation *= delta_p; 00569 parameters += parameterperturbation; 00570 00571 this->assembly(true, false); 00572 this->rhs->close(); 00573 00574 AutoPtr<NumericVector<Number> > temprhs = this->rhs->clone(); 00575 00576 oldparameters.value_copy(parameters); 00577 parameterperturbation *= -1.0; 00578 parameters += parameterperturbation; 00579 00580 this->assembly(true, false); 00581 this->rhs->close(); 00582 00583 *temprhs -= *(this->rhs); 00584 *temprhs /= (2.0*delta_p); 00585 00586 // Finally, assemble the jacobian at the non-perturbed parameter 00587 // values 00588 oldparameters.value_copy(parameters); 00589 00590 // Build the Jacobian 00591 this->assembly(false, true); 00592 this->matrix->close(); 00593 00594 // The weighted sensitivity problem is linear 00595 LinearSolver<Number> *linear_solver = this->get_linear_solver(); 00596 00597 std::pair<unsigned int, Real> solver_params = 00598 this->get_linear_solve_parameters(); 00599 00600 const std::pair<unsigned int, Real> rval = 00601 linear_solver->solve (*matrix, this->add_weighted_sensitivity_solution(), 00602 *temprhs, 00603 solver_params.second, 00604 solver_params.first); 00605 00606 this->release_linear_solver(linear_solver); 00607 00608 // The linear solver may not have fit our constraints exactly 00609 #ifdef LIBMESH_ENABLE_AMR 00610 this->get_dof_map().enforce_constraints_exactly 00611 (*this, &this->get_weighted_sensitivity_solution()); 00612 #endif 00613 00614 // Stop logging the nonlinear solve 00615 STOP_LOG("weighted_sensitivity_solve()", "ImplicitSystem"); 00616 00617 return rval; 00618 }
| void System::write_header | ( | Xdr & | io, | |
| const std::string & | version, | |||
| const bool | write_additional_data | |||
| ) | const [inherited] |
Writes the basic data header for this System.
This method implements the output of a System object, embedded in the output of an EquationSystems<T_sys>. This warrants some documentation. The output of this part consists of 5 sections:
for this system
5.) The number of variables in the system (unsigned int)
for each variable in the system
6.) The name of the variable (string)
7.) Combined in an FEType:
- The approximation order(s) of the variable (Order Enum, cast to int/s)
- The finite element family/ies of the variable (FEFamily Enum, cast to int/s)
end variable loop
8.) The number of additional vectors (unsigned int),
for each additional vector in the system object
9.) the name of the additional vector (string)
end system
Definition at line 815 of file system_io.C.
References System::_vectors, Xdr::data(), FEType::family, System::get_mesh(), FEType::inf_map, System::n_vars(), System::n_vectors(), System::name(), FEType::order, MeshBase::processor_id(), FEType::radial_family, FEType::radial_order, type, System::variable_name(), System::variable_type(), and Xdr::writing().
00818 { 00850 libmesh_assert (io.writing()); 00851 00852 00853 // Only write the header information 00854 // if we are processor 0. 00855 if (this->get_mesh().processor_id() != 0) 00856 return; 00857 00858 std::string comment; 00859 char buf[80]; 00860 00861 // 5.) 00862 // Write the number of variables in the system 00863 00864 { 00865 // set up the comment 00866 comment = "# No. of Variables in System \""; 00867 comment += this->name(); 00868 comment += "\""; 00869 00870 unsigned int n_vars = this->n_vars(); 00871 io.data (n_vars, comment.c_str()); 00872 } 00873 00874 00875 for (unsigned int var=0; var<this->n_vars(); var++) 00876 { 00877 // 6.) 00878 // Write the name of the var-th variable 00879 { 00880 // set up the comment 00881 comment = "# Name, Variable No. "; 00882 std::sprintf(buf, "%d", var); 00883 comment += buf; 00884 comment += ", System \""; 00885 comment += this->name(); 00886 comment += "\""; 00887 00888 std::string var_name = this->variable_name(var); 00889 io.data (var_name, comment.c_str()); 00890 } 00891 00892 // 7.) 00893 // Write the approximation order of the var-th variable 00894 // in this system 00895 { 00896 // set up the comment 00897 comment = "# Approximation Order, Variable \""; 00898 std::sprintf(buf, "%s", this->variable_name(var).c_str()); 00899 comment += buf; 00900 comment += "\", System \""; 00901 comment += this->name(); 00902 comment += "\""; 00903 00904 int order = static_cast<int>(this->variable_type(var).order); 00905 io.data (order, comment.c_str()); 00906 } 00907 00908 00909 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00910 00911 // do the same for radial_order 00912 { 00913 comment = "# Radial Approximation Order, Variable \""; 00914 std::sprintf(buf, "%s", this->variable_name(var).c_str()); 00915 comment += buf; 00916 comment += "\", System \""; 00917 comment += this->name(); 00918 comment += "\""; 00919 00920 int rad_order = static_cast<int>(this->variable_type(var).radial_order); 00921 io.data (rad_order, comment.c_str()); 00922 } 00923 00924 #endif 00925 00926 // Write the Finite Element type of the var-th variable 00927 // in this System 00928 { 00929 // set up the comment 00930 comment = "# FE Family, Variable \""; 00931 std::sprintf(buf, "%s", this->variable_name(var).c_str()); 00932 comment += buf; 00933 comment += "\", System \""; 00934 comment += this->name(); 00935 comment += "\""; 00936 00937 const FEType& type = this->variable_type(var); 00938 int fam = static_cast<int>(type.family); 00939 io.data (fam, comment.c_str()); 00940 00941 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00942 00943 comment = "# Radial FE Family, Variable \""; 00944 std::sprintf(buf, "%s", this->variable_name(var).c_str()); 00945 comment += buf; 00946 comment += "\", System \""; 00947 comment += this->name(); 00948 comment += "\""; 00949 00950 int radial_fam = static_cast<int>(type.radial_family); 00951 io.data (radial_fam, comment.c_str()); 00952 00953 comment = "# Infinite Mapping Type, Variable \""; 00954 std::sprintf(buf, "%s", this->variable_name(var).c_str()); 00955 comment += buf; 00956 comment += "\", System \""; 00957 comment += this->name(); 00958 comment += "\""; 00959 00960 int i_map = static_cast<int>(type.inf_map); 00961 io.data (i_map, comment.c_str()); 00962 #endif 00963 } 00964 } // end of the variable loop 00965 00966 // 8.) 00967 // Write the number of additional vectors in the System. 00968 // If write_additional_data==false, then write zero for 00969 // the number of additional vectors. 00970 { 00971 { 00972 // set up the comment 00973 comment = "# No. of Additional Vectors, System \""; 00974 comment += this->name(); 00975 comment += "\""; 00976 00977 unsigned int n_vectors = write_additional_data ? this->n_vectors () : 0; 00978 io.data (n_vectors, comment.c_str()); 00979 } 00980 00981 if (write_additional_data) 00982 { 00983 std::map<std::string, NumericVector<Number>* >::const_iterator 00984 vec_pos = this->_vectors.begin(); 00985 unsigned int cnt=0; 00986 00987 for (; vec_pos != this->_vectors.end(); ++vec_pos) 00988 { 00989 // 9.) 00990 // write the name of the cnt-th additional vector 00991 comment = "# Name of "; 00992 std::sprintf(buf, "%d", cnt++); 00993 comment += buf; 00994 comment += "th vector"; 00995 std::string vec_name = vec_pos->first; 00996 00997 io.data (vec_name, comment.c_str()); 00998 } 00999 } 01000 } 01001 }
| void System::write_parallel_data | ( | Xdr & | io, | |
| const bool | write_additional_data | |||
| ) | const [inherited] |
Writes additional data, namely vectors, for this System. This method may safely be called on a distributed-memory mesh. This method will create an individual file for each processor in the simulation where the local solution components for that processor will be stored.
This method implements the output of the vectors contained in this System object, embedded in the output of an EquationSystems<T_sys>.
9.) The global solution vector, re-ordered to be node-major (More on this later.)
for each additional vector in the object
10.) The global additional vector, re-ordered to be node-major (More on this later.)
Note that the actual IO is handled through the Xdr class (to be renamed later?) which provides a uniform interface to both the XDR (eXternal Data Representation) interface and standard ASCII output. Thus this one section of code will read XDR or ASCII files with no changes.
This method implements the output of the vectors contained in this System object, embedded in the output of an EquationSystems<T_sys>.
9.) The global solution vector, re-ordered to be node-major (More on this later.)
for each additional vector in the object
10.) The global additional vector, re-ordered to be node-major (More on this later.)
Note that the actual IO is handled through the Xdr class (to be renamed later?) which provides a uniform interface to both the XDR (eXternal Data Representation) interface and standard ASCII output. Thus this one section of code will read XDR or ASCII files with no changes.
Definition at line 1213 of file system_io.C.
References System::_vectors, Xdr::data(), System::get_mesh(), DofObject::invalid_id, System::n_vars(), System::name(), System::number(), System::solution, and Xdr::writing().
01215 { 01235 std::string comment; 01236 01237 libmesh_assert (io.writing()); 01238 01239 std::vector<Number> io_buffer; io_buffer.reserve(this->solution->local_size()); 01240 01241 // build the ordered nodes and element maps. 01242 // when writing/reading parallel files we need to iterate 01243 // over our nodes/elements in order of increasing global id(). 01244 // however, this is not guaranteed to be ordering we obtain 01245 // by using the node_iterators/element_iterators directly. 01246 // so build a set, sorted by id(), that provides the ordering. 01247 // further, for memory economy build the set but then transfer 01248 // its contents to vectors, which will be sorted. 01249 std::vector<const DofObject*> ordered_nodes, ordered_elements; 01250 { 01251 std::set<const DofObject*, CompareDofObjectsByID> 01252 ordered_nodes_set (this->get_mesh().local_nodes_begin(), 01253 this->get_mesh().local_nodes_end()); 01254 01255 ordered_nodes.insert(ordered_nodes.end(), 01256 ordered_nodes_set.begin(), 01257 ordered_nodes_set.end()); 01258 } 01259 { 01260 std::set<const DofObject*, CompareDofObjectsByID> 01261 ordered_elements_set (this->get_mesh().local_elements_begin(), 01262 this->get_mesh().local_elements_end()); 01263 01264 ordered_elements.insert(ordered_elements.end(), 01265 ordered_elements_set.begin(), 01266 ordered_elements_set.end()); 01267 } 01268 01269 const unsigned int sys_num = this->number(); 01270 const unsigned int n_vars = this->n_vars(); 01271 01272 // Loop over each variable and each node, and write out the value. 01273 for (unsigned int var=0; var<n_vars; var++) 01274 { 01275 // First write the node DOF values 01276 for (std::vector<const DofObject*>::const_iterator 01277 it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) 01278 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 01279 { 01280 //std::cout << "(*it)->id()=" << (*it)->id() << std::endl; 01281 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 01282 DofObject::invalid_id); 01283 01284 io_buffer.push_back((*this->solution)((*it)->dof_number(sys_num, var, comp))); 01285 } 01286 01287 // Then write the element DOF values 01288 for (std::vector<const DofObject*>::const_iterator 01289 it = ordered_elements.begin(); it != ordered_elements.end(); ++it) 01290 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 01291 { 01292 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 01293 DofObject::invalid_id); 01294 01295 io_buffer.push_back((*this->solution)((*it)->dof_number(sys_num, var, comp))); 01296 } 01297 } 01298 01299 // 9.) 01300 // 01301 // Actually write the reordered solution vector 01302 // for the ith system to disk 01303 01304 // set up the comment 01305 { 01306 comment = "# System \""; 01307 comment += this->name(); 01308 comment += "\" Solution Vector"; 01309 } 01310 01311 io.data (io_buffer, comment.c_str()); 01312 01313 // Only write additional vectors if wanted 01314 if (write_additional_data) 01315 { 01316 std::map<std::string, NumericVector<Number>* >::const_iterator 01317 pos = _vectors.begin(); 01318 01319 for(; pos != this->_vectors.end(); ++pos) 01320 { 01321 io_buffer.clear(); io_buffer.reserve( pos->second->local_size()); 01322 01323 // Loop over each variable and each node, and write out the value. 01324 for (unsigned int var=0; var<n_vars; var++) 01325 { 01326 // First write the node DOF values 01327 for (std::vector<const DofObject*>::const_iterator 01328 it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) 01329 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 01330 { 01331 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 01332 DofObject::invalid_id); 01333 01334 io_buffer.push_back((*pos->second)((*it)->dof_number(sys_num, var, comp))); 01335 } 01336 01337 // Then write the element DOF values 01338 for (std::vector<const DofObject*>::const_iterator 01339 it = ordered_elements.begin(); it != ordered_elements.end(); ++it) 01340 for (unsigned int comp=0; comp<(*it)->n_comp(sys_num, var); comp++) 01341 { 01342 libmesh_assert ((*it)->dof_number(sys_num, var, comp) != 01343 DofObject::invalid_id); 01344 01345 io_buffer.push_back((*pos->second)((*it)->dof_number(sys_num, var, comp))); 01346 } 01347 } 01348 01349 // 10.) 01350 // 01351 // Actually write the reordered additional vector 01352 // for this system to disk 01353 01354 // set up the comment 01355 { 01356 comment = "# System \""; 01357 comment += this->name(); 01358 comment += "\" Additional Vector \""; 01359 comment += pos->first; 01360 comment += "\""; 01361 } 01362 01363 io.data (io_buffer, comment.c_str()); 01364 } 01365 } 01366 }
| void System::write_serialized_data | ( | Xdr & | io, | |
| const bool | write_additional_data = true | |||
| ) | const [inherited] |
Writes additional data, namely vectors, for this System. This method may safely be called on a distributed-memory mesh.
This method implements the output of the vectors contained in this System object, embedded in the output of an EquationSystems<T_sys>.
9.) The global solution vector, re-ordered to be node-major (More on this later.)
for each additional vector in the object
10.) The global additional vector, re-ordered to be node-major (More on this later.)
Definition at line 1370 of file system_io.C.
References System::_vectors, Xdr::comment(), System::name(), libMesh::processor_id(), System::solution, and System::write_serialized_vector().
01372 { 01386 parallel_only(); 01387 std::string comment; 01388 01389 this->write_serialized_vector(io, *this->solution); 01390 01391 // set up the comment 01392 if (libMesh::processor_id() == 0) 01393 { 01394 comment = "# System \""; 01395 comment += this->name(); 01396 comment += "\" Solution Vector"; 01397 01398 io.comment (comment); 01399 } 01400 01401 // Only write additional vectors if wanted 01402 if (write_additional_data) 01403 { 01404 std::map<std::string, NumericVector<Number>* >::const_iterator 01405 pos = _vectors.begin(); 01406 01407 for(; pos != this->_vectors.end(); ++pos) 01408 { 01409 this->write_serialized_vector(io, *pos->second); 01410 01411 // set up the comment 01412 if (libMesh::processor_id() == 0) 01413 { 01414 comment = "# System \""; 01415 comment += this->name(); 01416 comment += "\" Additional Vector \""; 01417 comment += pos->first; 01418 comment += "\""; 01419 io.comment (comment); 01420 } 01421 } 01422 } 01423 }
| void System::zero_variable | ( | NumericVector< Number > & | v, | |
| unsigned int | var_num | |||
| ) | const [inherited] |
Zeroes all dofs in v that correspond to variable number var_num.
Definition at line 995 of file system.C.
References MeshBase::active_local_elements_begin(), MeshBase::active_local_elements_end(), DofObject::dof_number(), System::get_mesh(), MeshBase::local_nodes_begin(), MeshBase::local_nodes_end(), mesh, DofObject::n_comp(), System::n_vars(), System::number(), and NumericVector< T >::set().
00996 { 00997 /* Make sure the call makes sense. */ 00998 libmesh_assert(var_num<this->n_vars()); 00999 01000 /* Get a reference to the mesh. */ 01001 const MeshBase& mesh = this->get_mesh(); 01002 01003 /* Check which system we are. */ 01004 const unsigned int sys_num = this->number(); 01005 01006 /* Loop over nodes. */ 01007 { 01008 MeshBase::const_node_iterator it = mesh.local_nodes_begin(); 01009 const MeshBase::const_node_iterator end_it = mesh.local_nodes_end(); 01010 for ( ; it != end_it; ++it) 01011 { 01012 const Node* node = *it; 01013 unsigned int n_comp = node->n_comp(sys_num,var_num); 01014 for(unsigned int i=0; i<n_comp; i++) 01015 { 01016 const unsigned int index = node->dof_number(sys_num,var_num,i); 01017 v.set(index,0.0); 01018 } 01019 } 01020 } 01021 01022 /* Loop over elements. */ 01023 { 01024 MeshBase::const_element_iterator it = mesh.active_local_elements_begin(); 01025 const MeshBase::const_element_iterator end_it = mesh.active_local_elements_end(); 01026 for ( ; it != end_it; ++it) 01027 { 01028 const Elem* elem = *it; 01029 unsigned int n_comp = elem->n_comp(sys_num,var_num); 01030 for(unsigned int i=0; i<n_comp; i++) 01031 { 01032 const unsigned int index = elem->dof_number(sys_num,var_num,i); 01033 v.set(index,0.0); 01034 } 01035 } 01036 } 01037 }
Member Data Documentation
ReferenceCounter::Counts ReferenceCounter::_counts [static, protected, inherited] |
Actually holds the data.
Definition at line 110 of file reference_counter.h.
Referenced by ReferenceCounter::get_info(), ReferenceCounter::increment_constructor_count(), and ReferenceCounter::increment_destructor_count().
unsigned int FEMSystem::_mesh_sys [protected, inherited] |
System and variables from which to acquire moving mesh information
Definition at line 309 of file fem_system.h.
Referenced by FEMSystem::eulerian_residual(), FEMSystem::mesh_position_get(), FEMSystem::mesh_position_set(), FEMSystem::mesh_x_position(), FEMSystem::mesh_y_position(), FEMSystem::mesh_z_position(), and FEMSystem::numerical_jacobian().
unsigned int FEMSystem::_mesh_x_var [protected, inherited] |
Definition at line 309 of file fem_system.h.
Referenced by FEMSystem::eulerian_residual(), FEMSystem::mesh_position_get(), FEMSystem::mesh_x_position(), and FEMSystem::numerical_jacobian().
unsigned int FEMSystem::_mesh_y_var [protected, inherited] |
Definition at line 309 of file fem_system.h.
Referenced by FEMSystem::eulerian_residual(), FEMSystem::mesh_position_get(), FEMSystem::mesh_y_position(), and FEMSystem::numerical_jacobian().
unsigned int FEMSystem::_mesh_z_var [protected, inherited] |
Definition at line 309 of file fem_system.h.
Referenced by FEMSystem::eulerian_residual(), FEMSystem::mesh_position_get(), FEMSystem::mesh_z_position(), and FEMSystem::numerical_jacobian().
Threads::spin_mutex ReferenceCounter::_mutex [static, protected, inherited] |
Mutual exclusion object to enable thread-safe reference counting.
Definition at line 123 of file reference_counter.h.
Threads::atomic< unsigned int > ReferenceCounter::_n_objects [static, protected, inherited] |
The number of objects. Print the reference count information when the number returns to 0.
Definition at line 118 of file reference_counter.h.
Referenced by ReferenceCounter::n_objects(), ReferenceCounter::ReferenceCounter(), and ReferenceCounter::~ReferenceCounter().
std::vector<bool> DifferentiableSystem::_time_evolving [protected, inherited] |
Stores bools to tell us which variables are evolving in time and which are just constraints
Definition at line 443 of file diff_system.h.
Referenced by DifferentiableSystem::clear(), FEMSystem::eulerian_residual(), FEMSystem::init_context(), DifferentiableSystem::init_data(), FEMSystem::mass_residual(), and DifferentiableSystem::time_evolving().
bool System::assemble_before_solve [inherited] |
Flag which tells the system to whether or not to call the user assembly function during each call to solve(). By default, every call to solve() begins with a call to the user assemble, so this flag is true. (For explicit systems, "solving" the system occurs during the assembly step, so this flag is always true for explicit systems.)
You will only want to set this to false if you need direct control over when the system is assembled, and are willing to track the state of its assembly yourself. An example of such a case is an implicit system with multiple right hand sides. In this instance, a single assembly would likely be followed with multiple calls to solve.
The frequency system and Newmark system have their own versions of this flag, called _finished_assemble, which might be able to be replaced with this more general concept.
Definition at line 985 of file system.h.
Referenced by ImplicitSystem::adjoint_solve(), ImplicitSystem::sensitivity_solve(), LinearImplicitSystem::solve(), EigenSystem::solve(), and ImplicitSystem::weighted_sensitivity_adjoint_solve().
bool DifferentiableSystem::assemble_qoi_sides [inherited] |
If assemble_qoi_sides is true (it is false by default), the assembly loop for a quantity of interest or its derivatives will loop over all sides as well as all elements.
Definition at line 220 of file diff_system.h.
Referenced by FEMSystem::assemble_qoi(), and FEMSystem::assemble_qoi_derivative().
bool DifferentiableSystem::compute_internal_sides [inherited] |
compute_internal_sides is false by default, indicating that side_* computations will only be done on boundary sides. If compute_internal_sides is true, computations will be done on sides between elements as well.
Definition at line 168 of file diff_system.h.
Referenced by FEMSystem::assemble_qoi(), FEMSystem::assemble_qoi_derivative(), FEMSystem::assembly(), and FEMSystem::postprocess().
The continuation parameter must be a member variable of the derived class, and the "continuation_parameter" pointer defined here must be a pointer to that variable. This is how the continuation system updates the derived class's continuation parameter.
Also sometimes referred to as "lambda" in the code comments.
Definition at line 116 of file continuation_system.h.
Referenced by apply_predictor(), continuation_solve(), initialize_tangent(), save_current_solution(), solve_tangent(), and update_solution().
How tightly should the Newton iterations attempt to converge delta_lambda. Defaults to 1.e-6.
Definition at line 135 of file continuation_system.h.
Referenced by continuation_solve().
AutoPtr<NumericVector<Number> > System::current_local_solution [inherited] |
All the values I need to compute my contribution to the simulation at hand. Think of this as the current solution with any ghost values needed from other processors. This vector is necessarily larger than the solution vector in the case of a parallel simulation. The update() member is used to synchronize the contents of the solution and current_local_solution vectors.
Definition at line 1012 of file system.h.
Referenced by NonlinearImplicitSystem::assembly(), System::clear(), Problem_Interface::computeF(), System::current_solution(), ExactErrorEstimator::estimate_error(), System::init_data(), System::project_solution(), System::re_update(), System::reinit(), System::restrict_vectors(), and System::update().
NumericVector<Number>* ContinuationSystem::delta_u [private] |
Temporary vector "delta u" ... the Newton step update in our custom augmented PDE solve.
Definition at line 371 of file continuation_system.h.
Referenced by continuation_solve(), init_data(), solve_tangent(), and update_solution().
Real DifferentiableSystem::deltat [inherited] |
For time-dependent problems, this is the amount delta t to advance the solution in time.
Definition at line 384 of file diff_system.h.
Referenced by UnsteadySolver::advance_timestep(), EulerSolver::element_residual(), Euler2Solver::element_residual(), FEMSystem::eulerian_residual(), EulerSolver::side_residual(), Euler2Solver::side_residual(), UnsteadySolver::solve(), and TwostepTimeSolver::solve().
Real ContinuationSystem::dlambda_ds [private] |
The most recent value of the derivative of the continuation parameter with respect to s. We use "lambda" here for shortness of notation, lambda always refers to the continuation parameter.
Definition at line 397 of file continuation_system.h.
Referenced by apply_predictor(), continuation_solve(), initialize_tangent(), set_Theta_LOCA(), and solve_tangent().
Real ContinuationSystem::ds [private] |
The initial arclength stepsize, selected by the user. This is the max-allowable arclength stepsize, but the algorithm may frequently reduce ds near turning points.
Definition at line 404 of file continuation_system.h.
Referenced by set_max_arclength_stepsize(), and update_solution().
Real ContinuationSystem::ds_current [private] |
Value of stepsize currently in use. Will not exceed user-provided maximum arclength stepize ds.
Definition at line 410 of file continuation_system.h.
Referenced by apply_predictor(), continuation_solve(), initialize_tangent(), set_max_arclength_stepsize(), and update_solution().
The minimum-allowed steplength, defaults to 1.e-8.
Definition at line 215 of file continuation_system.h.
Referenced by update_solution().
NumericVector<Number>* ContinuationSystem::du_ds [private] |
Extra work vectors used by the continuation algorithm. These are added to the system by the init_data() routine.
The "solution" tangent vector du/ds.
Definition at line 339 of file continuation_system.h.
Referenced by apply_predictor(), continuation_solve(), init_data(), initialize_tangent(), and solve_tangent().
int FEMSystem::extra_quadrature_order [inherited] |
By default, when calling the user-defined residual functions, the FEMSystem will first set up an appropriate FEType::default_quadrature_rule() object for performing the integration. This rule will integrate elements of order up to 2*p+1 exactly (where p is the sum of the base FEType and local p refinement levels), but if additional (or reduced) quadrature accuracy is desired then this extra_quadrature_order (default 0) will be added.
Definition at line 249 of file fem_system.h.
Referenced by FEMContext::FEMContext().
bool FEMSystem::fe_reinit_during_postprocess [inherited] |
If fe_reinit_during_postprocess is true (it is true by default), FE objects will be reinit()ed with their default quadrature rules. If false, FE objects will need to be reinit()ed by the user or will be in an undefined state.
Definition at line 238 of file fem_system.h.
Referenced by FEMSystem::postprocess().
How much to try to reduce the residual by at the first (inexact) Newton step. This is frequently something large like 1/2 in an inexact Newton method, to prevent oversolving.
Definition at line 148 of file continuation_system.h.
Referenced by continuation_solve().
AutoPtr<LinearSolver<Number> > ContinuationSystem::linear_solver [private] |
We maintain our own linear solver interface, for solving custom systems of equations and/or things which do not require a full-blown NewtonSolver.
Definition at line 378 of file continuation_system.h.
Referenced by continuation_solve(), and solve_tangent().
SparseMatrix<Number>* ImplicitSystem::matrix [inherited] |
The system matrix. Implicit systems are characterized by the need to solve the linear system Ax=b. This is the system matrix A.
Definition at line 326 of file implicit_system.h.
Referenced by __libmesh_petsc_diff_solver_jacobian(), ImplicitSystem::add_system_matrix(), ImplicitSystem::adjoint_solve(), ImplicitSystem::assemble(), NonlinearImplicitSystem::assembly(), LinearImplicitSystem::assembly(), FEMSystem::assembly(), ImplicitSystem::clear(), NewmarkSystem::compute_matrix(), continuation_solve(), ImplicitSystem::init_matrices(), ImplicitSystem::sensitivity_solve(), PetscDiffSolver::solve(), NonlinearImplicitSystem::solve(), NewtonSolver::solve(), LinearImplicitSystem::solve(), FrequencySystem::solve(), EigenTimeSolver::solve(), solve_tangent(), ImplicitSystem::weighted_sensitivity_adjoint_solve(), and ImplicitSystem::weighted_sensitivity_solve().