39 #include "axisym_navier_stokes.h"
42 #include "fluid_interface.h"
45 #include "constitutive.h"
48 #include "meshes/rectangular_quadmesh.h"
54 using namespace oomph;
87 double Alpha = 0.8537;
141 template<
class ELEMENT>
161 unsigned n_node = this->nnode();
164 const unsigned c_index = C_bulk_index;
176 for(
unsigned l=0;l<n_node;l++)
178 C += this->nodal_value(l,c_index)*psi(l);
188 TimeStepper* time_stepper_pt= this->node_pt(l)->time_stepper_pt();
193 if (time_stepper_pt->type()!=
"Steady")
196 const unsigned c_index = C_bulk_index;
199 const unsigned n_time = time_stepper_pt->ntstorage();
201 for(
unsigned t=0;t<n_time;t++)
203 dcdt += time_stepper_pt->weight(1,t)*this->nodal_value(t,l,c_index);
213 Vector<double> &residuals, DenseMatrix<double> &jacobian,
214 const unsigned &flag,
const Shape &psif,
const DShape &dpsifds,
215 const DShape &dpsifdS,
const DShape &dpsifdS_div,
216 const Vector<double> &s,
217 const Vector<double> &interpolated_x,
const Vector<double> &interpolated_n,
218 const double &W,
const double &J)
223 residuals, jacobian, flag,psif,dpsifds,dpsifdS,dpsifdS_div,
224 s, interpolated_x, interpolated_n, W, J);
227 const double k = this->k();
228 const double alpha = this->alpha();
230 unsigned n_node = this->nnode();
233 int local_eqn = 0, local_unknown = 0;
238 unsigned c_bulk_index = this->C_bulk_index;
242 double interpolated_C = 0.0;
243 double interpolated_C_bulk = 0.0;
246 for(
unsigned l=0;l<n_node;l++)
248 const double psi = psif(l);
249 const double C_ = this->nodal_value(l,this->C_index[l]);
251 interpolated_C += C_*psi;
252 interpolated_C_bulk += this->nodal_value(l,c_bulk_index)*psi;
256 double flux = alpha*(interpolated_C_bulk - interpolated_C);
259 for(
unsigned l=0;l<n_node;l++)
264 local_eqn = this->nodal_local_eqn(l,c_bulk_index);
270 residuals[local_eqn] -= k*flux*psif(l)*W*J;
274 for(
unsigned l2=0;l2<n_node;l2++)
276 local_unknown = this->nodal_local_eqn(l2,this->C_index[l2]);
277 if(local_unknown >= 0)
279 jacobian(local_eqn,local_unknown) += k*alpha*psif(l2)*psif(l)*W*J;
282 local_unknown = this->nodal_local_eqn(l2,c_bulk_index);
283 if(local_unknown >= 0)
285 jacobian(local_eqn,local_unknown) -= k*alpha*psif(l2)*psif(l)*W*J;
294 local_eqn = this->nodal_local_eqn(l,this->C_index[l]);
300 residuals[local_eqn] -= flux*psif(l)*W*J;
304 for(
unsigned l2=0;l2<n_node;l2++)
306 local_unknown = this->nodal_local_eqn(l2,this->C_index[l2]);
307 if(local_unknown >= 0)
309 jacobian(local_eqn,local_unknown) += alpha*psif(l2)*psif(l)*W*J;
312 local_unknown = this->nodal_local_eqn(l2,c_bulk_index);
313 if(local_unknown >= 0)
315 jacobian(local_eqn,local_unknown) -= alpha*psif(l2)*psif(l)*W*J;
329 FiniteElement*
const &element_pt,
const int &face_index) :
331 (element_pt,face_index)
334 Alpha_pt = &this->Default_Physical_Constant_Value;
335 K_pt = &this->Default_Physical_Constant_Value;
346 double k() {
return *K_pt;}
355 void output(std::ostream &outfile,
const unsigned &n_plot)
357 outfile.precision(16);
363 outfile <<
"ZONE I=" << n_plot << std::endl;
365 const unsigned n_node = this->nnode();
366 const unsigned dim = this->dim();
369 DShape dpsi(n_node,dim);
372 for(
unsigned l=0;l<n_plot;l++)
374 s[0] = -1.0 + l*2.0/(n_plot-1);
376 this->dshape_local(s,psi,dpsi);
377 Vector<double> interpolated_tangent(2,0.0);
378 for(
unsigned l=0;l<n_node;l++)
380 const double dpsi_ = dpsi(l,0);
381 for(
unsigned i=0;i<2;i++)
383 interpolated_tangent[i] += this->nodal_position(l,i)*dpsi_;
388 double t_vel = (this->interpolated_u(s,0)*interpolated_tangent[0] + this->interpolated_u(s,1)*interpolated_tangent[1])/
389 sqrt(interpolated_tangent[0]*interpolated_tangent[0] + interpolated_tangent[1]*interpolated_tangent[1]);
393 for(
unsigned i=0;i<2;i++) outfile << this->interpolated_x(s,i) <<
" ";
394 for(
unsigned i=0;i<2;i++) outfile << this->interpolated_u(s,i) <<
" ";
396 outfile << 0.0 <<
" ";
398 outfile << this->interpolated_C(s) <<
" ";
399 outfile << interpolated_C_bulk(s) <<
" ";
401 outfile << this->sigma(s) <<
" " << t_vel << std::endl;
403 outfile << std::endl;
412 template<
class ELEMENT,
class TIMESTEPPER>
432 const unsigned n_node = Bulk_mesh_pt->nnode();
435 for(
unsigned n=0;n<n_node;n++)
438 for(
unsigned i=0;i<3;i++)
441 Bulk_mesh_pt->node_pt(n)->set_value(i,0.0);
444 Bulk_mesh_pt->node_pt(n)->set_value(3,1.0);
449 assign_initial_values_impulsive();
460 double global_error = 0.0;
463 const unsigned n_node = Bulk_mesh_pt->nnode();
466 for(
unsigned n=0;n<n_node;n++)
469 const unsigned n_dim = 1;
471 double node_position_error = 0.0;
473 for(
unsigned i=0;i<n_dim;i++)
477 Bulk_mesh_pt->node_pt(n)->position_time_stepper_pt()->
478 temporal_error_in_position(Bulk_mesh_pt->node_pt(n),i);
481 node_position_error += error*error;
485 node_position_error /= n_dim;
487 global_error += node_position_error;
491 global_error /= n_node;
494 return sqrt(global_error);
502 Mesh* Interface_mesh_pt;
508 Node* Document_node_pt;
523 const unsigned n_interface_element = Interface_mesh_pt->nelement();
526 for(
unsigned e=0;e<n_interface_element;e++)
531 (Interface_mesh_pt->element_pt(e));
545 const unsigned n_node = Bulk_mesh_pt->nnode();
546 for(
unsigned n=0;n<n_node;n++)
549 double r = Bulk_mesh_pt->node_pt(n)->x(0);
551 double z_value = Bulk_mesh_pt->node_pt(n)->x(1);
559 Bulk_mesh_pt->node_pt(n)->x(0) = 1.0 - (1.0-r)*thickness;
563 Bulk_mesh_pt->set_lagrangian_nodal_coordinates();
576 template<
class ELEMENT,
class TIMESTEPPER>
584 add_time_stepper_pt(
new TIMESTEPPER(
true));
588 Bulk_mesh_pt =
new ElasticRectangularQuadMesh<ELEMENT>(n_r,n_z,1.0,l_z,time_stepper_pt());
591 Interface_mesh_pt =
new Mesh;
600 unsigned n_element = Bulk_mesh_pt->nboundary_element(3);
603 for(
unsigned e=0;e<n_element;e++)
606 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
607 Bulk_mesh_pt->boundary_element_pt(3,e));
610 int face_index = Bulk_mesh_pt->face_index_at_boundary(3,e);
617 Interface_mesh_pt->add_element_pt(interface_element_pt);
624 Document_node_pt = Bulk_mesh_pt->node_pt(0);
627 add_sub_mesh(Bulk_mesh_pt);
628 add_sub_mesh(Interface_mesh_pt);
642 unsigned n_node = this->Bulk_mesh_pt->nnode();
643 for(
unsigned n=0;n<n_node;++n)
645 this->Bulk_mesh_pt->node_pt(n)->pin(2);
646 this->Bulk_mesh_pt->node_pt(n)->pin_position(1);
653 unsigned n_node = Bulk_mesh_pt->nboundary_node(ibound);
654 for(
unsigned n=0;n<n_node;n++)
656 Bulk_mesh_pt->boundary_node_pt(ibound,n)->set_value(4,1.0);
660 const unsigned n_boundary = Bulk_mesh_pt->nboundary();
663 for(
unsigned b=0;b<n_boundary;b++)
666 const unsigned n_node = Bulk_mesh_pt->nboundary_node(b);
669 for(
unsigned n=0;n<n_node;n++)
672 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(2);
677 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(0);
678 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(1);
679 Bulk_mesh_pt->boundary_node_pt(b,n)->pin_position(0);
684 Bulk_mesh_pt->boundary_node_pt(b,n)->pin(1);
695 const unsigned n_bulk = Bulk_mesh_pt->nelement();
698 for(
unsigned e=0;e<n_bulk;e++)
701 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
717 el_pt->constitutive_law_pt() = Constitutive_law_pt;
728 Data* external_pressure_data_pt =
new Data(1);
733 external_pressure_data_pt->pin(0);
734 external_pressure_data_pt->set_value(0,p_ext);
737 const unsigned n_interface_element = Interface_mesh_pt->nelement();
740 for(
unsigned e=0;e<n_interface_element;e++)
745 (Interface_mesh_pt->element_pt(e));
771 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
780 template<
class ELEMENT,
class TIMESTEPPER>
786 double t= time_pt()->time();
787 cout <<
"Time is now " << t << std::endl;
790 Trace_file << time_pt()->time() <<
" "
791 << Document_node_pt->x(0)
792 <<
" " << this->compute_total_mass() << std::endl;
798 const unsigned npts = 5;
809 sprintf(filename,
"%s/int%i.dat",doc_info.directory().c_str(),
811 some_file.open(filename);
812 Interface_mesh_pt->output(some_file,npts);
849 template<
class ELEMENT,
class TIMESTEPPER>
858 deform_free_surface(epsilon);
864 doc_info.set_directory(
"RESLT");
871 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
872 Trace_file.open(filename);
875 Trace_file <<
"time" <<
", "
876 <<
"edge spine height" <<
", "
877 <<
"mass " <<
", " << std::endl;
883 set_initial_condition();
886 const unsigned n_timestep = unsigned(t_max/dt);
896 doc_solution(doc_info);
904 for(
unsigned t=1;t<=n_timestep;t++)
907 cout <<
"\nTimestep " << t <<
" of " << n_timestep << std::endl;
910 unsteady_newton_solve(dt);
918 doc_solution(doc_info);
924 Bulk_mesh_pt->set_lagrangian_nodal_coordinates();
943 int main(
int argc,
char* argv[])
947 CommandLineArgs::setup(argc,argv);
950 double t_max = 1000.0;
953 const double dt = 0.1;
956 if(CommandLineArgs::Argc>1)
962 const unsigned n_r = 10;
965 const unsigned n_z = 80;
978 problem(n_r,n_z,l_z);
Interface class to handle the mass transport between bulk and surface as well as the surfactant trans...
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...
unsigned C_bulk_index
Storage for the index at which the bulk concentration is stored.
ElasticAxisymmetricSolubleSurfactantTransportInterfaceElement(FiniteElement *const &element_pt, const int &face_index)
Constructor that passes the bulk element and face index down to the underlying.
void output(std::ostream &outfile, const unsigned &n_plot)
Overload the output function.
double *& k_pt()
Access function for pointer to solubility number.
double *& alpha_pt()
Access function for pointer to adsorption number.
double * K_pt
Pointer to solubility number.
double alpha()
Return the adsorption number.
double * Alpha_pt
Pointer to adsorption number.
double dc_bulk_dt_surface(const unsigned &l) const
The time derivative of the bulk surface concentration.
double k()
Return the solubility nubmer.
double interpolated_C_bulk(const Vector< double > &s)
Get the bulk surfactant concentration.
Single fluid interface problem including transport of an insoluble surfactant.
void set_initial_condition()
Set initial conditions: Set all nodal velocities to zero and initialise the previous velocities to co...
void unsteady_run(const unsigned &nstep)
Run an unsteady simulation with specified number of steps.
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)
Constructor: Pass number of elements in x and y directions. Also lengths of the domain in x- and y-di...
void deform_free_surface(const double &epsilon)
Deform the mesh/free surface to a prescribed function.
void doc_solution(DocInfo &doc_info)
Doc the solution.
ConstitutiveLaw * Constitutive_law_pt
Pointer to the constitutive law.
double global_temporal_error_norm()
The global temporal error norm, based on the movement of the nodes in the radial direction only (beca...
~InterfaceProblem()
Destructor (empty)
double compute_total_mass()
Compute the total mass of the insoluble surfactant.
void unsteady_run(const double &t_max, const double &dt)
Do unsteady run up to maximum time t_max with given timestep dt.
InterfaceProblem(const unsigned &n_r, const unsigned &n_z, const double &l_z)
Constructor: Pass the number of elements in radial and axial directions and the length of the domain ...
ElasticRectangularQuadMesh< ELEMENT > * Bulk_mesh_pt
Access function for the specific mesh.
Specialise to the Axisymmetric geometry.
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)
Helper function to calculate the additional contributions to be added at each integration point....
double *& ca_pt()
Pointer to the Capillary 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()
Access function for pointer to the surface Peclet number.
double *& beta_pt()
Access function for pointer to the Elasticity number.
double integrate_c()
Compute the concentration intergated over the surface area.
double *& peclet_strouhal_s_pt()
Access function for pointer to the surface Peclet x Strouhal number.
Namepspace for global parameters, chosen from Campana et al. as in the axisymmetric problem.
double Alpha_absorption
Alpha for absorption kinetics.
double P_ext
External pressure.
double ReSt
Womersley = Reynolds times Strouhal.
double Epsilon
Free surface cosine deformation parameter.
double Beta
Surface Elasticity number (weak case)
double Nu
Pseudo-solid Poisson ratio.
ofstream Pvd_file
Pvd file – a wrapper for all the different vtu output files plus information about continuous time to...
double Pe_reference_scale
double Ca
Capillary number.
double Peclet_S
Surface Peclet number.
double K
K parameter that describes solubility number.
double Alpha
Wavelength of the domain.
double ReInvFr
Product of Reynolds and Froude number.
double Re
Reynolds number.
double Peclet_St_S
Sufrace Peclet number multiplied by Strouhal number.
Vector< double > G(3)
Direction of gravity.
int main(int argc, char *argv[])
//////////////////////////////////////////////////////////////////// ////////////////////////////////...