35 template <
unsigned DIM>
39 template <
unsigned DIM>
43 template <
unsigned DIM>
47 template <
unsigned DIM>
51 template <
unsigned DIM>
57 template<
unsigned DIM>
63 if ((strain.
ncol()!=DIM)||(strain.
nrow()!=DIM))
65 std::ostringstream error_message;
66 error_message <<
"Strain matrix is " << strain.
ncol() <<
" x " 67 << strain.
nrow() <<
", but dimension of the equations is " 70 OOMPH_CURRENT_FUNCTION,
71 OOMPH_EXCEPTION_LOCATION);
90 unsigned n_node = nnode();
93 unsigned u_nodal_index[DIM];
94 for(
unsigned i=0;
i<DIM;
i++) {u_nodal_index[
i] = u_index(
i);}
101 (void) dshape_eulerian(s,psi,dpsidx);
107 for(
unsigned l=0;l<n_node;l++)
110 for(
unsigned i=0;
i<DIM;
i++)
113 const double u_value = this->nodal_value(l,u_nodal_index[
i]);
116 for(
unsigned j=0;j<DIM;j++)
118 interpolated_dudx(i,j) += u_value*dpsidx(l,j);
124 for(
unsigned i=0;
i<DIM;
i++)
129 for(
int j=(DIM-1);j>=
static_cast<int>(
i);j--)
132 if(static_cast<int>(
i)!=j)
135 0.5*(interpolated_dudx(
i,j) + interpolated_dudx(j,
i));
140 strain(
i,
i) = interpolated_dudx(
i,
i);
144 for(
int j=(
i-1);j>=0;j--)
146 strain(
i,j) = strain(j,
i);
159 template<
unsigned DIM>
165 if ((stress.
ncol()!=DIM)||(stress.
nrow()!=DIM))
167 std::ostringstream error_message;
168 error_message <<
"Stress matrix is " << stress.
ncol() <<
" x " 169 << stress.
nrow() <<
", but dimension of the equations is " 172 OOMPH_CURRENT_FUNCTION,
173 OOMPH_EXCEPTION_LOCATION);
179 this->get_strain(s,strain);
184 for(
unsigned i=0;
i<DIM;
i++)
186 for(
unsigned j=0;j<DIM;j++)
189 for (
unsigned k=0;k<DIM;k++)
191 for (
unsigned l=0;k<DIM;k++)
193 stress(
i,j)+=this->
E(
i,j,k,l)*strain(k,l);
203 template<
unsigned DIM>
206 const Shape &q_basis_local,
209 Shape &q_basis)
const 213 this->dshape_local(s,psi,dpsi);
219 double det = local_to_eulerian_mapping(dpsi,jacobian,inverse_jacobian);
223 this->transform_derivatives(inverse_jacobian,dpsi);
226 const unsigned n_q_basis = this->nq_basis();
229 for(
unsigned l=0;l<n_q_basis;l++)
232 for(
unsigned i=0;
i<DIM;
i++)
240 for(
unsigned i=0;
i<DIM;
i++)
243 for(
unsigned j=0;j<DIM;j++)
247 double jac_trans = jacobian(j,
i)/det;
250 for(
unsigned l=0;l<n_q_basis;l++)
253 q_basis(l,
i) += jac_trans*q_basis_local(l,j);
260 scale_basis(q_basis);
267 template<
unsigned DIM>
269 const unsigned &nplot)
275 outfile << tecplot_zone_string(nplot);
278 unsigned num_plot_points=nplot_points(nplot);
280 for(
unsigned iplot=0;iplot<num_plot_points;iplot++)
283 get_s_plot(iplot,nplot,s);
286 for(
unsigned i=0;
i<DIM;
i++)
288 outfile << interpolated_x(s,
i) <<
" ";
292 for(
unsigned i=0;
i<DIM;
i++)
294 outfile << interpolated_u(s,
i) <<
" ";
298 for(
unsigned i=0;
i<DIM;
i++)
300 outfile << interpolated_q(s,
i) <<
" ";
304 outfile << interpolated_div_q(s) <<
" ";
307 outfile << interpolated_p(s) <<
" ";
309 const unsigned n_node=this->nnode();
316 for(
unsigned i=0;
i<DIM;
i++)
318 for(
unsigned l=0;l<n_node;l++)
320 interpolated_du_dt[
i]+=du_dt(l,
i)*psi(l);
322 outfile << interpolated_du_dt[
i] <<
" ";
327 for(
unsigned i=0;
i<DIM;
i++)
329 for(
unsigned l=0;l<n_node;l++)
331 interpolated_d2u_dt2[
i]+=d2u_dt2(l,
i)*psi(l);
333 outfile << interpolated_d2u_dt2[
i] <<
" ";
336 const unsigned n_q_basis=this->nq_basis();
337 const unsigned n_q_basis_edge=this->nq_basis_edge();
339 Shape q_basis(n_q_basis,DIM), q_basis_local(n_q_basis,DIM);
340 this->get_q_basis_local(s,q_basis_local);
341 (void)this->transform_basis(s,q_basis_local,psi,q_basis);
345 for(
unsigned i=0;
i<DIM;
i++)
347 for(
unsigned l=0;l<n_q_basis_edge;l++)
349 interpolated_dq_dt[
i]+=dq_edge_dt(l)*q_basis(l,
i);
351 for(
unsigned l=n_q_basis_edge;l<n_q_basis;l++)
353 interpolated_dq_dt[
i]+=dq_internal_dt(l-n_q_basis_edge)*q_basis(l,
i);
355 outfile << interpolated_dq_dt[
i] <<
" ";
358 outfile << std::endl;
362 this->write_tecplot_zone_footer(outfile,nplot);
367 template<
unsigned DIM>
369 std::ostream &outfile,
370 const unsigned &nplot,
380 outfile << this->tecplot_zone_string(nplot);
386 unsigned num_plot_points=this->nplot_points(nplot);
388 for(
unsigned iplot=0;iplot<num_plot_points;iplot++)
391 this->get_s_plot(iplot,nplot,s);
394 this->interpolated_x(s,x);
397 (*exact_soln_pt)(x,exact_soln);
400 for(
unsigned i=0;
i<DIM;
i++)
402 outfile << x[
i] <<
" ";
404 for(
unsigned i=0;
i<2*DIM+2;
i++)
406 outfile << exact_soln[
i] <<
" ";
408 outfile << std::endl;
412 this->write_tecplot_zone_footer(outfile,nplot);
417 template<
unsigned DIM>
419 std::ostream &outfile,
420 const unsigned &nplot,
431 outfile << this->tecplot_zone_string(nplot);
437 unsigned num_plot_points=this->nplot_points(nplot);
439 for(
unsigned iplot=0;iplot<num_plot_points;iplot++)
442 this->get_s_plot(iplot,nplot,s);
445 this->interpolated_x(s,x);
448 (*exact_soln_pt)(time,x,exact_soln);
451 for(
unsigned i=0;
i<DIM;
i++)
453 outfile << x[
i] <<
" ";
455 for(
unsigned i=0;
i<2*DIM+2;
i++)
457 outfile << exact_soln[
i] <<
" ";
459 outfile << std::endl;
463 this->write_tecplot_zone_footer(outfile,nplot);
468 template<
unsigned DIM>
470 std::ostream &outfile,
475 for(
unsigned i=0;
i<3;
i++)
488 unsigned n_intpt = this->integral_pt()->nweight();
490 outfile <<
"ZONE" << std::endl;
496 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
499 for(
unsigned i=0;
i<DIM;
i++)
501 s[
i] = this->integral_pt()->knot(ipt,
i);
505 double w = this->integral_pt()->weight(ipt);
508 double J=this->J_eulerian(s);
514 this->interpolated_x(s,x);
517 (*exact_soln_pt)(x,exact_soln);
520 for(
unsigned i=0;
i<DIM;
i++)
522 norm[0]+=exact_soln[
i]*exact_soln[
i]*
W;
524 error[0]+=(exact_soln[
i]-this->interpolated_u(s,
i))*
525 (exact_soln[
i]-this->interpolated_u(s,
i))*W;
529 for(
unsigned i=0;
i<DIM;
i++)
531 norm[1]+=exact_soln[DIM+
i]*exact_soln[DIM+
i]*
W;
533 error[1]+=(exact_soln[DIM+
i]-this->interpolated_q(s,
i))*
534 (exact_soln[DIM+
i]-this->interpolated_q(s,
i))*W;
538 norm[1]+=exact_soln[2*DIM]*exact_soln[2*DIM]*
W;
539 error[1]+=(exact_soln[2*DIM]-interpolated_div_q(s))*
540 (exact_soln[2*DIM]-interpolated_div_q(s))*W;
543 norm[2]+=exact_soln[2*DIM+1]*exact_soln[2*DIM+1]*
W;
544 error[2]+=(exact_soln[2*DIM+1]-this->interpolated_p(s))*
545 (exact_soln[2*DIM+1]-this->interpolated_p(s))*W;
548 for(
unsigned i=0;
i<DIM;
i++)
550 outfile << x[
i] <<
" ";
554 for(
unsigned i=0;
i<DIM;
i++)
556 outfile << exact_soln[
i]-this->interpolated_u(s,
i) <<
" ";
560 for(
unsigned i=0;
i<DIM;
i++)
562 outfile << exact_soln[DIM+
i]-this->interpolated_q(s,
i) <<
" ";
566 outfile << exact_soln[2*DIM+1]-this->interpolated_p(s) <<
" ";
568 outfile << std::endl;
574 template<
unsigned DIM>
576 std::ostream &outfile,
582 for(
unsigned i=0;
i<3;
i++)
595 unsigned n_intpt = this->integral_pt()->nweight();
597 outfile <<
"ZONE" << std::endl;
603 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
606 for(
unsigned i=0;
i<DIM;
i++)
608 s[
i] = this->integral_pt()->knot(ipt,
i);
612 double w = this->integral_pt()->weight(ipt);
615 double J=this->J_eulerian(s);
621 this->interpolated_x(s,x);
624 (*exact_soln_pt)(time,x,exact_soln);
627 for(
unsigned i=0;
i<DIM;
i++)
629 norm[0]+=exact_soln[
i]*exact_soln[
i]*
W;
631 error[0]+=(exact_soln[
i]-this->interpolated_u(s,
i))*
632 (exact_soln[
i]-this->interpolated_u(s,
i))*W;
636 for(
unsigned i=0;
i<DIM;
i++)
638 norm[1]+=exact_soln[DIM+
i]*exact_soln[DIM+
i]*
W;
640 error[1]+=(exact_soln[DIM+
i]-this->interpolated_q(s,
i))*
641 (exact_soln[DIM+
i]-this->interpolated_q(s,
i))*W;
645 norm[1]+=exact_soln[2*DIM]*exact_soln[2*DIM]*
W;
646 error[1]+=(exact_soln[2*DIM]-interpolated_div_q(s))*
647 (exact_soln[2*DIM]-interpolated_div_q(s))*W;
650 norm[2]+=exact_soln[2*DIM+1]*exact_soln[2*DIM+1]*
W;
651 error[2]+=(exact_soln[2*DIM+1]-this->interpolated_p(s))*
652 (exact_soln[2*DIM+1]-this->interpolated_p(s))*W;
655 for(
unsigned i=0;
i<DIM;
i++)
657 outfile << x[
i] <<
" ";
661 for(
unsigned i=0;
i<DIM;
i++)
663 outfile << exact_soln[
i]-this->interpolated_u(s,
i) <<
" ";
667 for(
unsigned i=0;
i<DIM;
i++)
669 outfile << exact_soln[DIM+
i]-this->interpolated_q(s,
i) <<
" ";
673 outfile << exact_soln[2*DIM+1]-this->interpolated_p(s) <<
" ";
675 outfile << std::endl;
680 template<
unsigned DIM>
688 const unsigned n_node = nnode();
689 const unsigned n_q_basis = nq_basis();
690 const unsigned n_q_basis_edge = nq_basis_edge();
691 const unsigned n_p_basis = np_basis();
695 u_basis(n_node), u_test(n_node),
696 q_basis(n_q_basis,DIM), q_test(n_q_basis,DIM),
697 p_basis(n_p_basis), p_test(n_p_basis),
698 div_q_basis_ds(n_q_basis), div_q_test_ds(n_q_basis);
700 DShape dpsidx(n_node,DIM), du_basis_dx(n_node,DIM), du_test_dx(n_node,DIM);
703 unsigned n_intpt = integral_pt()->nweight();
715 double mass_source_local;
718 double lambda_sq = this->lambda_sq();
721 double k_inv = this->k_inv();
724 double alpha = this->alpha();
727 double porosity = this->porosity();
730 double density_ratio = this->density_ratio();
733 double rho_f_over_rho = density_ratio/(1+porosity*(density_ratio-1));
736 double time=node_pt(0)->time_stepper_pt()->time_pt()->time();
739 int local_eqn = 0, local_unknown = 0;
742 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
745 for(
unsigned i=0;
i<DIM;
i++) { s[
i] = integral_pt()->knot(ipt,
i); }
748 double w = integral_pt()->weight(ipt);
753 shape_basis_test_local_at_knot(
756 du_basis_dx,du_test_dx,
759 div_q_basis_ds,div_q_test_ds);
765 double interpolated_div_du_dt_dx=0.0;
768 double interpolated_div_q_ds=0.0;
770 double interpolated_p=0.0;
773 for(
unsigned l=0;l<n_node;l++)
776 for(
unsigned i=0;
i<DIM;
i++)
778 interpolated_x[
i] += nodal_position(l,
i)*psi(l);
780 interpolated_d2u_dt2[
i] += this->d2u_dt2(l,
i)*u_basis(l);
783 const double u_value = this->raw_nodal_value(l,u_index(
i));
784 interpolated_u[
i] += u_value*u_basis(l);
787 for(
unsigned j=0;j<DIM;j++)
789 interpolated_du_dx(
i,j) += u_value*du_basis_dx(l,j);
793 interpolated_div_du_dt_dx += this->du_dt(l,
i)*du_basis_dx(l,
i);
799 for(
unsigned i=0;
i<DIM;
i++)
802 for(
unsigned l=0;l<n_q_basis_edge;l++)
804 interpolated_q[
i] += q_edge(l)*q_basis(l,
i);
805 interpolated_dq_dt[
i] += dq_edge_dt(l)*q_basis(l,
i);
808 for(
unsigned l=n_q_basis_edge;l<n_q_basis;l++)
810 interpolated_q[
i] += q_internal(l-n_q_basis_edge)*q_basis(l,
i);
811 interpolated_dq_dt[
i] += dq_internal_dt(l-n_q_basis_edge)*q_basis(l,
i);
816 for(
unsigned l=0;l<n_p_basis;l++)
818 interpolated_p += p_value(l)*p_basis(l);
823 for(
unsigned l=0;l<n_q_basis_edge;l++)
825 interpolated_div_q_ds += q_edge(l)*div_q_basis_ds(l);
827 for(
unsigned l=n_q_basis_edge;l<n_q_basis;l++)
829 interpolated_div_q_ds += q_internal(l-n_q_basis_edge)*div_q_basis_ds(l);
833 this->force_solid(time,interpolated_x,f_solid);
836 this->force_fluid(time,interpolated_x,f_fluid);
839 this->mass_source(time,interpolated_x,mass_source_local);
846 for(
unsigned l=0;l<n_node;l++)
848 for(
unsigned a=0;a<DIM;a++)
850 local_eqn = this->nodal_local_eqn(l,u_index(a));
854 residuals[local_eqn] +=
855 (lambda_sq*(interpolated_d2u_dt2[a]
856 +rho_f_over_rho*interpolated_dq_dt[a]
862 for(
unsigned b=0;b<DIM;b++)
866 residuals[local_eqn] -= alpha*interpolated_p*du_test_dx(l,b)*
W;
869 for(
unsigned c=0;c<DIM;c++)
871 for(
unsigned d=0;d<DIM;d++)
874 residuals[local_eqn] +=
875 this->
E(a,b,c,d)*interpolated_du_dx(c,d)*du_test_dx(l,b)*
W;
883 for(
unsigned l2=0;l2<n_node;l2++)
885 for(
unsigned c=0;c<DIM;c++)
887 local_unknown=this->nodal_local_eqn(l2,u_index(c));
892 jacobian(local_eqn,local_unknown)+=
894 this->node_pt(l2)->time_stepper_pt()->weight(2,0)*
895 u_basis(l2)*u_test(l)*
W;
898 for(
unsigned b=0;b<DIM;b++)
900 for(
unsigned d=0;d<DIM;d++)
902 jacobian(local_eqn,local_unknown)+=
903 this->
E(a,b,c,d)*du_basis_dx(l2,d)*du_test_dx(l,b)*
W;
911 for(
unsigned l2=0;l2<n_q_basis;l2++)
915 if(l2<n_q_basis_edge)
917 local_unknown=q_edge_local_eqn(l2);
919 this->node_pt(q_edge_node_number(l2))->time_stepper_pt();
923 local_unknown=q_internal_local_eqn(l2-n_q_basis_edge);
925 this->internal_data_pt(q_internal_index())->time_stepper_pt();
930 jacobian(local_eqn,local_unknown)+=
931 lambda_sq*rho_f_over_rho*timestepper_pt->
weight(1,0)*
932 q_basis(l2,a)*u_test(l)*
W;
937 for(
unsigned l2=0;l2<n_p_basis;l2++)
939 local_unknown=p_local_eqn(l2);
942 jacobian(local_eqn,local_unknown)-=
943 alpha*p_basis(l2)*du_test_dx(l,a)*
W;
954 for(
unsigned l=0;l<n_q_basis;l++)
958 local_eqn = q_edge_local_eqn(l);
962 local_eqn = q_internal_local_eqn(l-n_q_basis_edge);
968 for(
unsigned i=0;
i<DIM;
i++)
970 residuals[local_eqn] +=
971 (k_inv*interpolated_q[
i]
972 -rho_f_over_rho*f_fluid[
i]
973 +rho_f_over_rho*lambda_sq*(interpolated_d2u_dt2[
i]
974 +(1.0/porosity)*interpolated_dq_dt[
i]
980 residuals[local_eqn] -= (interpolated_p*div_q_test_ds(l))*w;
986 for(
unsigned l2=0;l2<n_node;l2++)
988 for(
unsigned c=0;c<DIM;c++)
990 local_unknown=this->nodal_local_eqn(l2,u_index(c));
993 jacobian(local_eqn,local_unknown)+=
994 rho_f_over_rho*lambda_sq*
995 this->node_pt(l2)->time_stepper_pt()->weight(2,0)*
996 u_basis(l2)*q_test(l,c)*
W;
1002 for(
unsigned l2=0;l2<n_q_basis;l2++)
1006 if(l2<n_q_basis_edge)
1008 local_unknown=q_edge_local_eqn(l2);
1010 this->node_pt(q_edge_node_number(l2))->time_stepper_pt();
1014 local_unknown=q_internal_local_eqn(l2-n_q_basis_edge);
1016 this->internal_data_pt(q_internal_index())->time_stepper_pt();
1019 if(local_unknown>=0)
1021 for(
unsigned c=0;c<DIM;c++)
1023 jacobian(local_eqn,local_unknown)+=
1024 q_basis(l2,c)*q_test(l,c)*
1026 rho_f_over_rho*lambda_sq*
1027 timestepper_pt->
weight(1,0)/porosity)*W;
1033 for(
unsigned l2=0;l2<n_p_basis;l2++)
1035 local_unknown=p_local_eqn(l2);
1038 jacobian(local_eqn,local_unknown)-=
1039 p_basis(l2)*div_q_test_ds(l)*w;
1046 for(
unsigned l=0;l<n_p_basis;l++)
1049 local_eqn=p_local_eqn(l);
1055 residuals[local_eqn]+=alpha*interpolated_div_du_dt_dx*p_test(l)*w*J;
1057 residuals[local_eqn]+=interpolated_div_q_ds*p_test(l)*w;
1059 residuals[local_eqn]-=mass_source_local*p_test(l)*w*J;
1065 for(
unsigned l2=0;l2<n_node;l2++)
1067 for(
unsigned c=0;c<DIM;c++)
1069 local_unknown=this->nodal_local_eqn(l2,u_index(c));
1071 if(local_unknown>=0)
1073 jacobian(local_eqn,local_unknown)+=
1074 alpha*this->node_pt(l2)->time_stepper_pt()->weight(1,0)*
1075 du_basis_dx(l2,c)*p_test(l)*
W;
1081 for(
unsigned l2=0;l2<n_q_basis;l2++)
1083 if(l2<n_q_basis_edge)
1085 local_unknown=q_edge_local_eqn(l2);
1089 local_unknown=q_internal_local_eqn(l2-n_q_basis_edge);
1092 if(local_unknown>=0)
1094 jacobian(local_eqn,local_unknown)+=
1095 p_test(l)*div_q_basis_ds(l2)*w;
unsigned long nrow() const
Return the number of rows of the matrix.
static double Default_k_inv_value
Static default value for 1/k.
unsigned long ncol() const
Return the number of columns of the matrix.
void output(std::ostream &outfile)
Output with default number of plot points.
virtual void fill_in_generic_residual_contribution(Vector< double > &residuals, DenseMatrix< double > &jacobian, bool flag)
Fill in residuals and, if flag==true, jacobian.
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as ...
static double Default_porosity_value
Static default value for the porosity.
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output FE representation of exact soln: x,y,u1,u2,div_q,p at Nplot^DIM plot points.
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
static double Default_alpha_value
Static default value for alpha.
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
static double Default_lambda_sq_value
Static default value for timescale ratio (1.0 – for natural scaling)
void get_stress(const Vector< double > &s, DenseMatrix< double > &sigma) const
Return the Cauchy stress tensor, as calculated from the elasticity tensor at specified local coordina...
double transform_basis(const Vector< double > &s, const Shape &q_basis_local, Shape &psi, DShape &dpsi, Shape &q_basis) const
Performs a div-conserving transformation of the vector basis functions from the reference element to ...
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
static double Default_density_ratio_value
Static default value for the density ratio.
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
Compute the error between the FE solution and the exact solution using the H(div) norm for q and L^2 ...
void get_strain(const Vector< double > &s, DenseMatrix< double > &strain) const
Return the strain tensor.