42 #include "axisym_navier_stokes.h" 45 #include "fluid_interface.h" 48 #include "meshes/horizontal_single_layer_spine_mesh.h" 51 using namespace oomph;
75 double Ca = pow(Film_Thickness,3.0);
118 template<
class ELEMENT>
145 unsigned n_node = this->nnode();
148 const unsigned c_index = C_index;
160 for(
unsigned l=0;l<n_node;l++)
162 C += this->nodal_value(l,c_index)*psi(l);
172 TimeStepper* time_stepper_pt= this->node_pt(l)->time_stepper_pt();
177 if (time_stepper_pt->type()!=
"Steady")
180 const unsigned c_index = C_index;
183 const unsigned n_time = time_stepper_pt->ntstorage();
185 for(
unsigned t=0;t<n_time;t++)
187 dcdt += time_stepper_pt->weight(1,t)*this->nodal_value(t,l,c_index);
196 double sigma(
const Vector<double> &s)
199 const unsigned n_node = this->nnode();
206 for(
unsigned l=0;l<n_node;l++)
208 C += this->nodal_value(l,C_index)*psi(l);
212 double Beta = this->beta();
214 return (1.0 - Beta*(C-1.0));
222 this->fill_in_generic_residual_contribution_interface(residuals,jacobian,1);
226 const unsigned n_node = this->nnode();
228 const unsigned n_dof = this->ndof();
230 Vector<double> newres(n_dof);
236 const double fd_step = this->Default_fd_jacobian_step;
239 for(
unsigned n=0;n<n_node;n++)
242 unsigned c_index = this->C_index;
245 local_unknown = this->nodal_local_eqn(n,c_index);
247 if(local_unknown >= 0)
250 double *value_pt = this->node_pt(n)->value_pt(c_index);
253 double old_var = *value_pt;
256 *value_pt += fd_step;
259 this->get_residuals(newres);
262 for(
unsigned m=0;m<n_dof;m++)
264 double sum = (newres[m] - residuals[m])/fd_step;
266 jacobian(m,local_unknown) = sum;
276 SpineElement<FaceGeometry<ELEMENT> >::fill_in_jacobian_from_geometric_data(jacobian);
284 const unsigned &flag,
const Shape &psif,
const DShape &dpsifds,
285 const DShape &dpsifdS,
const DShape &dpsifdS_div,
286 const Vector<double> &s,
287 const Vector<double> &interpolated_x,
const Vector<double> &interpolated_n,
288 const double &W,
const double &J)
292 bool Integrated_curvature =
true;
295 unsigned n_node = this->nnode();
298 int local_eqn = 0, local_unknown = 0;
303 unsigned c_index = this->C_index;
304 Vector<unsigned> u_index = this->U_index_interface;
307 const double Pe_s = this->peclet_s();
311 const double r = interpolated_x[0];
314 const double J_raw = J/r;
318 double interpolated_C = 0.0;
319 double interpolated_dCds = 0.0;
322 const unsigned ndim = this->node_pt(0)->ndim();
323 Vector<double> interpolated_tangent(ndim,0.0);
324 Vector<double> interpolated_u(ndim,0.0);
325 Vector<double> mesh_velocity(ndim,0.0);
326 Vector<double> interpolated_duds(ndim,0.0);
327 if(ndim+1 != u_index.size())
329 throw OomphLibError(
"Dimension Incompatibility",
330 OOMPH_CURRENT_FUNCTION,
331 OOMPH_EXCEPTION_LOCATION);
334 for(
unsigned l=0;l<n_node;l++)
336 const double psi = psif(l);
337 const double dpsi = dpsifds(l,0);
338 interpolated_C += this->nodal_value(l,c_index)*psi;
339 interpolated_dCds += this->nodal_value(l,c_index)*dpsi;
340 dCdt += dcdt_surface(l)*psi;
341 for(
unsigned i=0;i<ndim;i++)
343 interpolated_tangent[i] += this->nodal_position(l,i)*dpsi;
344 interpolated_u[i] += this->nodal_value(l,u_index[i])*psi;
345 interpolated_duds[i] += this->nodal_value(l,u_index[i])*dpsi;
348 for(
unsigned j=0;j<ndim;j++)
350 mesh_velocity[j] += this->dnodal_position_dt(l,j)*psi;
355 double u_tangent = 0.0, t_length = 0.0;
356 for(
unsigned i=0;i<ndim;i++)
358 u_tangent += interpolated_u[i]*interpolated_tangent[i];
359 t_length += interpolated_tangent[i]*interpolated_tangent[i];
363 Vector<double> d2xds(2,0.0);
364 for(
unsigned i=0;i<2;i++)
366 d2xds[i] = this->nodal_position(0,i) +
367 this->nodal_position(2,i) - 2.0*this->nodal_position(1,i);
372 for(
unsigned i=0;i<2;i++)
374 k1 += (d2xds[i]/(J_raw*J_raw) - interpolated_tangent[i]*(
375 interpolated_tangent[0]*d2xds[0]
376 + interpolated_tangent[1]*d2xds[1])/(J_raw*J_raw*J_raw*J_raw))*interpolated_n[i];
380 double k2 = - (interpolated_n[0] / r);
383 for(
unsigned l=0;l<n_node;l++)
386 local_eqn = this->nodal_local_eqn(l,c_index);
392 residuals[local_eqn] += dCdt*psif(l)*r*W*J_raw;
396 if(Integrated_curvature)
398 for(
unsigned i=0;i<2;i++)
401 (interpolated_u[i] - mesh_velocity[i])*interpolated_tangent[i];
404 residuals[local_eqn] += tmp*interpolated_dCds*psif(l)*r*W/J_raw;
406 residuals[local_eqn] += interpolated_C*interpolated_u[0]*psif(l)*W*J_raw;
408 residuals[local_eqn] += interpolated_C*
409 (interpolated_duds[0]*interpolated_tangent[0]
410 + interpolated_duds[1]*interpolated_tangent[1])*r*W*psif(l)/J_raw;
416 for(
unsigned i=0;i<2;i++)
418 tmp += -mesh_velocity[i]*interpolated_tangent[i];
420 residuals[local_eqn] += tmp*interpolated_dCds*psif(l)*r*W/J_raw;
422 residuals[local_eqn] -=
423 interpolated_C*(k1 + k2)*psif(l)*r*W*J_raw*(
424 interpolated_u[0]*interpolated_n[0]
425 + interpolated_u[1]*interpolated_n[1]);
427 residuals[local_eqn] -= interpolated_C*(
428 interpolated_tangent[0]*interpolated_u[0] +
429 interpolated_tangent[1]*interpolated_u[1])*dpsifds(l,0)*r*W/J_raw;
433 residuals[local_eqn] += (1.0/Pe_s)*interpolated_dCds*dpsifds(l,0)*r*W/J_raw;
439 for(
unsigned l2=0;l2<n_node;l2++)
442 TimeStepper* time_stepper_pt=this->node_pt(l2)->time_stepper_pt();
445 local_unknown =this->nodal_local_eqn(l2,c_index);
447 if(local_unknown >=0)
449 jacobian(local_eqn,local_unknown) +=
450 time_stepper_pt->weight(1,0)*psif(l2)*psif(l)*r*W*J_raw;
452 if(Integrated_curvature)
454 jacobian(local_eqn,local_unknown) += ((interpolated_u[0] - mesh_velocity[0])*interpolated_tangent[0]
455 + (interpolated_u[1] - mesh_velocity[1])*interpolated_tangent[1])*dpsifds(l2,0)
459 jacobian(local_eqn,local_unknown) += psif(l2)*interpolated_u[0]*psif(l)*W*J_raw;
461 jacobian(local_eqn,local_unknown) += psif(l2)*(interpolated_tangent[0]*interpolated_duds[0]
462 + interpolated_tangent[1]*interpolated_duds[1])*psif(l)*r*W/J_raw;
466 jacobian(local_eqn,local_unknown) -=
467 (mesh_velocity[0]*interpolated_tangent[0] + mesh_velocity[1]*interpolated_tangent[1])*dpsifds(l2,0)*psif(l)*r*W/J_raw;
469 jacobian(local_eqn,local_unknown) -= psif(l2)*(k1 + k2)*psif(l)*r*W*J_raw*(interpolated_u[0]*interpolated_n[0]
470 + interpolated_u[1]*interpolated_n[1]);
472 jacobian(local_eqn,local_unknown) -= psif(l2)*(interpolated_tangent[0]*interpolated_u[0] + interpolated_tangent[1]*
473 interpolated_u[1])*dpsifds(l,0)*r*W/J_raw;
476 jacobian(local_eqn,local_unknown) += (1.0/Pe_s)*dpsifds(l2,0)*dpsifds(l,0)*r*W/J_raw;
482 for(
unsigned i2=0;i2<ndim;i2++)
486 local_unknown = this->nodal_local_eqn(l2,u_index[i2]);
490 if(local_unknown >= 0)
494 if(Integrated_curvature)
496 jacobian(local_eqn,local_unknown) +=
497 interpolated_dCds*psif(l2)*interpolated_tangent[i2]*psif(l)*r*W/J_raw;
501 jacobian(local_eqn,local_unknown) += interpolated_C*psif(l2)*W*J_raw;
506 jacobian(local_eqn,local_unknown) -= interpolated_C*(k1 + k2)*psif(l)*r*W*J_raw*psif(l2)*interpolated_n[i2];
508 jacobian(local_eqn,local_unknown) -= interpolated_C*interpolated_tangent[i2]*psif(l2)*dpsifds(l,0)*r*W/J_raw;
511 jacobian(local_eqn,local_unknown) +=
512 interpolated_C*interpolated_tangent[i2]*dpsifds(l2,0)*psif(l)*r*W/J_raw;
526 DenseMatrix<double> &mass_matrix)
529 this->fill_in_contribution_to_jacobian(residuals,jacobian);
537 (element_pt,face_index)
540 Beta_pt = &Default_Physical_Constant_Value;
541 Peclet_S_pt = &Default_Physical_Constant_Value;
542 Peclet_Strouhal_S_pt = &Default_Physical_Constant_Value;
548 unsigned n_node_face = this->nnode();
551 Vector<unsigned> additional_data_values(n_node_face);
552 for(
unsigned i=0;i<n_node_face;i++) additional_data_values[i] = 1;
554 this->resize_nodes(additional_data_values);
558 C_index = this->node_pt(0)->nvalue()-1;
562 double beta() {
return *Beta_pt;}
579 void output(std::ostream &outfile,
const unsigned &n_plot)
581 outfile.precision(16);
587 outfile <<
"ZONE I=" << n_plot << std::endl;
589 const unsigned n_node = this->nnode();
590 const unsigned dim = this->dim();
593 DShape dpsi(n_node,dim);
596 for(
unsigned l=0;l<n_plot;l++)
598 s[0] = -1.0 + l*2.0/(n_plot-1);
600 this->dshape_local(s,psi,dpsi);
601 Vector<double> interpolated_tangent(2,0.0);
602 for(
unsigned l=0;l<n_node;l++)
604 const double dpsi_ = dpsi(l,0);
605 for(
unsigned i=0;i<2;i++)
607 interpolated_tangent[i] += this->nodal_position(l,i)*dpsi_;
612 double t_vel = (this->interpolated_u(s,0)*interpolated_tangent[0] + this->interpolated_u(s,1)*interpolated_tangent[1])/
613 sqrt(interpolated_tangent[0]*interpolated_tangent[0] + interpolated_tangent[1]*interpolated_tangent[1]);
617 for(
unsigned i=0;i<2;i++) outfile << this->interpolated_x(s,i) <<
" ";
618 for(
unsigned i=0;i<2;i++) outfile << this->interpolated_u(s,i) <<
" ";
620 outfile << 0.0 <<
" ";
622 outfile << interpolated_C(s) <<
" ";
624 outfile << sigma(s) <<
" " << t_vel << std::endl;
626 outfile << std::endl;
634 unsigned n_node = this->nnode();
638 DShape dpsifds(n_node,1);
641 unsigned n_intpt = this->integral_pt()->nweight();
650 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
653 s[0] = this->integral_pt()->knot(ipt,0);
656 double W = this->integral_pt()->weight(ipt);
659 this->dshape_local_at_knot(ipt,psif,dpsifds);
662 Vector<double> interpolated_x(2,0.0);
663 Vector<double> interpolated_t(2,0.0);
664 double interpolated_c = 0.0;
668 for(
unsigned l=0;l<n_node;l++)
670 interpolated_c += this->nodal_value(l,C_index)*psif(l);
672 for(
unsigned i=0;i<2;i++)
674 interpolated_x[i] += this->nodal_position(l,i)*psif(l);
675 interpolated_t[i] += this->nodal_position(l,i)*dpsifds(l,0);
680 double r = interpolated_x[0];
683 double tlength = interpolated_t[0]*interpolated_t[0] +
684 interpolated_t[1]*interpolated_t[1];
687 double J = sqrt(tlength);
689 mass += interpolated_c*r*W*J;
698 template<
class ELEMENT>
712 template <
class ELEMENT>
714 public HorizontalSingleLayerSpineMesh<ELEMENT>
726 TimeStepper* time_stepper_pt=
727 &Mesh::Default_TimeStepper) :
728 HorizontalSingleLayerSpineMesh<ELEMENT>(nx,ny,lx,ly,time_stepper_pt) {}
735 double W = spine_node_pt->fraction();
738 double H = spine_node_pt->h();
741 spine_node_pt->x(0) = 1.0-(1.0-W)*H;
753 template<
class ELEMENT,
class TIMESTEPPER>
773 Bulk_mesh_pt->node_update();
782 const unsigned n_node = Bulk_mesh_pt->nnode();
785 for(
unsigned n=0;n<n_node;n++)
788 for(
unsigned i=0;i<3;i++)
791 Bulk_mesh_pt->node_pt(n)->set_value(i,0.0);
797 assign_initial_values_impulsive();
808 double global_error = 0.0;
811 const unsigned n_node = Bulk_mesh_pt->nnode();
814 for(
unsigned n=0;n<n_node;n++)
817 const unsigned n_dim = 1;
819 double node_position_error = 0.0;
821 for(
unsigned i=0;i<n_dim;i++)
825 Bulk_mesh_pt->node_pt(n)->position_time_stepper_pt()->
826 temporal_error_in_position(Bulk_mesh_pt->node_pt(n),i);
829 node_position_error += error*error;
833 node_position_error /= n_dim;
835 global_error += node_position_error;
839 global_error /= n_node;
842 return sqrt(global_error);
853 void doc_solution(DocInfo &doc_info);
856 void unsteady_run(
const double &t_max,
const double &dt);
865 const unsigned n_interface_element = Interface_mesh_pt->nelement();
868 for(
unsigned e=0;e<n_interface_element;e++)
873 (Interface_mesh_pt->element_pt(e));
887 const unsigned n_spine = Bulk_mesh_pt->nspine();
890 for(
unsigned i=0;i<n_spine;i++)
894 double z_value = Bulk_mesh_pt->boundary_node_pt(1,i)->x(1);
897 Bulk_mesh_pt->spine_pt(i)->height() =
904 Bulk_mesh_pt->node_update();
918 template<
class ELEMENT,
class TIMESTEPPER>
926 add_time_stepper_pt(
new TIMESTEPPER(
true));
933 Interface_mesh_pt =
new Mesh;
942 unsigned n_element = Bulk_mesh_pt->nboundary_element(3);
945 for(
unsigned e=0;e<n_element;e++)
948 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
949 Bulk_mesh_pt->boundary_element_pt(3,e));
952 int face_index = Bulk_mesh_pt->face_index_at_boundary(3,e);
959 Interface_mesh_pt->add_element_pt(interface_element_pt);
966 add_sub_mesh(Bulk_mesh_pt);
967 add_sub_mesh(Interface_mesh_pt);
979 unsigned n_node = this->Bulk_mesh_pt->nnode();
980 for(
unsigned n=0;n<n_node;++n)
982 this->Bulk_mesh_pt->node_pt(n)->pin(2);
989 unsigned n_node = Bulk_mesh_pt->nboundary_node(ibound);
990 for(
unsigned n=0;n<n_node;n++)
992 Bulk_mesh_pt->boundary_node_pt(ibound,n)->set_value(3,1.0);
996 const unsigned n_boundary = Bulk_mesh_pt->nboundary();
999 for(
unsigned b=0;b<n_boundary;b++)
1002 const unsigned n_node = Bulk_mesh_pt->nboundary_node(b);
1005 for(
unsigned n=0;n<n_node;n++)
1008 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(2);
1013 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(0);
1014 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(1);
1019 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(1);
1029 const unsigned n_bulk = Bulk_mesh_pt->nelement();
1032 for(
unsigned e=0;e<n_bulk;e++)
1035 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
1053 Data* external_pressure_data_pt =
new Data(1);
1058 external_pressure_data_pt->pin(0);
1059 external_pressure_data_pt->set_value(0,p_ext);
1062 const unsigned n_interface_element = Interface_mesh_pt->nelement();
1065 for(
unsigned e=0;e<n_interface_element;e++)
1070 (Interface_mesh_pt->element_pt(e));
1090 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
1099 template<
class ELEMENT,
class TIMESTEPPER>
1105 double t= time_pt()->time();
1106 cout <<
"Time is now " << t << std::endl;
1109 Trace_file << time_pt()->time() <<
" " 1110 << Bulk_mesh_pt->spine_pt(0)->height()
1111 <<
" " << this->compute_total_mass() << std::endl;
1117 const unsigned npts = 5;
1128 sprintf(filename,
"%s/int%i.dat",doc_info.directory().c_str(),
1130 some_file.open(filename);
1131 Interface_mesh_pt->output(some_file,npts);
1156 string file_name=
"soln"+StringConversion::to_string(doc_info.number())
1168 template<
class ELEMENT,
class TIMESTEPPER>
1177 deform_free_surface(epsilon);
1183 doc_info.set_directory(
"RESLT");
1186 doc_info.number()=0;
1190 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
1191 Trace_file.open(filename);
1194 Trace_file <<
"time" <<
", " 1195 <<
"edge spine height" <<
", " 1196 <<
"contact angle left" <<
", " 1197 <<
"contact angle right" <<
", " << std::endl;
1203 set_initial_condition();
1206 const unsigned n_timestep = unsigned(t_max/dt);
1211 sprintf(filename,
"%s/soln.pvd",doc_info.directory().c_str());
1216 doc_solution(doc_info);
1219 doc_info.number()++;
1224 for(
unsigned t=1;t<=n_timestep;t++)
1227 cout <<
"\nTimestep " << t <<
" of " << n_timestep << std::endl;
1230 unsteady_newton_solve(dt);
1238 doc_solution(doc_info);
1241 doc_info.number()++;
1263 CommandLineArgs::setup(argc,argv);
1266 double t_max = 1000.0;
1269 const double dt = 0.1;
1272 if(CommandLineArgs::Argc>1)
1278 const unsigned n_r = 10;
1281 const unsigned n_z = 80;
1294 problem(n_r,n_z,l_z);
double Peclet_S
Surface Peclet number.
double global_temporal_error_norm()
double beta()
Return the Elasticity number.
double peclet_strouhal_s()
Return the surface peclect strouhal number.
virtual void spine_node_update(SpineNode *spine_node_pt)
Node update function assumed spines rooted at the wall fixed to be at r=1 and directed inwards to r=0...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Fill in the contribution to the residuals Calculate the contribution to the jacobian.
double Peclet_St_S
Sufrace Peclet number multiplied by Strouhal number.
void add_additional_residual_contributions_interface(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag, const Shape &psif, const DShape &dpsifds, const DShape &dpsifdS, const DShape &dpsifdS_div, const Vector< double > &s, const Vector< double > &interpolated_x, const Vector< double > &interpolated_n, const double &W, const double &J)
Overload the Helper function to calculate the residuals and jacobian entries. This particular functio...
InterfaceProblem(const unsigned &n_r, const unsigned &n_y, const unsigned &n_theta, const double &r_min, const double &r_max, const double &l_y, const double &theta_max)
Problem constructor.
double * Peclet_Strouhal_S_pt
Pointer to the surface Peclect Strouhal number.
void set_external_pressure_data(Data *external_pressure_data_pt)
Set the Data that contains the single pressure value that specifies the "external pressure" for the i...
double * Peclet_S_pt
Pointer to Surface Peclet number.
static double Default_Physical_Constant_Value
Default value of the physical constants.
ofstream Pvd_file
Pvd file – a wrapper for all the different vtu output files plus information about continuous time t...
double dcdt_surface(const unsigned &l) const
The time derivative of the surface concentration.
double ReSt
Womersley = Reynolds times Strouhal.
void output(std::ostream &outfile, const unsigned &n_plot)
double interpolated_C(const Vector< double > &s)
Get the surfactant concentration.
~InterfaceProblem()
Destructor (empty)
double peclet_s()
Return the surface peclect number.
double integrate_c() const
Compute the concentration intergated over the area.
double Re
Reynolds number.
double Epsilon
Free surface cosine deformation parameter.
void actions_before_newton_convergence_check()
void set_initial_condition()
double sigma(const Vector< double > &s)
double ReInvFr
Product of Reynolds and Froude number.
int main(int argc, char *argv[])
Driver code for single fluid axisymmetric horizontal interface problem.
Vector< double > G(3)
Direction of gravity.
MyHorizontalSingleLayerSpineMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass number of elements in x-direction, number of elements in y-direction, radial extent, axial length , and pointer to timestepper (defaults to Steady timestepper)
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
MyHorizontalSingleLayerSpineMesh< ELEMENT > * Bulk_mesh_pt
Access function for the specific mesh.
double *& peclet_s_pt()
Access function for pointer to the surface Peclet number.
void unsteady_run(const unsigned &nstep)
Run an unsteady simulation with specified number of steps.
double Beta
Surface Elasticity number (weak case)
void deform_free_surface(const double &epsilon)
Deform the mesh/free surface to a prescribed function.
double *& beta_pt()
Access function for pointer to the Elasticity number.
double P_ext
External pressure.
void doc_solution(DocInfo &doc_info)
Doc the solution.
double * Beta_pt
Pointer to an Elasticity number.
Mesh * Interface_mesh_pt
Mesh for the free surface (interface) elements.
SpineAxisymmetricMarangoniSurfactantFluidInterfaceElement(FiniteElement *const &element_pt, const int &face_index)
double Ca
Capillary number.
double Alpha
Wavelength of the domain.
double *& peclet_strouhal_s_pt()
Access function for pointer to the surface Peclet x Strouhal number.
double compute_total_mass()
Compute the total mass of the insoluble surfactant.
double *& ca_pt()
Pointer to the Capillary number.