35 #include "navier_stokes.h" 36 #include "fluid_interface.h" 39 #include "meshes/bretherton_spine_mesh.h" 43 using namespace oomph;
80 void inflow(
const Vector<double>& x, Vector<double>& veloc)
83 std::ostringstream error_stream;
84 bool throw_error=
false;
87 error_stream <<
"You must set H_lo_pt\n";
92 error_stream <<
"You must set H_up_pt\n";
97 error_stream <<
"You must set Y_lo_pt\n";
102 error_stream <<
"You must set Y_up_pt\n";
109 throw OomphLibError(error_stream.str(),
110 OOMPH_CURRENT_FUNCTION,
111 OOMPH_EXCEPTION_LOCATION);
117 double h_av=0.5*(*H_lo_pt+*
H_up_pt);
124 double C =6.0*(2.0*h_av+y_lo-y_up)/
125 (y_up*y_up*y_up-y_lo*y_lo*y_lo-h_av*y_up*
126 y_up*y_up+h_av*y_lo*y_lo*y_lo-3.0*y_lo*y_up*y_up+
127 3.0*y_lo*y_lo*y_up+3.0*y_lo*y_up*y_up*h_av-3.0*y_lo*y_lo*y_up*h_av);
133 veloc[0]=-1.0+C*(1.0-h_av)*((y_lo-y)*(y_up-y));
156 template<
class ELEMENT>
164 typedef void (*InflowFctPt)(
const Vector<double>& x, Vector<double>& veloc);
176 const Vector<Data*>& inflow_ext_data,
177 const unsigned& inflow_boundary,
178 InflowFctPt inflow_fct_pt)
181 unsigned n_ext=inflow_ext_data.size();
182 Inflow_ext_data.resize(n_ext);
183 for (
unsigned i=0;i<n_ext;i++)
185 Inflow_ext_data[i]=inflow_ext_data[i];
188 Inflow_boundary=inflow_boundary;
190 Inflow_fct_pt=inflow_fct_pt;
199 ELEMENT::assign_local_eqn_numbers(store_local_dof_pt);
205 unsigned local_eqn_count = this->ndof();
209 unsigned max_nvalue=0;
210 unsigned n_ext=Inflow_ext_data.size();
211 for (
unsigned i=0;i<n_ext;i++)
214 Data* data_pt=Inflow_ext_data[i];
216 unsigned n_val=data_pt->nvalue();
217 if (n_val>max_nvalue) max_nvalue=n_val;
221 Inflow_ext_data_eqn.resize(n_ext,max_nvalue);
224 std::deque<unsigned long> global_eqn_number_queue;
227 for (
unsigned i=0;i<n_ext;i++)
230 Data* data_pt=Inflow_ext_data[i];
233 unsigned n_val=data_pt->nvalue();
234 for (
unsigned ival=0;ival<n_val;ival++)
238 long eqn_number=data_pt->eqn_number(ival);
242 global_eqn_number_queue.push_back(eqn_number);
244 Inflow_ext_data_eqn(i,ival)=local_eqn_count;
250 Inflow_ext_data_eqn(i,ival)=-1;
256 this->add_global_eqn_numbers(global_eqn_number_queue,
257 GeneralisedElement::Dof_pt_deque);
266 DenseMatrix<double>& jacobian)
269 unsigned n_ext=Inflow_ext_data.size();
272 ELEMENT::get_jacobian(residuals,jacobian);
274 if (n_ext==0)
return;
277 Vector<double> residuals_plus(residuals.size());
278 double fd_step=1.0e-8;
281 for (
unsigned i=0;i<n_ext;i++)
284 Data* data_pt=Inflow_ext_data[i];
287 unsigned n_val=data_pt->nvalue();
288 for (
unsigned ival=0;ival<n_val;ival++)
291 int local_eqn=Inflow_ext_data_eqn(i,ival);
297 double *value_pt = data_pt->value_pt(ival);
300 double backup = *value_pt;
303 *value_pt += fd_step;
310 unsigned n_dof = this->ndof();
312 for(
unsigned idof=0;idof<n_dof;idof++) {residuals_plus[idof] = 0.0;}
314 this->get_residuals(residuals_plus);
316 for(
unsigned idof=0;idof<n_dof;idof++)
318 jacobian(idof,local_eqn)=
319 (residuals_plus[idof]-residuals[idof])/fd_step;
348 Vector<double> veloc(2);
349 unsigned n_nod = this->nnode();
350 for (
unsigned j=0;j<n_nod;j++)
352 Node* nod_pt = this->node_pt(j);
354 if(nod_pt->is_on_boundary(Inflow_boundary))
357 for (
unsigned i=0;i<2;i++)
359 if (nod_pt->eqn_number(0)>=0)
361 std::ostringstream error_stream;
363 <<
"We're assigning a Dirichlet condition for the " 365 <<
"velocity, even though it is not pinned!\n" 366 <<
"This can't be right! I'm bailing out..." 369 throw OomphLibError(error_stream.str(),
370 OOMPH_CURRENT_FUNCTION,
371 OOMPH_EXCEPTION_LOCATION);
378 Inflow_fct_pt(x,veloc);
379 nod_pt->set_value(0,veloc[0]);
380 nod_pt->set_value(1,veloc[1]);
412 class FaceGeometry<
BrethertonElement<SpineElement<QCrouzeixRaviartElement<2> > > >:
public virtual QElement<1,3>
424 class FaceGeometry<
BrethertonElement<SpineElement<QTaylorHoodElement<2> > > >:
public virtual QElement<1,3>
437 SpineElement<QCrouzeixRaviartElement<2> > > > >:
public virtual PointElement
450 class FaceGeometry<FaceGeometry<
BrethertonElement<SpineElement<QTaylorHoodElement<2> > > > >:
public virtual PointElement
467 template<
class ELEMENT>
484 Bulk_mesh_pt->node_update();
488 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
492 Vector<double> veloc(2);
495 for (
unsigned inod=0;inod<num_nod;inod++)
498 x[0]=mesh_pt()->boundary_node_pt(ibound,inod)->x(0);
499 x[1]=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
503 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,veloc[0]);
504 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1,veloc[1]);
517 const double &pvalue)
520 dynamic_cast<ELEMENT *
>(Bulk_mesh_pt->element_pt(e))->
521 fix_pressure(l,pvalue);
527 void activate_inflow_dependency();
530 void parameter_study(
const unsigned& nsteps);
533 void doc_solution(DocInfo& doc_info);
545 BrethertonSpineMesh<ELEMENT,SpineLineFluidInterfaceElement<ELEMENT> >*
554 template<
class ELEMENT>
579 GeomObject* lower_wall_pt=
new StraightLine(-1.0);
580 GeomObject* upper_wall_pt=
new StraightLine( 1.0);
592 Bulk_mesh_pt =
new BrethertonSpineMesh<ELEMENT,
593 SpineLineFluidInterfaceElement<ELEMENT> >
594 (nx1,nx2,nx3,nh,nhalf,h,lower_wall_pt,upper_wall_pt,xi0,0.0,xi1,xi2);
597 mesh_pt()=Bulk_mesh_pt;
600 Control_element_pt=Bulk_mesh_pt->control_element_pt();
607 Bulk_mesh_pt->spine_pt(0)->spine_height_pt()->value_pt(0);
610 unsigned last_spine=Bulk_mesh_pt->nfree_surface_spines()-1;
612 Bulk_mesh_pt->spine_pt(last_spine)->spine_height_pt()->value_pt(0);
617 Bulk_mesh_pt->boundary_node_pt(ibound,0)->x_pt(0,1);
620 unsigned nnod=Bulk_mesh_pt->nboundary_node(ibound);
622 Bulk_mesh_pt->boundary_node_pt(ibound,nnod-1)->x_pt(0,1);
625 activate_inflow_dependency();
632 for(
unsigned ibound=0;ibound<=2;ibound++)
634 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
635 for (
unsigned inod=0;inod<num_nod;inod++)
637 mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
638 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
643 for(
unsigned ibound=3;ibound<=5;ibound+=2)
645 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
646 for (
unsigned inod=0;inod<num_nod;inod++)
648 mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
649 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
654 unsigned central_spine=(Bulk_mesh_pt->nfree_surface_spines()-1)/2;
655 Bulk_mesh_pt->spine_pt(central_spine)->spine_height_pt()->pin(0);
659 for (
unsigned ibound=0;ibound<=2;ibound+=2)
661 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
662 for (
unsigned inod=0;inod<num_nod;inod++)
665 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,-1.0);
666 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1, 0.0);
672 for (
unsigned ibound=3;ibound<=5;ibound+=2)
674 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
675 for (
unsigned inod=0;inod<num_nod;inod++)
678 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,-1.0);
679 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1, 0.0);
688 unsigned n_bulk=Bulk_mesh_pt->nbulk();
689 for(
unsigned i=0;i<n_bulk;i++)
692 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->
702 unsigned interface_element_pt_range = Bulk_mesh_pt->ninterface_element();
703 for(
unsigned i=0;i<interface_element_pt_range;i++)
706 SpineLineFluidInterfaceElement<ELEMENT>* el_pt =
707 dynamic_cast<SpineLineFluidInterfaceElement<ELEMENT>*
> 708 (Bulk_mesh_pt->interface_element_pt(i));
716 Bulk_mesh_pt->node_update();
719 cout <<
"Number of unknowns: " << assign_eqn_numbers() << std::endl;
729 template<
class ELEMENT>
734 Vector<Data*> outflow_spines(2);
737 outflow_spines[0]=Bulk_mesh_pt->spine_pt(0)->spine_height_pt();
740 unsigned last_spine=Bulk_mesh_pt->nfree_surface_spines()-1;
741 outflow_spines[1]=Bulk_mesh_pt->spine_pt(last_spine)->spine_height_pt();;
747 unsigned nel=Bulk_mesh_pt->nboundary_element(ibound);
748 for (
unsigned e=0;e<nel;e++)
751 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->
752 boundary_element_pt(ibound,e));
754 el_pt->activate_inflow_dependency_on_external_data(
765 template<
class ELEMENT>
781 unsigned last_spine=Bulk_mesh_pt->nfree_surface_spines()-1;
785 Trace_file <<
" " << Bulk_mesh_pt->spine_pt(0)->height();
786 Trace_file <<
" " << Bulk_mesh_pt->spine_pt(last_spine)->height();
787 Trace_file <<
" " << 1.3375*pow(Global_Physical_Variables::Ca,2.0/3.0);
788 Trace_file <<
" " << -Control_element_pt->interpolated_p_nst(s)*
790 Trace_file <<
" " << 1.0+3.8*pow(Global_Physical_Variables::Ca,2.0/3.0);
791 Trace_file <<
" " << Control_element_pt->interpolated_u_nst(s,0);
792 Trace_file <<
" " << Control_element_pt->interpolated_u_nst(s,1);
793 Trace_file << std::endl;
797 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
799 some_file.open(filename);
800 Bulk_mesh_pt->output(some_file,npts);
805 sprintf(filename,
"%s/boundaries%i.dat",doc_info.directory().c_str(),
807 some_file.open(filename);
808 Bulk_mesh_pt->output_boundaries(some_file);
819 template<
class ELEMENT>
824 Problem::Max_residuals=100.0;
828 doc_info.set_directory(
"RESLT");
834 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
835 Trace_file.open(filename);
837 Trace_file <<
"VARIABLES=\"Ca\",";
838 Trace_file <<
"\"h<sub>bottom</sub>\",\"h<sub>too</sub>\",";
839 Trace_file <<
"\"h<sub>Bretherton</sub>\",\"p<sub>tip</sub>\",";
840 Trace_file <<
"\"p<sub>tip (Bretherton)</sub>\",\"u<sub>stag</sub>\",";
841 Trace_file <<
"\"v<sub>stag</sub>\"";
842 Trace_file <<
"\"<greek>a</greek><sub>bottom</sub>\",";
843 Trace_file <<
"\"<greek>a</greek><sub>top</sub>\"";
844 Trace_file << std::endl;
850 doc_solution(doc_info);
853 for (
unsigned step=1;step<=nsteps;step++)
855 cout << std::endl <<
"STEP " << step << std::endl;
864 cout <<
"Checking max. res for Ca = " 868 DoubleVector residuals;
869 actions_before_newton_solve();
870 actions_before_newton_convergence_check();
871 get_residuals(residuals);
872 double max_res=residuals.max();
878 cout <<
". Too big!" << std::endl;
880 Global_Physical_Variables::Ca *= factor;
882 factor=1.0+(factor-1.0)/1.5;
883 cout <<
"New reduction factor: " << factor << std::endl;
885 Global_Physical_Variables::Ca /= factor;
892 cout <<
". OK" << std::endl << std::endl;
899 cout <<
"Solving for capillary number: " 905 doc_solution(doc_info);
920 int main(
int argc,
char* argv[])
925 CommandLineArgs::setup(argc,argv);
951 if (CommandLineArgs::Argc>1)
double * Y_up_pt
Pointer to y-position at inflow on the upper wall.
BrethertonElement()
Constructor: Call the constructor of the underlying element.
Vector< Data * > Inflow_ext_data
Storage for the external Data that affects the inflow.
BrethertonProblem()
Constructor:
void actions_before_newton_convergence_check()
Spine heights/lengths are unknowns in the problem so their values get corrected during each Newton st...
double * H_up_pt
Pointer to film thickness at outflow on the upper wall.
Vector< double > G(2)
Direction of gravity.
void fix_pressure(const unsigned &e, const unsigned &l, const double &pvalue)
Fix pressure value l in element e to value p_value.
void activate_inflow_dependency()
Activate the dependency of the inflow velocity on the spine heights at the outflow.
void activate_inflow_dependency_on_external_data(const Vector< Data *> &inflow_ext_data, const unsigned &inflow_boundary, InflowFctPt inflow_fct_pt)
Activate the dependency of the "inflow" on the external data. Pass the vector of pointers to the exte...
double ReSt
Womersley = Reynolds times Strouhal.
unsigned Inflow_boundary
Number of the inflow boundary in the global mesh.
void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
void reassign_inflow()
For all nodes that are located on specified boundary re-assign the inflow velocity, using the function pointed to by the function pointer.
int main(int argc, char *argv[])
void inflow(const Vector< double > &x, Vector< double > &veloc)
double Re
Reynolds number.
void actions_before_newton_solve()
Update before solve: empty.
double * Y_lo_pt
Pointer to y-position at inflow on the lower wall.
Namepspace for global parameters.
void actions_after_newton_solve()
Update after solve can remain empty, because the update is performed automatically after every Newton...
double ReInvFr
Product of Reynolds and Froude number.
ELEMENT * Control_element_pt
Pointer to control element.
ofstream Trace_file
Trace file.
void assign_local_eqn_numbers(const bool &store_local_dof_pt)
void doc_solution(DocInfo &doc_info)
Doc the solution.
DenseMatrix< int > Inflow_ext_data_eqn
Storage for the local equation numbers associated the Data values that affect the inflow...
BrethertonSpineMesh< ELEMENT, SpineLineFluidInterfaceElement< ELEMENT > > * Bulk_mesh_pt
Pointer to bulk mesh.
void parameter_study(const unsigned &nsteps)
Run a parameter study; perform specified number of steps.
InflowFctPt Inflow_fct_pt
Function pointer to the global function that specifies the inflow velocity profile on the global mesh...
double Ca
Capillary number.
double * H_lo_pt
Pointer to film thickness at outflow on the lower wall.